summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore50
-rw-r--r--.gitlab-ci.yml3
-rw-r--r--.travis.yml4
-rw-r--r--ChangeLog1528
-rw-r--r--Doxyfile.in3
-rw-r--r--Makefile.am28
-rw-r--r--README4
-rw-r--r--ReleaseNotes1013
-rw-r--r--acinclude.m44
-rw-r--r--changes/40241_v24
-rw-r--r--changes/autoconf-2.703
-rw-r--r--changes/bug160164
-rw-r--r--changes/bug248576
-rw-r--r--changes/bug273156
-rw-r--r--changes/bug301875
-rw-r--r--changes/bug310363
-rw-r--r--changes/bug325884
-rw-r--r--changes/bug326663
-rw-r--r--changes/bug327094
-rw-r--r--changes/bug328805
-rw-r--r--changes/bug331194
-rw-r--r--changes/bug331313
-rw-r--r--changes/bug332844
-rw-r--r--changes/bug332853
-rw-r--r--changes/bug335313
-rw-r--r--changes/bug337817
-rw-r--r--changes/bug338999
-rw-r--r--changes/bug339003
-rw-r--r--changes/bug339175
-rw-r--r--changes/bug339774
-rw-r--r--changes/bug340843
-rw-r--r--changes/bug340863
-rw-r--r--changes/bug341304
-rw-r--r--changes/bug342334
-rw-r--r--changes/bug342993
-rw-r--r--changes/bug343035
-rw-r--r--changes/bug344005
-rw-r--r--changes/bug400013
-rw-r--r--changes/bug400154
-rw-r--r--changes/bug400175
-rw-r--r--changes/bug400209
-rw-r--r--changes/bug400283
-rw-r--r--changes/bug400724
-rw-r--r--changes/bug400765
-rw-r--r--changes/bug400806
-rw-r--r--changes/bug400835
-rw-r--r--changes/bug400954
-rw-r--r--changes/bug400994
-rw-r--r--changes/bug401053
-rw-r--r--changes/bug401133
-rw-r--r--changes/bug401175
-rw-r--r--changes/bug401294
-rw-r--r--changes/bug401723
-rw-r--r--changes/bug401773
-rw-r--r--changes/bug401875
-rw-r--r--changes/bug402383
-rw-r--r--changes/bug40256_0453
-rw-r--r--changes/bug402816
-rw-r--r--changes/bug40285_0454
-rw-r--r--changes/bug402874
-rw-r--r--changes/bug402983
-rw-r--r--changes/bug403155
-rw-r--r--changes/bug403184
-rw-r--r--changes/bug46316
-rw-r--r--changes/doc334173
-rw-r--r--changes/doc341336
-rw-r--r--changes/parallel_unit_test4
-rw-r--r--changes/ticket188883
-rw-r--r--changes/ticket224733
-rw-r--r--changes/ticket243086
-rw-r--r--changes/ticket248444
-rw-r--r--changes/ticket255286
-rw-r--r--changes/ticket282084
-rw-r--r--changes/ticket289923
-rw-r--r--changes/ticket315763
-rw-r--r--changes/ticket316344
-rw-r--r--changes/ticket318124
-rw-r--r--changes/ticket3208813
-rw-r--r--changes/ticket321434
-rw-r--r--changes/ticket321783
-rw-r--r--changes/ticket325423
-rw-r--r--changes/ticket326225
-rw-r--r--changes/ticket326967
-rw-r--r--changes/ticket327204
-rw-r--r--changes/ticket327923
-rw-r--r--changes/ticket328736
-rw-r--r--changes/ticket328884
-rw-r--r--changes/ticket329056
-rw-r--r--changes/ticket329943
-rw-r--r--changes/ticket330143
-rw-r--r--changes/ticket331925
-rw-r--r--changes/ticket331944
-rw-r--r--changes/ticket331954
-rw-r--r--changes/ticket332755
-rw-r--r--changes/ticket332804
-rw-r--r--changes/ticket333003
-rw-r--r--changes/ticket333034
-rw-r--r--changes/ticket3331615
-rw-r--r--changes/ticket333345
-rw-r--r--changes/ticket333393
-rw-r--r--changes/ticket333463
-rw-r--r--changes/ticket333494
-rw-r--r--changes/ticket333663
-rw-r--r--changes/ticket333683
-rw-r--r--changes/ticket333694
-rw-r--r--changes/ticket333703
-rw-r--r--changes/ticket334003
-rw-r--r--changes/ticket334364
-rw-r--r--changes/ticket334513
-rw-r--r--changes/ticket334584
-rw-r--r--changes/ticket336245
-rw-r--r--changes/ticket336336
-rw-r--r--changes/ticket336424
-rw-r--r--changes/ticket336794
-rw-r--r--changes/ticket337477
-rw-r--r--changes/ticket337783
-rw-r--r--changes/ticket337793
-rw-r--r--changes/ticket337884
-rw-r--r--changes/ticket337894
-rw-r--r--changes/ticket337967
-rw-r--r--changes/ticket3381712
-rw-r--r--changes/ticket338734
-rw-r--r--changes/ticket338806
-rw-r--r--changes/ticket339014
-rw-r--r--changes/ticket339565
-rw-r--r--changes/ticket340873
-rw-r--r--changes/ticket342113
-rw-r--r--changes/ticket34255_0433
-rw-r--r--changes/ticket343826
-rw-r--r--changes/ticket400033
-rw-r--r--changes/ticket400053
-rw-r--r--changes/ticket400263
-rw-r--r--changes/ticket400307
-rw-r--r--changes/ticket400355
-rw-r--r--changes/ticket400615
-rw-r--r--changes/ticket400717
-rw-r--r--changes/ticket400733
-rw-r--r--changes/ticket400816
-rw-r--r--changes/ticket400894
-rw-r--r--changes/ticket401066
-rw-r--r--changes/ticket401096
-rw-r--r--changes/ticket401117
-rw-r--r--changes/ticket401254
-rw-r--r--changes/ticket401264
-rw-r--r--changes/ticket401335
-rw-r--r--changes/ticket401353
-rw-r--r--changes/ticket401423
-rw-r--r--changes/ticket401627
-rw-r--r--changes/ticket401646
-rw-r--r--changes/ticket401744
-rw-r--r--changes/ticket401834
-rw-r--r--changes/ticket401884
-rw-r--r--changes/ticket401955
-rw-r--r--changes/ticket402013
-rw-r--r--changes/ticket402055
-rw-r--r--changes/ticket402086
-rw-r--r--changes/ticket40221_0456
-rw-r--r--changes/ticket402265
-rw-r--r--changes/ticket402314
-rw-r--r--changes/ticket402434
-rw-r--r--changes/ticket402454
-rw-r--r--changes/ticket402544
-rw-r--r--changes/ticket402573
-rw-r--r--changes/ticket402794
-rw-r--r--changes/ticket402896
-rw-r--r--changes/ticket402953
-rw-r--r--changes/ticket403008
-rw-r--r--changes/ticket403343
-rw-r--r--changes/ticket403563
-rw-r--r--changes/ticket403605
-rw-r--r--changes/ticket403694
-rw-r--r--changes/ticket403733
-rw-r--r--changes/ticket61983
-rw-r--r--configure.ac219
-rw-r--r--contrib/README2
-rw-r--r--contrib/dist/tor.service.in35
-rw-r--r--contrib/include.am1
-rwxr-xr-xcontrib/or-tools/exitlist2
-rw-r--r--contrib/win32build/tor-mingw.nsi.in2
-rw-r--r--doc/HACKING/CircuitPaddingDevelopment.md16
-rw-r--r--doc/HACKING/CircuitPaddingQuickStart.md56
-rw-r--r--doc/HACKING/CodeStructure.md123
-rw-r--r--doc/HACKING/CodingStandards.md129
-rw-r--r--doc/HACKING/CodingStandardsRust.md262
-rw-r--r--doc/HACKING/Fuzzing.md40
-rw-r--r--doc/HACKING/GettingStarted.md19
-rw-r--r--doc/HACKING/GettingStartedRust.md42
-rw-r--r--doc/HACKING/HelpfulTools.md130
-rw-r--r--doc/HACKING/Module.md6
-rw-r--r--doc/HACKING/README.1st.md4
-rw-r--r--doc/HACKING/ReleaseSeriesLifecycle.md2
-rw-r--r--doc/HACKING/ReleasingTor.md90
-rw-r--r--doc/HACKING/Tracing.md91
-rw-r--r--doc/HACKING/WritingTests.md160
-rw-r--r--doc/HACKING/android/Simpleperf.md8
-rw-r--r--doc/HACKING/tracing/EventsCircuit.md139
-rw-r--r--doc/HACKING/tracing/README.md163
-rw-r--r--doc/TUNING17
-rw-r--r--doc/include.am48
-rw-r--r--doc/man/tor-gencert.1.txt (renamed from doc/tor-gencert.1.txt)7
-rw-r--r--doc/man/tor-print-ed-signing-cert.1.txt (renamed from doc/tor-print-ed-signing-cert.1.txt)4
-rw-r--r--doc/man/tor-resolve.1.txt (renamed from doc/tor-resolve.1.txt)4
-rw-r--r--doc/man/tor.1.txt (renamed from doc/tor.1.txt)192
-rw-r--r--doc/man/torify.1.txt (renamed from doc/torify.1.txt)4
-rw-r--r--doc/state-contents.txt225
-rw-r--r--doc/ticket401363
-rw-r--r--m4/pc_from_ucontext.m42
-rw-r--r--m4/pkg.m42
-rwxr-xr-xscripts/build/combine_libs35
-rwxr-xr-xscripts/ci/ci-driver.sh2
-rwxr-xr-xscripts/codegen/fuzzing_include_am.py9
-rw-r--r--scripts/codegen/makedesc.py115
-rwxr-xr-xscripts/git/git-install-tools.sh6
-rwxr-xr-xscripts/git/git-list-tor-branches.sh9
-rwxr-xr-xscripts/git/git-pull-all.sh16
-rwxr-xr-xscripts/git/git-resquash.sh46
-rwxr-xr-xscripts/git/git-setup-dirs.sh31
-rwxr-xr-xscripts/git/pre-commit.git-hook26
-rwxr-xr-xscripts/git/pre-push.git-hook1
-rwxr-xr-xscripts/maint/annotate_ifdef_directives.py2
-rw-r--r--scripts/maint/checkOptionDocs.pl.in2
-rwxr-xr-xscripts/maint/clang-format.sh41
-rwxr-xr-xscripts/maint/code-format.sh232
-rwxr-xr-xscripts/maint/codetool.py2
-rw-r--r--scripts/maint/practracker/.enable_practracker_in_hooks1
-rw-r--r--scripts/maint/practracker/exceptions.txt37
-rwxr-xr-xscripts/maint/rename_c_identifier.py4
-rw-r--r--src/app/app.md5
-rw-r--r--src/app/config/app_config.md3
-rw-r--r--src/app/config/config.c438
-rw-r--r--src/app/config/config.h15
-rw-r--r--src/app/config/or_options_st.h72
-rw-r--r--src/app/config/or_state_st.h18
-rw-r--r--src/app/config/resolve_addr.c1029
-rw-r--r--src/app/config/resolve_addr.h51
-rw-r--r--src/app/config/statefile.c91
-rw-r--r--src/app/config/statefile.h1
-rw-r--r--src/app/config/testnet.inc3
-rw-r--r--src/app/include.am18
-rw-r--r--src/app/main/include.am2
-rw-r--r--src/app/main/main.c50
-rw-r--r--src/app/main/risky_options.c35
-rw-r--r--src/app/main/risky_options.h17
-rw-r--r--src/app/main/shutdown.c2
-rw-r--r--src/app/main/subsysmgr.c2
-rw-r--r--src/app/main/subsystem_list.c7
-rw-r--r--src/config/torrc.minimal.in-staging2
-rw-r--r--src/config/torrc.sample.in15
-rw-r--r--src/core/crypto/onion_crypto.c2
-rw-r--r--src/core/mainloop/connection.c407
-rw-r--r--src/core/mainloop/connection.h11
-rw-r--r--src/core/mainloop/cpuworker.c2
-rw-r--r--src/core/mainloop/mainloop.c23
-rw-r--r--src/core/mainloop/netstatus.c2
-rw-r--r--src/core/mainloop/periodic.c2
-rw-r--r--src/core/or/channel.c101
-rw-r--r--src/core/or/channel.h36
-rw-r--r--src/core/or/channelpadding.c6
-rw-r--r--src/core/or/channelpadding.h3
-rw-r--r--src/core/or/channeltls.c397
-rw-r--r--src/core/or/channeltls.h4
-rw-r--r--src/core/or/circuit_st.h6
-rw-r--r--src/core/or/circuitbuild.c502
-rw-r--r--src/core/or/circuitbuild.h27
-rw-r--r--src/core/or/circuitlist.c27
-rw-r--r--src/core/or/circuitlist.h7
-rw-r--r--src/core/or/circuitmux.h2
-rw-r--r--src/core/or/circuitpadding.c163
-rw-r--r--src/core/or/circuitpadding.h27
-rw-r--r--src/core/or/circuitpadding_machines.c27
-rw-r--r--src/core/or/circuitstats.c67
-rw-r--r--src/core/or/circuitstats.h6
-rw-r--r--src/core/or/circuituse.c91
-rw-r--r--src/core/or/circuituse.h16
-rw-r--r--src/core/or/command.c12
-rw-r--r--src/core/or/connection_edge.c136
-rw-r--r--src/core/or/connection_edge.h6
-rw-r--r--src/core/or/connection_or.c206
-rw-r--r--src/core/or/connection_or.h7
-rw-r--r--src/core/or/connection_st.h57
-rw-r--r--src/core/or/cpath_build_state_st.h2
-rw-r--r--src/core/or/crypt_path.c2
-rw-r--r--src/core/or/dos.c12
-rw-r--r--src/core/or/extend_info_st.h16
-rw-r--r--src/core/or/extendinfo.c330
-rw-r--r--src/core/or/extendinfo.h40
-rw-r--r--src/core/or/include.am10
-rw-r--r--src/core/or/lttng_circuit.inc322
-rw-r--r--src/core/or/onion.h5
-rw-r--r--src/core/or/or.h21
-rw-r--r--src/core/or/or_connection_st.h24
-rw-r--r--src/core/or/origin_circuit_st.h14
-rw-r--r--src/core/or/policies.c300
-rw-r--r--src/core/or/policies.h35
-rw-r--r--src/core/or/port_cfg_st.h2
-rw-r--r--src/core/or/protover.c576
-rw-r--r--src/core/or/protover.h38
-rw-r--r--src/core/or/protover_rust.c2
-rw-r--r--src/core/or/relay.c9
-rw-r--r--src/core/or/scheduler.c2
-rw-r--r--src/core/or/scheduler_kist.c7
-rw-r--r--src/core/or/sendme.c8
-rw-r--r--src/core/or/server_port_cfg_st.h2
-rw-r--r--src/core/or/status.c41
-rw-r--r--src/core/or/status.h1
-rw-r--r--src/core/or/trace_probes_circuit.c30
-rw-r--r--src/core/or/trace_probes_circuit.h22
-rw-r--r--src/core/or/versions.c59
-rw-r--r--src/core/proto/proto_socks.c6
-rw-r--r--src/core/stA1RajU0
-rw-r--r--src/core/stiysZNDbin19083264 -> 0 bytes
-rw-r--r--src/ext/README79
-rw-r--r--src/ext/curve25519_donna/README2
-rw-r--r--src/ext/ed25519/donna/README.md10
-rw-r--r--src/ext/ed25519/donna/ed25519_tor.c1
-rw-r--r--src/ext/ed25519/donna/fuzz/build-nix.php2
-rw-r--r--src/ext/ed25519/donna/test-internals.c2
-rw-r--r--src/ext/ext.md88
-rw-r--r--src/ext/include.am2
-rw-r--r--src/feature/client/addressmap.c4
-rw-r--r--src/feature/client/bridges.c160
-rw-r--r--src/feature/client/bridges.h2
-rw-r--r--src/feature/client/circpathbias.c2
-rw-r--r--src/feature/client/entrynodes.c14
-rw-r--r--src/feature/client/transports.c121
-rw-r--r--src/feature/client/transports.h3
-rw-r--r--src/feature/control/control.c22
-rw-r--r--src/feature/control/control.h1
-rw-r--r--src/feature/control/control_bootstrap.c16
-rw-r--r--src/feature/control/control_cmd.c37
-rw-r--r--src/feature/control/control_events.c86
-rw-r--r--src/feature/control/control_events.h9
-rw-r--r--src/feature/control/control_fmt.c2
-rw-r--r--src/feature/control/control_getinfo.c98
-rw-r--r--src/feature/control/control_getinfo.h4
-rw-r--r--src/feature/control/fmt_serverstatus.c103
-rw-r--r--src/feature/control/fmt_serverstatus.h18
-rw-r--r--src/feature/control/getinfo_geoip.c2
-rw-r--r--src/feature/control/include.am2
-rw-r--r--src/feature/dirauth/dirauth_config.c4
-rw-r--r--src/feature/dirauth/dirauth_options.inc7
-rw-r--r--src/feature/dirauth/dirvote.c255
-rw-r--r--src/feature/dirauth/dirvote.h27
-rw-r--r--src/feature/dirauth/keypin.c4
-rw-r--r--src/feature/dirauth/process_descs.c53
-rw-r--r--src/feature/dirauth/reachability.c28
-rw-r--r--src/feature/dirauth/shared_random.c6
-rw-r--r--src/feature/dirauth/shared_random_state.c2
-rw-r--r--src/feature/dirauth/vote_microdesc_hash_st.h2
-rw-r--r--src/feature/dirauth/voteflags.c6
-rw-r--r--src/feature/dirauth/voting_schedule.h2
-rw-r--r--src/feature/dircache/consdiffmgr.c12
-rw-r--r--src/feature/dircache/dircache.c35
-rw-r--r--src/feature/dirclient/dir_server_st.h6
-rw-r--r--src/feature/dirclient/dirclient.c272
-rw-r--r--src/feature/dirclient/dirclient_modes.c4
-rw-r--r--src/feature/dircommon/consdiff.c4
-rw-r--r--src/feature/dircommon/directory.c30
-rw-r--r--src/feature/dircommon/directory.h1
-rw-r--r--src/feature/dirparse/authcert_parse.c4
-rw-r--r--src/feature/dirparse/microdesc_parse.c2
-rw-r--r--src/feature/dirparse/ns_parse.c67
-rw-r--r--src/feature/dirparse/routerparse.c50
-rw-r--r--src/feature/dirparse/sigcommon.c6
-rw-r--r--src/feature/dirparse/sigcommon.h12
-rw-r--r--src/feature/feature.md23
-rw-r--r--src/feature/hibernate/hibernate.h2
-rw-r--r--src/feature/hs/hs_cache.c65
-rw-r--r--src/feature/hs/hs_cell.c4
-rw-r--r--src/feature/hs/hs_cell.h2
-rw-r--r--src/feature/hs/hs_circuit.c13
-rw-r--r--src/feature/hs/hs_circuit.h2
-rw-r--r--src/feature/hs/hs_circuitmap.c2
-rw-r--r--src/feature/hs/hs_client.c11
-rw-r--r--src/feature/hs/hs_client.h8
-rw-r--r--src/feature/hs/hs_common.c19
-rw-r--r--src/feature/hs/hs_common.h2
-rw-r--r--src/feature/hs/hs_config.c4
-rw-r--r--src/feature/hs/hs_config.h2
-rw-r--r--src/feature/hs/hs_descriptor.c19
-rw-r--r--src/feature/hs/hs_ident.c2
-rw-r--r--src/feature/hs/hs_ident.h2
-rw-r--r--src/feature/hs/hs_metrics.c171
-rw-r--r--src/feature/hs/hs_metrics.h70
-rw-r--r--src/feature/hs/hs_metrics_entry.c65
-rw-r--r--src/feature/hs/hs_metrics_entry.h51
-rw-r--r--src/feature/hs/hs_ob.c15
-rw-r--r--src/feature/hs/hs_service.c119
-rw-r--r--src/feature/hs/hs_service.h25
-rw-r--r--src/feature/hs/hs_sys.c36
-rw-r--r--src/feature/hs/hs_sys.h22
-rw-r--r--src/feature/hs/include.am10
-rw-r--r--src/feature/keymgt/loadkey.c6
-rw-r--r--src/feature/metrics/.may_include1
-rw-r--r--src/feature/metrics/include.am10
-rw-r--r--src/feature/metrics/metrics.c280
-rw-r--r--src/feature/metrics/metrics.h37
-rw-r--r--src/feature/metrics/metrics_sys.c37
-rw-r--r--src/feature/metrics/metrics_sys.h22
-rw-r--r--src/feature/nodelist/authcert.c26
-rw-r--r--src/feature/nodelist/authcert.h2
-rw-r--r--src/feature/nodelist/authority_cert_st.h6
-rw-r--r--src/feature/nodelist/describe.c114
-rw-r--r--src/feature/nodelist/describe.h18
-rw-r--r--src/feature/nodelist/dirlist.c110
-rw-r--r--src/feature/nodelist/dirlist.h10
-rw-r--r--src/feature/nodelist/fmt_routerstatus.c8
-rw-r--r--src/feature/nodelist/microdesc.c5
-rw-r--r--src/feature/nodelist/networkstatus.c97
-rw-r--r--src/feature/nodelist/networkstatus_voter_info_st.h6
-rw-r--r--src/feature/nodelist/node_select.c186
-rw-r--r--src/feature/nodelist/node_select.h28
-rw-r--r--src/feature/nodelist/node_st.h5
-rw-r--r--src/feature/nodelist/nodelist.c255
-rw-r--r--src/feature/nodelist/nodelist.h24
-rw-r--r--src/feature/nodelist/routerinfo.c55
-rw-r--r--src/feature/nodelist/routerinfo.h9
-rw-r--r--src/feature/nodelist/routerinfo_st.h7
-rw-r--r--src/feature/nodelist/routerlist.c199
-rw-r--r--src/feature/nodelist/routerlist.h14
-rw-r--r--src/feature/nodelist/routerset.c105
-rw-r--r--src/feature/nodelist/routerset.h4
-rw-r--r--src/feature/nodelist/routerstatus_st.h6
-rw-r--r--src/feature/nodelist/torcert.c12
-rw-r--r--src/feature/nodelist/torcert.h12
-rw-r--r--src/feature/relay/circuitbuild_relay.c84
-rw-r--r--src/feature/relay/circuitbuild_relay.h2
-rw-r--r--src/feature/relay/dns.c2
-rw-r--r--src/feature/relay/ext_orport.c2
-rw-r--r--src/feature/relay/relay_config.c222
-rw-r--r--src/feature/relay/relay_config.h7
-rw-r--r--src/feature/relay/relay_find_addr.c280
-rw-r--r--src/feature/relay/relay_find_addr.h17
-rw-r--r--src/feature/relay/relay_periodic.c101
-rw-r--r--src/feature/relay/router.c657
-rw-r--r--src/feature/relay/router.h21
-rw-r--r--src/feature/relay/routerkeys.c41
-rw-r--r--src/feature/relay/selftest.c408
-rw-r--r--src/feature/relay/selftest.h18
-rw-r--r--src/feature/rend/rendcache.c9
-rw-r--r--src/feature/rend/rendclient.c11
-rw-r--r--src/feature/rend/rendcommon.c10
-rw-r--r--src/feature/rend/rendparse.c17
-rw-r--r--src/feature/rend/rendservice.c38
-rw-r--r--src/feature/stats/bw_array_st.h57
-rw-r--r--src/feature/stats/bwhist.c548
-rw-r--r--src/feature/stats/bwhist.h47
-rw-r--r--src/feature/stats/connstats.c283
-rw-r--r--src/feature/stats/connstats.h25
-rw-r--r--src/feature/stats/geoip_stats.c2
-rw-r--r--src/feature/stats/include.am5
-rw-r--r--src/feature/stats/predict_ports.c4
-rw-r--r--src/feature/stats/rephist.c822
-rw-r--r--src/feature/stats/rephist.h28
-rw-r--r--src/include.am4
-rw-r--r--src/lib/buf/buffers.c17
-rw-r--r--src/lib/buf/buffers.h2
-rw-r--r--src/lib/conf/conftypes.h2
-rw-r--r--src/lib/confmgt/typedvar.c2
-rw-r--r--src/lib/container/namemap.c2
-rw-r--r--src/lib/crypt_ops/compat_openssl.h3
-rw-r--r--src/lib/crypt_ops/crypto_curve25519.h4
-rw-r--r--src/lib/crypt_ops/crypto_dh_openssl.c2
-rw-r--r--src/lib/crypt_ops/crypto_format.c35
-rw-r--r--src/lib/crypt_ops/crypto_openssl_mgt.c2
-rw-r--r--src/lib/crypt_ops/crypto_openssl_mgt.h2
-rw-r--r--src/lib/defs/x25519_sizes.h3
-rw-r--r--src/lib/dispatch/dispatch.h2
-rw-r--r--src/lib/encoding/binascii.c2
-rw-r--r--src/lib/fs/conffile.c162
-rw-r--r--src/lib/fs/files.c36
-rw-r--r--src/lib/fs/files.h4
-rw-r--r--src/lib/fs/path.c415
-rw-r--r--src/lib/fs/path.h7
-rw-r--r--src/lib/log/log.c85
-rw-r--r--src/lib/log/log.h4
-rw-r--r--src/lib/log/ratelim.c12
-rw-r--r--src/lib/log/ratelim.h8
-rw-r--r--src/lib/math/prob_distr.c4
-rw-r--r--src/lib/meminfo/.may_include1
-rw-r--r--src/lib/meminfo/meminfo.c3
-rw-r--r--src/lib/metrics/include.am25
-rw-r--r--src/lib/metrics/lib_metrics.md12
-rw-r--r--src/lib/metrics/metrics_common.c29
-rw-r--r--src/lib/metrics/metrics_common.h45
-rw-r--r--src/lib/metrics/metrics_store.c140
-rw-r--r--src/lib/metrics/metrics_store.h42
-rw-r--r--src/lib/metrics/metrics_store_entry.c129
-rw-r--r--src/lib/metrics/metrics_store_entry.h68
-rw-r--r--src/lib/metrics/prometheus.c56
-rw-r--r--src/lib/metrics/prometheus.h18
-rw-r--r--src/lib/net/address.c63
-rw-r--r--src/lib/net/address.h16
-rw-r--r--src/lib/net/buffers_net.c33
-rw-r--r--src/lib/net/buffers_net.h6
-rw-r--r--src/lib/osinfo/include.am6
-rw-r--r--src/lib/osinfo/libc.c66
-rw-r--r--src/lib/osinfo/libc.h19
-rw-r--r--src/lib/process/process.c2
-rw-r--r--src/lib/process/process_unix.c2
-rw-r--r--src/lib/process/process_win32.c22
-rw-r--r--src/lib/process/restrict.c2
-rw-r--r--src/lib/process/waitpid.c2
-rw-r--r--src/lib/pubsub/pub_binding_st.h2
-rw-r--r--src/lib/pubsub/pubsub_build.h2
-rw-r--r--src/lib/pubsub/pubsub_check.c2
-rw-r--r--src/lib/pubsub/pubsub_macros.h2
-rw-r--r--src/lib/sandbox/sandbox.c43
-rw-r--r--src/lib/sandbox/sandbox.h5
-rw-r--r--src/lib/string/compat_string.h2
-rw-r--r--src/lib/string/util_string.c9
-rw-r--r--src/lib/string/util_string.h1
-rw-r--r--src/lib/subsys/initialization.md4
-rw-r--r--src/lib/subsys/subsys.h12
-rw-r--r--src/lib/thread/compat_winthreads.c124
-rw-r--r--src/lib/thread/threads.h7
-rw-r--r--src/lib/time/compat_time.h2
-rw-r--r--src/lib/time/tvdiff.c2
-rw-r--r--src/lib/tls/buffers_tls.c29
-rw-r--r--src/lib/tls/buffers_tls.h2
-rw-r--r--src/lib/tls/tortls_openssl.c2
-rw-r--r--src/lib/trace/.may_include1
-rw-r--r--src/lib/trace/debug.h30
-rw-r--r--src/lib/trace/events.h84
-rw-r--r--src/lib/trace/include.am26
-rw-r--r--src/lib/trace/lttng/include.am3
-rw-r--r--src/lib/trace/lttng/lttng.h28
-rw-r--r--src/lib/trace/trace.c8
-rw-r--r--src/lib/trace/trace.h30
-rw-r--r--src/lib/trace/trace_stub.c19
-rw-r--r--src/lib/trace/trace_sys.c36
-rw-r--r--src/lib/trace/trace_sys.h22
-rw-r--r--src/lib/trace/usdt/include.am3
-rw-r--r--src/lib/trace/usdt/usdt.h33
-rw-r--r--src/mainpage.md5
-rw-r--r--src/rust/crypto/rand/rng.rs4
-rw-r--r--src/rust/external/crypto_digest.rs6
-rw-r--r--src/rust/protover/ffi.rs10
-rw-r--r--src/rust/protover/protover.rs29
-rw-r--r--src/rust/protover/tests/protover.rs13
-rw-r--r--src/rust/tor_allocate/tor_allocate.rs2
-rw-r--r--src/rust/tor_log/tor_log.rs4
-rw-r--r--src/test/conf_examples/bug_31495_1/expected2
-rw-r--r--src/test/conf_examples/bug_31495_1/expected_log1
-rw-r--r--src/test/conf_examples/bug_31495_1/torrc2
-rw-r--r--src/test/conf_examples/bug_31495_2/error1
-rw-r--r--src/test/conf_examples/bug_31495_2/torrc3
-rw-r--r--src/test/conf_examples/bug_31495_3/cmdline1
-rw-r--r--src/test/conf_examples/bug_31495_3/expected2
-rw-r--r--src/test/conf_examples/bug_31495_3/expected_log1
-rw-r--r--src/test/conf_examples/bug_31495_3/torrc3
-rw-r--r--src/test/conf_examples/crypto_accel/expected_log_nss2
-rw-r--r--src/test/conf_examples/crypto_accel_req/expected_log_nss2
-rw-r--r--src/test/conf_examples/dirauth_3/error_no_dirauth1
-rw-r--r--src/test/conf_examples/dirauth_3/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/dirauth_3/expected9
-rw-r--r--src/test/conf_examples/dirauth_3/expected_log1
-rw-r--r--src/test/conf_examples/dirauth_3/torrc13
-rw-r--r--src/test/conf_examples/large_1/expected2
-rw-r--r--src/test/conf_examples/large_1/expected_no_dirauth2
-rw-r--r--src/test/conf_examples/large_1/torrc1
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_log2
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_log_lzma2
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_log_lzma_zstd2
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_log_zstd2
-rw-r--r--src/test/conf_examples/multiple_routerset_1/expected1
-rw-r--r--src/test/conf_examples/multiple_routerset_1/expected_log1
-rw-r--r--src/test/conf_examples/multiple_routerset_1/torrc2
-rw-r--r--src/test/conf_examples/multiple_routerset_2/cmdline1
-rw-r--r--src/test/conf_examples/multiple_routerset_2/expected1
-rw-r--r--src/test/conf_examples/multiple_routerset_2/expected_log1
-rw-r--r--src/test/conf_examples/multiple_routerset_2/torrc2
-rw-r--r--src/test/conf_examples/multiple_routerset_3/cmdline1
-rw-r--r--src/test/conf_examples/multiple_routerset_3/expected1
-rw-r--r--src/test/conf_examples/multiple_routerset_3/expected_log1
-rw-r--r--src/test/conf_examples/multiple_routerset_3/torrc2
-rw-r--r--src/test/conf_examples/multiple_routerset_4/cmdline1
-rw-r--r--src/test/conf_examples/multiple_routerset_4/expected1
-rw-r--r--src/test/conf_examples/multiple_routerset_4/expected_log1
-rw-r--r--src/test/conf_examples/multiple_routerset_4/torrc3
-rw-r--r--src/test/conf_examples/nss_1/expected_log2
-rw-r--r--src/test/conf_examples/nss_1/expected_log_nss2
-rw-r--r--src/test/ed25519_exts_ref.py6
-rw-r--r--src/test/example_extrainfo.inc505
-rw-r--r--src/test/example_extrainfo.template182
-rw-r--r--src/test/failing_routerdescs.inc1840
-rw-r--r--src/test/failing_routerdescs.template812
-rw-r--r--src/test/fuzz/include.am9
-rw-r--r--src/test/hs_test_helpers.c8
-rw-r--r--src/test/include.am48
-rw-r--r--src/test/rend_test_helpers.c13
-rw-r--r--src/test/slow_ed25519.py25
-rw-r--r--src/test/test-memwipe.c23
-rw-r--r--src/test/test.c25
-rw-r--r--src/test/test.h4
-rw-r--r--src/test/test_addr.c1
-rw-r--r--src/test/test_address.c30
-rw-r--r--src/test/test_address_set.c11
-rw-r--r--src/test/test_bridges.c12
-rw-r--r--src/test/test_bwmgt.c4
-rw-r--r--src/test/test_channel.c92
-rw-r--r--src/test/test_channeltls.c34
-rw-r--r--src/test/test_circuitbuild.c464
-rw-r--r--src/test/test_circuitmux.c2
-rw-r--r--src/test/test_circuitpadding.c27
-rw-r--r--src/test/test_circuitstats.c95
-rw-r--r--src/test/test_config.c1665
-rw-r--r--src/test/test_confparse.c2
-rw-r--r--src/test/test_connection.c119
-rw-r--r--src/test/test_consdiffmgr.c2
-rw-r--r--src/test/test_controller.c87
-rw-r--r--src/test/test_controller_events.c28
-rw-r--r--src/test/test_crypto.c10
-rw-r--r--src/test/test_descriptors.inc734
-rw-r--r--src/test/test_dir.c588
-rw-r--r--src/test/test_dir_common.c46
-rw-r--r--src/test/test_dir_handle_get.c75
-rw-r--r--src/test/test_dirvote.c671
-rw-r--r--src/test/test_dispatch.c2
-rw-r--r--src/test/test_dos.c32
-rw-r--r--src/test/test_entrynodes.c22
-rw-r--r--src/test/test_geoip.c6
-rw-r--r--src/test/test_guardfraction.c6
-rw-r--r--src/test/test_helpers.c150
-rw-r--r--src/test/test_helpers.h7
-rw-r--r--src/test/test_hs_client.c8
-rw-r--r--src/test/test_hs_common.c8
-rw-r--r--src/test/test_hs_control.c4
-rw-r--r--src/test/test_hs_descriptor.c9
-rw-r--r--src/test/test_hs_metrics.c68
-rw-r--r--src/test/test_hs_service.c15
-rw-r--r--src/test/test_include.py196
-rwxr-xr-xsrc/test/test_include.sh111
-rwxr-xr-xsrc/test/test_key_expiration.sh70
-rw-r--r--src/test/test_link_handshake.c2
-rw-r--r--src/test/test_logging.c6
-rw-r--r--src/test/test_metrics.c277
-rw-r--r--src/test/test_microdesc.c185
-rw-r--r--src/test/test_nodelist.c86
-rw-r--r--src/test/test_options.c2
-rwxr-xr-xsrc/test/test_parseconf.sh2
-rw-r--r--src/test/test_periodic_event.c7
-rw-r--r--src/test/test_policy.c215
-rw-r--r--src/test/test_prob_distr.c4
-rw-r--r--src/test/test_process.c2
-rw-r--r--src/test/test_process_descs.c2
-rw-r--r--src/test/test_protover.c372
-rw-r--r--src/test/test_rebind.py2
-rw-r--r--src/test/test_relay.c191
-rw-r--r--src/test/test_relaycell.c26
-rw-r--r--src/test/test_router.c137
-rw-r--r--src/test/test_routerkeys.c54
-rw-r--r--src/test/test_routerlist.c46
-rw-r--r--src/test/test_routerset.c56
-rw-r--r--src/test/test_sendme.c2
-rw-r--r--src/test/test_shared_random.c4
-rw-r--r--src/test/test_statefile.c56
-rw-r--r--src/test/test_stats.c374
-rw-r--r--src/test/test_status.c341
-rw-r--r--src/test/test_util.c535
-rw-r--r--src/test/test_voting_flags.c14
-rw-r--r--src/test/testing_common.c2
-rw-r--r--src/test/vote_descriptors.inc8
-rw-r--r--src/tools/include.am8
-rw-r--r--src/trunnel/circpad_negotiation.c52
-rw-r--r--src/trunnel/circpad_negotiation.h27
-rw-r--r--src/trunnel/circpad_negotiation.trunnel17
-rw-r--r--src/win32/orconfig.h2
668 files changed, 24686 insertions, 10280 deletions
diff --git a/.gitignore b/.gitignore
index 53d7e5715b..19a82fb4b6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -104,31 +104,31 @@ core.*
/doc/Makefile
/doc/Makefile.in
/doc/doxygen
-/doc/tor.1
-/doc/tor.1.in
-/doc/tor.html
-/doc/tor.html.in
-/doc/tor.1.xml
-/doc/tor-gencert.1
-/doc/tor-gencert.1.in
-/doc/tor-gencert.html
-/doc/tor-gencert.html.in
-/doc/tor-gencert.1.xml
-/doc/tor-resolve.1
-/doc/tor-resolve.1.in
-/doc/tor-resolve.html
-/doc/tor-resolve.html.in
-/doc/tor-resolve.1.xml
-/doc/torify.1
-/doc/torify.1.in
-/doc/torify.html
-/doc/torify.html.in
-/doc/torify.1.xml
-/doc/tor-print-ed-signing-cert.1
-/doc/tor-print-ed-signing-cert.1.in
-/doc/tor-print-ed-signing-cert.html
-/doc/tor-print-ed-signing-cert.html.in
-/doc/tor-print-ed-signing-cert.1.xml
+/doc/man/tor.1
+/doc/man/tor.1.in
+/doc/man/tor.html
+/doc/man/tor.html.in
+/doc/man/tor.1.xml
+/doc/man/tor-gencert.1
+/doc/man/tor-gencert.1.in
+/doc/man/tor-gencert.html
+/doc/man/tor-gencert.html.in
+/doc/man/tor-gencert.1.xml
+/doc/man/tor-resolve.1
+/doc/man/tor-resolve.1.in
+/doc/man/tor-resolve.html
+/doc/man/tor-resolve.html.in
+/doc/man/tor-resolve.1.xml
+/doc/man/torify.1
+/doc/man/torify.1.in
+/doc/man/torify.html
+/doc/man/torify.html.in
+/doc/man/torify.1.xml
+/doc/man/tor-print-ed-signing-cert.1
+/doc/man/tor-print-ed-signing-cert.1.in
+/doc/man/tor-print-ed-signing-cert.html
+/doc/man/tor-print-ed-signing-cert.html.in
+/doc/man/tor-print-ed-signing-cert.1.xml
# /doc/spec/
/doc/spec/Makefile
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ba61c71b2b..8afd090a58 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -96,7 +96,7 @@ variables:
- if [ "$CHUTNEY" = yes ]; then git clone --depth 1 https://git.torproject.org/chutney.git ; export CHUTNEY_PATH="$(pwd)/chutney"; fi
- if [ "$TRACING" = yes ]; then apt install liblttng-ust-dev; fi
-# Minmal check on debian: just make, make check.
+# Minimal check on debian: just make, make check.
#
debian-minimal:
image: debian:stable
@@ -170,6 +170,7 @@ debian-tracing:
variables:
TRACING: "yes"
CHECK: "no"
+ DISTCHECK: "yes"
script:
- ./scripts/ci/ci-driver.sh
# Ensure that we only run tracing when it's implemented.
diff --git a/.travis.yml b/.travis.yml
index 01343e65d9..aaca3a7368 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -237,8 +237,8 @@ install:
- dd ibs=1 count=1024 if=/dev/urandom > ~/.torrc
script:
- # Skip test_rebind on macOS
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export TOR_SKIP_TEST_REBIND=true; fi
+ # Skip test_rebind and test_include on macOS
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export TOR_SKIP_TEST_REBIND=true; export TOR_SKIP_TEST_INCLUDE=true; fi
- ./autogen.sh
- CONFIGURE_FLAGS="$ASCIIDOC_OPTIONS $COVERAGE_OPTIONS $HARDENING_OPTIONS $MODULES_OPTIONS $NSS_OPTIONS $OPENSSL_OPTIONS $RUST_OPTIONS --enable-fatal-warnings --disable-silent-rules"
- echo "Configure flags are $CONFIGURE_FLAGS CC=\"$CC $C_DIALECT_OPTIONS\""
diff --git a/ChangeLog b/ChangeLog
index 9ddbfa95fd..88fd95f191 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,1529 @@
+Changes in version 0.4.4.6 - 2020-11-12
+ Tor 0.4.4.6 is the second stable release in the 0.4.4.x series. It
+ backports fixes from later releases, including a fix for TROVE-2020-
+ 005, a security issue that could be used, under certain cases, by an
+ adversary to observe traffic patterns on a limited number of circuits
+ intended for a different relay.
+
+ o Major bugfixes (security, backport from 0.4.5.1-alpha):
+ - When completing a channel, relays now check more thoroughly to
+ make sure that it matches any pending circuits before attaching
+ those circuits. Previously, address correctness and Ed25519
+ identities were not checked in this case, but only when extending
+ circuits on an existing channel. Fixes bug 40080; bugfix on
+ 0.2.7.2-alpha. Resolves TROVE-2020-005.
+
+ o Minor features (directory authorities, backport from 0.4.5.1-alpha):
+ - Authorities now list a different set of protocols as required and
+ recommended. These lists have been chosen so that only truly
+ recommended and/or required protocols are included, and so that
+ clients using 0.2.9 or later will continue to work (even though
+ they are not supported), whereas only relays running 0.3.5 or
+ later will meet the requirements. Closes ticket 40162.
+ - Make it possible to specify multiple ConsensusParams torrc lines.
+ Now directory authority operators can for example put the main
+ ConsensusParams config in one torrc file and then add to it from a
+ different torrc file. Closes ticket 40164.
+
+ o Minor features (subprotocol versions, backport from 0.4.5.1-alpha):
+ - Tor no longer allows subprotocol versions larger than 63.
+ Previously version numbers up to UINT32_MAX were allowed, which
+ significantly complicated our code. Implements proposal 318;
+ closes ticket 40133.
+
+ o Minor features (tests, v2 onion services, backport from 0.4.5.1-alpha):
+ - Fix a rendezvous cache unit test that was triggering an underflow
+ on the global rend cache allocation. Fixes bug 40125; bugfix
+ on 0.2.8.1-alpha.
+ - Fix another rendezvous cache unit test that was triggering an
+ underflow on the global rend cache allocation. Fixes bug 40126;
+ bugfix on 0.2.8.1-alpha.
+
+ o Minor bugfixes (compilation, backport from 0.4.5.1-alpha):
+ - Fix compiler warnings that would occur when building with
+ "--enable-all-bugs-are-fatal" and "--disable-module-relay" at the
+ same time. Fixes bug 40129; bugfix on 0.4.4.1-alpha.
+ - Resolve a compilation warning that could occur in
+ test_connection.c. Fixes bug 40113; bugfix on 0.2.9.3-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.5.1-alpha):
+ - Remove a debug logging statement that uselessly spammed the logs.
+ Fixes bug 40135; bugfix on 0.3.5.0-alpha.
+
+ o Minor bugfixes (relay configuration, crash, backport from 0.4.5.1-alpha):
+ - Avoid a fatal assert() when failing to create a listener
+ connection for an address that was in use. Fixes bug 40073; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor bugfixes (v2 onion services, backport from 0.4.5.1-alpha):
+ - For HSFETCH commands on v2 onion services addresses, check the
+ length of bytes decoded, not the base32 length. Fixes bug 34400;
+ bugfix on 0.4.1.1-alpha. Patch by Neel Chauhan.
+
+
+Changes in version 0.4.3.7 - 2020-11-12
+ Tor 0.4.3.7 backports several bugfixes from later releases. It
+ includes a fix for TROVE-2020-005, a security issue that could be
+ used, under certain cases, by an adversary to observe traffic patterns
+ on a limited number of circuits intended for a different relay.
+
+ Please be aware that support for the 0.4.3.x series will end on 15
+ February 2021. Please upgrade to 0.4.4.x or 0.4.5.x before then, or
+ downgrade to 0.3.5.x, which will be supported until at least 1
+ February 2022.
+
+ o Major features (fallback directory list, backport form 0.4.4.3-alpha):
+ - Replace the 148 fallback directories originally included in Tor
+ 0.4.1.4-rc (of which around 105 are still functional) with a list
+ of 144 fallbacks generated in July 2020. Closes ticket 40061.
+
+ o Major bugfixes (security, backport from 0.4.5.1-alpha):
+ - When completing a channel, relays now check more thoroughly to
+ make sure that it matches any pending circuits before attaching
+ those circuits. Previously, address correctness and Ed25519
+ identities were not checked in this case, but only when extending
+ circuits on an existing channel. Fixes bug 40080; bugfix on
+ 0.2.7.2-alpha. Resolves TROVE-2020-005.
+
+ o Major bugfixes (NSS, backport from 0.4.4.3-alpha):
+ - When running with NSS enabled, make sure that NSS knows to expect
+ nonblocking sockets. Previously, we set our TCP sockets as
+ nonblocking, but did not tell NSS, which in turn could lead to
+ unexpected blocking behavior. Fixes bug 40035; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor features (security, backport from 0.4.4.4-rc):
+ - Channels using obsolete versions of the Tor link protocol are no
+ longer allowed to circumvent address-canonicity checks. (This is
+ only a minor issue, since such channels have no way to set ed25519
+ keys, and therefore should always be rejected for circuits that
+ specify ed25519 identities.) Closes ticket 40081.
+
+ o Minor features (subprotocol versions, backport from 0.4.5.1-alpha):
+ - Tor no longer allows subprotocol versions larger than 63.
+ Previously version numbers up to UINT32_MAX were allowed, which
+ significantly complicated our code. Implements proposal 318;
+ closes ticket 40133.
+
+ o Minor features (tests, backport from 0.4.4.5):
+ - Our "make check" target now runs the unit tests in 8 parallel
+ chunks. Doing this speeds up hardened CI builds by more than a
+ factor of two. Closes ticket 40098.
+
+ o Minor features (tests, v2 onion services, backport from 0.4.5.1-alpha):
+ - Fix a rendezvous cache unit test that was triggering an underflow
+ on the global rend cache allocation. Fixes bug 40125; bugfix
+ on 0.2.8.1-alpha.
+ - Fix another rendezvous cache unit test that was triggering an
+ underflow on the global rend cache allocation. Fixes bug 40126;
+ bugfix on 0.2.8.1-alpha.
+
+ o Minor bugfixes (correctness, buffers, backport from 0.4.4.4-rc):
+ - Fix a correctness bug that could cause an assertion failure if we
+ ever tried using the buf_move_all() function with an empty input
+ buffer. As far as we know, no released versions of Tor do this.
+ Fixes bug 40076; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.5.1-alpha):
+ - Remove a debug logging statement that uselessly spammed the logs.
+ Fixes bug 40135; bugfix on 0.3.5.0-alpha.
+
+ o Minor bugfixes (rate limiting, bridges, pluggable transports, backport from 0.4.4.4-rc):
+ - On a bridge, treat all connections from an ExtORPort as remote by
+ default for the purposes of rate-limiting. Previously, bridges
+ would treat the connection as local unless they explicitly
+ received a "USERADDR" command. ExtORPort connections still count
+ as local if there is a USERADDR command with an explicit local
+ address. Fixes bug 33747; bugfix on 0.2.5.1-alpha.
+
+ o Minor bugfixes (relay configuration, crash, backport from 0.4.5.1-alpha):
+ - Avoid a fatal assert() when failing to create a listener
+ connection for an address that was in use. Fixes bug 40073; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor bugfixes (relay, usability, backport from 0.4.4.3-alpha):
+ - Adjust the rules for when to warn about having too many
+ connections to other relays. Previously we'd tolerate up to 1.5
+ connections per relay on average. Now we tolerate more connections
+ for directory authorities, and raise the number of total
+ connections we need to see before we warn. Fixes bug 33880; bugfix
+ on 0.3.1.1-alpha.
+
+ o Minor bugfixes (tests, 0.4.4.5):
+ - Fix the behavior of the rend_cache/clean_v2_descs_as_dir when run
+ on its own. Previously, it would exit with an error. Fixes bug
+ 40099; bugfix on 0.2.8.1-alpha.
+
+ o Minor bugfixes (v2 onion services, backport from 0.4.5.1-alpha):
+ - For HSFETCH commands on v2 onion services addresses, check the
+ length of bytes decoded, not the base32 length. Fixes bug 34400;
+ bugfix on 0.4.1.1-alpha. Patch by Neel Chauhan.
+
+ o Minor bugfixes (windows, backport from 0.4.4.4-rc):
+ - Fix a bug that prevented Tor from starting if its log file grew
+ above 2GB. Fixes bug 31036; bugfix on 0.2.1.8-alpha.
+
+ o Deprecated features (onion service v2, backport form 0.4.4.2-alpha):
+ - Add a deprecation warning for version 2 onion services. Closes
+ ticket 40003.
+
+ o Removed features (backport from 0.4.4.3-alpha):
+ - 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. ticket 40030.
+
+
+Changes in version 0.3.5.12 - 2020-11-12
+ Tor 0.4.3.7 backports several bugfixes from later releases. It
+ includes a fix for TROVE-2020-005, a security issue that could be
+ used, under certain cases, by an adversary to observe traffic patterns
+ on a limited number of circuits intended for a different relay.
+
+ o Major features (fallback directory list, backport form 0.4.4.3-alpha):
+ - Replace the 148 fallback directories originally included in Tor
+ 0.4.1.4-rc (of which around 105 are still functional) with a list
+ of 144 fallbacks generated in July 2020. Closes ticket 40061.
+
+ o Major bugfixes (security, backport from 0.4.5.1-alpha):
+ - When completing a channel, relays now check more thoroughly to
+ make sure that it matches any pending circuits before attaching
+ those circuits. Previously, address correctness and Ed25519
+ identities were not checked in this case, but only when extending
+ circuits on an existing channel. Fixes bug 40080; bugfix on
+ 0.2.7.2-alpha. Resolves TROVE-2020-005.
+
+ o Major bugfixes (NSS, backport from 0.4.4.3-alpha):
+ - When running with NSS enabled, make sure that NSS knows to expect
+ nonblocking sockets. Previously, we set our TCP sockets as
+ nonblocking, but did not tell NSS, which in turn could lead to
+ unexpected blocking behavior. Fixes bug 40035; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor features (security, backport from 0.4.4.4-rc):
+ - Channels using obsolete versions of the Tor link protocol are no
+ longer allowed to circumvent address-canonicity checks. (This is
+ only a minor issue, since such channels have no way to set ed25519
+ keys, and therefore should always be rejected for circuits that
+ specify ed25519 identities.) Closes ticket 40081.
+
+ 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 (subprotocol versions, backport from 0.4.5.1-alpha):
+ - Tor no longer allows subprotocol versions larger than 63.
+ Previously version numbers up to UINT32_MAX were allowed, which
+ significantly complicated our code. Implements proposal 318;
+ closes ticket 40133.
+
+ o Minor features (tests, backport from 0.4.4.5):
+ - Our "make check" target now runs the unit tests in 8 parallel
+ chunks. Doing this speeds up hardened CI builds by more than a
+ factor of two. Closes ticket 40098.
+
+ o Minor features (tests, v2 onion services, backport from 0.4.5.1-alpha):
+ - Fix a rendezvous cache unit test that was triggering an underflow
+ on the global rend cache allocation. Fixes bug 40125; bugfix
+ on 0.2.8.1-alpha.
+ - Fix another rendezvous cache unit test that was triggering an
+ underflow on the global rend cache allocation. Fixes bug 40126;
+ bugfix on 0.2.8.1-alpha.
+
+ o Minor bugfixes (correctness, buffers, backport from 0.4.4.4-rc):
+ - Fix a correctness bug that could cause an assertion failure if we
+ ever tried using the buf_move_all() function with an empty input
+ buffer. As far as we know, no released versions of Tor do this.
+ Fixes bug 40076; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.5.1-alpha):
+ - Remove a debug logging statement that uselessly spammed the logs.
+ Fixes bug 40135; bugfix on 0.3.5.0-alpha.
+
+ o Minor bugfixes (rate limiting, bridges, pluggable transports, backport from 0.4.4.4-rc):
+ - On a bridge, treat all connections from an ExtORPort as remote by
+ default for the purposes of rate-limiting. Previously, bridges
+ would treat the connection as local unless they explicitly
+ received a "USERADDR" command. ExtORPort connections still count
+ as local if there is a USERADDR command with an explicit local
+ address. Fixes bug 33747; bugfix on 0.2.5.1-alpha.
+
+ o Minor bugfixes (relay configuration, crash, backport from 0.4.5.1-alpha):
+ - Avoid a fatal assert() when failing to create a listener
+ connection for an address that was in use. Fixes bug 40073; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor bugfixes (relay, usability, backport from 0.4.4.3-alpha):
+ - Adjust the rules for when to warn about having too many
+ connections to other relays. Previously we'd tolerate up to 1.5
+ connections per relay on average. Now we tolerate more connections
+ for directory authorities, and raise the number of total
+ connections we need to see before we warn. Fixes bug 33880; bugfix
+ on 0.3.1.1-alpha.
+
+ o Minor bugfixes (relays, backport from 0.4.4.1-alpha):
+ - 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.
+
+ o Minor bugfixes (tests, 0.4.4.5):
+ - Fix the behavior of the rend_cache/clean_v2_descs_as_dir when run
+ on its own. Previously, it would exit with an error. Fixes bug
+ 40099; bugfix on 0.2.8.1-alpha.
+
+ o Minor bugfixes (windows, backport from 0.4.4.4-rc):
+ - Fix a bug that prevented Tor from starting if its log file grew
+ above 2GB. Fixes bug 31036; bugfix on 0.2.1.8-alpha.
+
+ o Deprecated features (onion service v2, backport form 0.4.4.2-alpha):
+ - Add a deprecation warning for version 2 onion services. Closes
+ ticket 40003.
+
+
+Changes in version 0.4.5.1-alpha - 2020-11-01
+ Tor 0.4.5.1-alpha is the first alpha release in the 0.4.5.x series. It
+ improves support for IPv6, address discovery and self-testing, code
+ metrics and tracing.
+
+ This release also fixes TROVE-2020-005, a security issue that could be
+ used, under certain cases, by an adversary to observe traffic patterns
+ on a limited number of circuits intended for a different relay. To
+ mount this attack, the adversary would need to actively extend
+ circuits to an incorrect address, as well as compromise a relay's
+ legacy RSA-1024 key. We'll be backporting this fix to other release
+ series soon, after it has had some testing.
+
+ Here are the changes since 0.4.4.5.
+
+ o Major features (build):
+ - When building Tor, first link all object files into a single
+ static library. This may help with embedding Tor in other
+ programs. Note that most Tor functions do not constitute a part of
+ a stable or supported API: only those functions in tor_api.h
+ should be used if embedding Tor. Closes ticket 40127.
+
+ o Major features (metrics):
+ - Introduce a new MetricsPort which exposes, through an HTTP
+ interface, a series of metrics that tor collects at runtime. At
+ the moment, the only supported output format is Prometheus data
+ model. Closes ticket 40063. See the manual page for more
+ information and security considerations.
+ o Major features (relay, IPv6):
+ - The torrc option Address now supports IPv6. This unifies our
+ address discovery interface to support IPv4, IPv6, and hostnames.
+ Closes ticket 33233.
+ - Launch IPv4 and IPv6 ORPort self-test circuits on relays and
+ bridges. Closes ticket 33222.
+ - Relays now automatically bind on IPv6 for their ORPort, unless
+ specified otherwise with the IPv4Only flag. Closes ticket 33246.
+ - When a relay with IPv6 support is told to open a connection to
+ another relay, and the extend cell lists both IPv4 and IPv6
+ addresses, the first relay now picks randomly which address to
+ use. Closes ticket 33220.
+ - Relays now track their IPv6 ORPort reachability separately from
+ the reachability of their IPv4 ORPort. They will not publish a
+ descriptor unless _both_ ports appear to be externally reachable.
+ Closes ticket 34067.
+
+ o Major features (tracing):
+ - Add event-tracing library support for USDT and LTTng-UST, and a
+ few tracepoints in the circuit subsystem. More will come
+ incrementally. This feature is compiled out by default: it needs
+ to be enabled at configure time. See documentation in
+ doc/HACKING/Tracing.md. Closes ticket 32910.
+
+ o Major bugfixes (security):
+ - When completing a channel, relays now check more thoroughly to
+ make sure that it matches any pending circuits before attaching
+ those circuits. Previously, address correctness and Ed25519
+ identities were not checked in this case, but only when extending
+ circuits on an existing channel. Fixes bug 40080; bugfix on
+ 0.2.7.2-alpha. Resolves TROVE-2020-005.
+
+ o Major bugfixes (TLS, buffer):
+ - When attempting to read N bytes on a TLS connection, really try to
+ read all N bytes. Previously, Tor would stop reading after the
+ first TLS record, which can be smaller than the N bytes requested,
+ and not check for more data until the next mainloop event. Fixes
+ bug 40006; bugfix on 0.1.0.5-rc.
+
+ o Minor features (address discovery):
+ - If no Address statements are found, relays now prioritize guessing
+ their address by looking at the local interface instead of the
+ local hostname. If the interface address can't be found, the local
+ hostname is used. Closes ticket 33238.
+
+ o Minor features (admin tools):
+ - Add a new --format argument to -key-expiration option to allow
+ specifying the time format of the expiration date. Adds Unix
+ timestamp format support. Patch by Daniel Pinto. Closes
+ ticket 30045.
+
+ o Minor features (bootstrap reporting):
+ - When reporting bootstrapping status on a relay, do not consider
+ connections that have never been the target of an origin circuit.
+ Previously, all connection failures were treated as potential
+ bootstrapping failures, including connections that had been opened
+ because of client requests. Closes ticket 25061.
+
+ o Minor features (build):
+ - When running the configure script, try to detect version
+ mismatches between the OpenSSL headers and libraries, and suggest
+ that the user should try "--with-openssl-dir". Closes 40138.
+ - If the configure script has given any warnings, remind the user
+ about them at the end of the script. Related to 40138.
+
+ o Minor features (configuration):
+ - Allow using wildcards (* and ?) with the %include option on
+ configuration files. Closes ticket 25140. Patch by Daniel Pinto.
+ - Allow the configuration options EntryNodes, ExcludeNodes,
+ ExcludeExitNodes, ExitNodes, MiddleNodes, HSLayer2Nodes and
+ HSLayer3Nodes to be specified multiple times. Closes ticket 28361.
+ Patch by Daniel Pinto.
+
+ o Minor features (control port):
+ - Add a DROPTIMEOUTS command to drop circuit build timeout history
+ and reset the current timeout. Closes ticket 40002.
+ - When a stream enters the AP_CONN_STATE_CONTROLLER_WAIT status,
+ send a control port event. Closes ticket 32190. Patch by
+ Neel Chauhan.
+ - Introduce GETINFO "stats/ntor/{assigned/requested}" and
+ "stats/tap/{assigned/requested}" to get the NTor and TAP circuit
+ onion handshake counts respectively. Closes ticket 28279. Patch by
+ Neel Chauhan.
+
+ o Minor features (control port, IPv6):
+ - Tor relays now try to report to the controller when they are
+ launching an IPv6 self-test. Closes ticket 34068.
+ - Introduce "GETINFO address/v4" and "GETINFO address/v6" in the
+ control port to fetch the Tor host's respective IPv4 or IPv6
+ address. We keep "GETINFO address" for backwards-compatibility.
+ Closes ticket 40039. Patch by Neel Chauhan.
+
+ o Minor features (directory authorities):
+ - Authorities now list a different set of protocols as required and
+ recommended. These lists have been chosen so that only truly
+ recommended and/or required protocols are included, and so that
+ clients using 0.2.9 or later will continue to work (even though
+ they are not supported), whereas only relays running 0.3.5 or
+ later will meet the requirements. Closes ticket 40162.
+ - Add a new consensus method 30 that removes the unnecessary "="
+ padding from ntor-onion-key. Closes ticket 7869. Patch by
+ Daniel Pinto.
+ - Directory authorities now reject descriptors from relays running
+ Tor versions from the obsolete 0.4.1 series. Resolves ticket
+ 34357. Patch by Neel Chauhan.
+ - Make it possible to specify multiple ConsensusParams torrc lines.
+ Now directory authority operators can for example put the main
+ ConsensusParams config in one torrc file and then add to it from a
+ different torrc file. Closes ticket 40164.
+ - The AssumeReachable option no longer stops directory authorities
+ from checking whether other relays are running. A new
+ AuthDirTestReachability option can be used to disable these
+ checks. Closes ticket 34445.
+ - When looking for possible Sybil attacks, also consider IPv6
+ addresses. Two routers are considered to have "the same" address
+ by this metric if they are in the same /64 network. Patch from
+ Maurice Pibouin. Closes ticket 7193.
+
+ o Minor features (directory authorities, IPv6):
+ - Make authorities add their IPv6 ORPort (if any) to the trusted
+ servers list. Authorities previously added only their IPv4
+ addresses. Closes ticket 32822.
+
+ o Minor features (ed25519, relay):
+ - Save a relay's base64-encoded ed25519 identity key to the data
+ directory in a file named fingerprint-ed25519. Closes ticket
+ 30642. Patch by Neel Chauhan.
+
+ o Minor features (heartbeat):
+ - Include the total number of inbound and outbound IPv4 and IPv6
+ connections in the heartbeat message. Closes ticket 29113.
+
+ o Minor features (IPv6, ExcludeNodes):
+ - Handle IPv6 addresses in ExcludeNodes; previously they were
+ ignored. Closes ticket 34065. Patch by Neel Chauhan.
+
+ o Minor features (logging):
+ - Add the running glibc version to the log, and the compiled glibc
+ version to the library list returned when using --library-versions.
+ Patch from Daniel Pinto. Closes ticket 40047.
+ - Consider an HTTP 301 response to be an error (like a 404) when
+ processing a directory response. Closes ticket 40053.
+ - Log directory fetch statistics as a single line. Closes
+ ticket 40159.
+ - Provide more complete descriptions of our connections when logging
+ about them. Closes ticket 40041.
+ - When describing a relay in the logs, we now include its ed25519
+ identity. Closes ticket 22668.
+
+ o Minor features (onion services):
+ - Only overwrite an onion service's existing hostname file if its
+ contents are wrong. This enables read-only onion-service
+ directories. Resolves ticket 40062. Patch by Neel Chauhan.
+
+ o Minor features (pluggable transports):
+ - Add an OutboundBindAddressPT option to allow users to specify
+ which IPv4 and IPv6 address pluggable transports should use for
+ outgoing IP packets. Tor does not have a way to enforce that the
+ pluggable transport honors this option, so each pluggable transport
+ needs to implement support on its own. Closes ticket 5304.
+
+ o Minor features (relay address tracking):
+ - We now store relay addresses for OR connections in a more logical
+ way. Previously we would sometimes overwrite the actual address of
+ a connection with a "canonical address", and then store the "real
+ address" elsewhere to remember it. We now track the "canonical
+ address" elsewhere for the cases where we need it, and leave the
+ connection's address alone. Closes ticket 33898.
+
+ o Minor features (relay):
+ - If a relay is unable to discover its address, attempt to learn it
+ from the NETINFO cell. Closes ticket 40022.
+ - Log immediately when launching a relay self-check. Previously we
+ would try to log before launching checks, or approximately when we
+ intended to launch checks, but this tended to be error-prone.
+ Closes ticket 34137.
+
+ o Minor features (relay, address discovery):
+ - If Address option is not found in torrc, attempt to learn our
+ address with the configured ORPort address if any. Closes
+ ticket 33236.
+
+ o Minor features (relay, IPv6):
+ - Add an AssumeReachableIPv6 option to disable self-checking IPv6
+ reachability. Closes part of ticket 33224.
+ - Add new "assume-reachable" and "assume-reachable-ipv6" consensus
+ parameters to be used in an emergency to tell relays that they
+ should publish even if they cannot complete their ORPort self-
+ checks. Closes ticket 34064 and part of 33224.
+ - Allow relays to send IPv6-only extend cells. Closes ticket 33222.
+ - Declare support for the Relay=3 subprotocol version. Closes
+ ticket 33226.
+ - When launching IPv6 ORPort self-test circuits, make sure that the
+ second-last hop can initiate an IPv6 extend. Closes ticket 33222.
+
+ o Minor features (specification update):
+ - Several fields in microdescriptors, router descriptors, and
+ consensus documents that were formerly optional are now required.
+ Implements proposal 315; closes ticket 40132.
+
+ o Minor features (state management):
+ - When loading the state file, remove entries from the statefile
+ that have been obsolete for a long time. Ordinarily Tor preserves
+ unrecognized entries in order to keep forward-compatibility, but
+ these entries have not actually been used in any release since
+ before 0.3.5.x. Closes ticket 40137.
+
+ o Minor features (statistics, ipv6):
+ - Relays now publish IPv6-specific counts of single-direction versus
+ bidirectional relay connections. Closes ticket 33264.
+ - Relays now publish their IPv6 read and write statistics over time,
+ if statistics are enabled. Closes ticket 33263.
+
+ o Minor features (subprotocol versions):
+ - Tor no longer allows subprotocol versions larger than 63.
+ Previously version numbers up to UINT32_MAX were allowed, which
+ significantly complicated our code. Implements proposal 318;
+ closes ticket 40133.
+ - Use the new limitations on subprotocol versions due to proposal
+ 318 to simplify our implementation. Part of ticket 40133.
+
+ o Minor features (testing configuration):
+ - The TestingTorNetwork option no longer implicitly sets
+ AssumeReachable to 1. This change allows us to test relays' self-
+ testing mechanisms, and to test authorities' relay-testing
+ functionality. Closes ticket 34446.
+
+ o Minor features (testing):
+ - Added unit tests for channel_matches_target_addr_for_extend().
+ Closes Ticket 33919. Patch by MrSquanchee.
+
+ o Minor features (tests, v2 onion services):
+ - Fix a rendezvous cache unit test that was triggering an underflow
+ on the global rend cache allocation. Fixes bug 40125; bugfix
+ on 0.2.8.1-alpha.
+ - Fix another rendezvous cache unit test that was triggering an
+ underflow on the global rend cache allocation. Fixes bug 40126;
+ bugfix on 0.2.8.1-alpha.
+
+ o Minor bugfixes (circuit padding):
+ - When circpad_send_padding_cell_for_callback is called,
+ `is_padding_timer_scheduled` flag was not reset. Now it is set to
+ 0 at the top of that function. Fixes bug 32671; bugfix
+ on 0.4.0.1-alpha.
+ - Add a per-circuit padding machine instance counter, so we can
+ differentiate between shutdown requests for old machines on a
+ circuit. Fixes bug 30992; bugfix on 0.4.1.1-alpha.
+ - Add the ability to keep circuit padding machines if they match a
+ set of circuit states or purposes. This allows us to have machines
+ that start up under some conditions but don't shut down under
+ others. We now use this mask to avoid starting up introduction
+ circuit padding again after the machines have already completed.
+ Fixes bug 32040; bugfix on 0.4.1.1-alpha.
+
+ o Minor bugfixes (compatibility):
+ - Strip '\r' characters when reading text files on Unix platforms.
+ This should resolve an issue where a relay operator migrates a
+ relay from Windows to Unix, but does not change the line ending of
+ Tor's various state files to match the platform, and the CRLF line
+ endings from Windows end up leaking into other files such as the
+ extra-info document. Fixes bug 33781; bugfix on 0.0.9pre5.
+
+ o Minor bugfixes (compilation):
+ - Fix compiler warnings that would occur when building with
+ "--enable-all-bugs-are-fatal" and "--disable-module-relay" at the
+ same time. Fixes bug 40129; bugfix on 0.4.4.1-alpha.
+ - Resolve a compilation warning that could occur in
+ test_connection.c. Fixes bug 40113; bugfix on 0.2.9.3-alpha.
+
+ o Minor bugfixes (configuration):
+ - Fix bug where %including a pattern ending with */ would include
+ files and folders (instead of folders only) in versions of glibc <
+ 2.19. Fixes bug 40141; bugfix on 0.4.5.0-alpha-dev. Patch by
+ Daniel Pinto.
+
+ o Minor bugfixes (control port):
+ - Make sure we send the SOCKS request address in relay begin cells
+ when a stream is attached with the purpose
+ CIRCUIT_PURPOSE_CONTROLLER. Fixes bug 33124; bugfix on 0.0.5.
+ Patch by Neel Chauhan.
+
+ o Minor bugfixes (logging):
+ - Remove a debug logging statement that uselessly spammed the logs.
+ Fixes bug 40135; bugfix on 0.3.5.0-alpha.
+ - When logging a rate-limited message about how many messages have
+ been suppressed in the last N seconds, give an accurate value for
+ N, rounded up to the nearest minute. Previously we would report
+ the size of the rate-limiting interval, regardless of when the
+ messages started to occur. Fixes bug 19431; bugfix
+ on 0.2.2.16-alpha.
+
+ o Minor bugfixes (relay configuration, crash):
+ - Avoid a fatal assert() when failing to create a listener
+ connection for an address that was in use. Fixes bug 40073; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor bugfixes (rust, protocol versions):
+ - Declare support for the onion service introduction point denial of
+ service extensions when building with Rust. Fixes bug 34248;
+ bugfix on 0.4.2.1-alpha.
+ - Make Rust protocol version support checks consistent with the
+ undocumented error behavior of the corresponding C code. Fixes bug
+ 34251; bugfix on 0.3.3.5-rc.
+
+ o Minor bugfixes (self-testing):
+ - When receiving an incoming circuit, only accept it as evidence
+ that we are reachable if the declared address of its channel is
+ the same address we think that we have. Otherwise, it could be
+ evidence that we're reachable on some other address. Fixes bug
+ 20165; bugfix on 0.1.0.1-rc.
+
+ o Minor bugfixes (spec conformance):
+ - Use the correct key type when generating signing->link
+ certificates. Fixes bug 40124; bugfix on 0.2.7.2-alpha.
+
+ o Minor bugfixes (subprotocol versions):
+ - Consistently reject extra commas, instead of only rejecting
+ leading commas. Fixes bug 27194; bugfix on 0.2.9.4-alpha.
+ - In summarize_protover_flags(), treat empty strings the same as
+ NULL. This prevents protocols_known from being set. Previously, we
+ treated empty strings as normal strings, which led to
+ protocols_known being set. Fixes bug 34232; bugfix on
+ 0.3.3.2-alpha. Patch by Neel Chauhan.
+
+ o Minor bugfixes (v2 onion services):
+ - For HSFETCH commands on v2 onion services addresses, check the
+ length of bytes decoded, not the base32 length. Fixes bug 34400;
+ bugfix on 0.4.1.1-alpha. Patch by Neel Chauhan.
+
+ o Code simplification and refactoring:
+ - Add and use a set of functions to perform down-casts on constant
+ connection and channel pointers. Closes ticket 40046.
+ - Refactor our code that logs descriptions of connections, channels,
+ and the peers on them, to use a single call path. This change
+ enables us to refactor the data types that they use, and eliminates
+ many confusing usages of those types. Closes ticket 40041.
+ - Refactor some common node selection code into a single function.
+ Closes ticket 34200.
+ - Remove the now-redundant 'outbuf_flushlen' field from our
+ connection type. It was previously used for an older version of
+ our rate-limiting logic. Closes ticket 33097.
+ - Rename "fascist_firewall_*" identifiers to "reachable_addr_*"
+ instead, for consistency with other code. Closes ticket 18106.
+ - Rename functions about "advertised" ports which are not in fact
+ guaranteed to return the ports that have been advertised. Closes
+ ticket 40055.
+ - Split implementation of several command line options from
+ options_init_from_torrc into smaller isolated functions. Patch by
+ Daniel Pinto. Closes ticket 40102.
+ - When an extend cell is missing an IPv4 or IPv6 address, fill in
+ the address from the extend info. This is similar to what was done
+ in ticket 33633 for ed25519 keys. Closes ticket 33816. Patch by
+ Neel Chauhan.
+
+ o Deprecated features:
+ - The "non-builtin" argument to the "--dump-config" command is now
+ deprecated. When it works, it behaves the same as "short", which
+ you should use instead. Closes ticket 33398.
+
+ o Documentation:
+ - Replace URLs from our old bugtracker so that they refer to the new
+ bugtracker and wiki. Closes ticket 40101.
+
+ o Removed features:
+ - We no longer ship or build a "tor.service" file for use with
+ systemd. No distribution included this script unmodified, and we
+ don't have the expertise ourselves to maintain this in a way that
+ all the various systemd-based distributions can use. Closes
+ ticket 30797.
+ - We no longer ship support for the Android logging API. Modern
+ versions of Android can use the syslog API instead. Closes
+ ticket 32181.
+ - The "optimistic data" feature is now always on; there is no longer
+ an option to disable it from the torrc file or from the consensus
+ directory. Closes part of 40139.
+ - The "usecreatefast" network parameter is now removed; there is no
+ longer an option for authorities to turn it off. Closes part
+ of 40139.
+
+ o Testing:
+ - Add unit tests for bandwidth statistics manipulation functions.
+ Closes ticket 33812. Patch by MrSquanchee.
+
+ o Code simplification and refactoring (autoconf):
+ - Remove autoconf checks for unused funcs and headers. Closes ticket
+ 31699; Patch by @bduszel
+
+ o Code simplification and refactoring (maintainer scripts):
+ - Disable by default the pre-commit hook. Use the environment
+ variable TOR_EXTRA_PRE_COMMIT_CHECKS in order to run it.
+ Furthermore, stop running practracker in the pre-commit hook and
+ make check-local. Closes ticket 40019.
+
+ o Code simplification and refactoring (relay address):
+ - Most of IPv4 representation was using "uint32_t". It has now been
+ moved to use the internal "tor_addr_t" interface instead. This is
+ so we can properly integrate IPv6 along IPv4 with common
+ interfaces. Closes ticket 40043.
+
+ o Documentation (manual page):
+ - Move them from doc/ to doc/man/. Closes ticket 40044.
+ - Describe the status of the "Sandbox" option more accurately. It is
+ no longer "experimental", but it _is_ dependent on kernel and libc
+ versions. Closes ticket 23378.
+
+ o Documentation (tracing):
+ - Document in depth the circuit subsystem trace events in the new
+ doc/tracing/EventsCircuit.md. Closes ticket 40036.
+
+
+Changes in version 0.4.4.5 - 2020-09-15
+ Tor 0.4.4.5 is the first stable release in the 0.4.4.x series. This
+ series improves our guard selection algorithms, adds v3 onion balance
+ support, improves the amount of code that can be disabled when running
+ without relay support, and includes numerous small bugfixes and
+ enhancements. It also lays the ground for some IPv6 features that
+ we'll be developing more in the next (0.4.5) series.
+
+ Per our support policy, we support each stable release series for nine
+ months after its first stable release, or three months after the first
+ stable release of the next series: whichever is longer. This means
+ that 0.4.4.x will be supported until around June 2021--or later, if
+ 0.4.5.x is later than anticipated.
+
+ Note also that support for 0.4.2.x has just ended; support for 0.4.3
+ will continue until Feb 15, 2021. We still plan to continue supporting
+ 0.3.5.x, our long-term stable series, until Feb 2022.
+
+ Below are the changes since 0.4.4.4-rc. For a complete list of changes
+ since 0.4.3.6, see the ReleaseNotes file.
+
+ o Major bugfixes (onion services, DoS):
+ - Correct handling of parameters for the onion service DoS defense.
+ Previously, the consensus parameters for the onion service DoS
+ defenses were overwriting the parameters set by the service
+ operator using HiddenServiceEnableIntroDoSDefense. Fixes bug
+ 40109; bugfix on 0.4.2.1-alpha.
+
+ o Major bugfixes (stats, onion services):
+ - Fix a bug where we were undercounting the Tor network's total
+ onion service traffic, by ignoring any traffic originating from
+ clients. Now we count traffic from both clients and services.
+ Fixes bug 40117; bugfix on 0.2.6.2-alpha.
+
+ o Minor features (control port):
+ - If a ClientName was specified in ONION_CLIENT_AUTH_ADD for an
+ onion service, display it when we use ONION_CLIENT_AUTH_VIEW.
+ Closes ticket 40089. Patch by Neel Chauhan.
+
+ o Minor features (denial-of-service memory limiter):
+ - Allow the user to configure even lower values for the
+ MaxMemInQueues parameter. Relays now enforce a minimum of 64 MB,
+ when previously the minimum was 256 MB. On clients, there is no
+ minimum. Relays and clients will both warn if the value is set so
+ low that Tor is likely to stop working. Closes ticket 24308.
+
+ o Minor features (tests):
+ - Our "make check" target now runs the unit tests in 8 parallel
+ chunks. Doing this speeds up hardened CI builds by more than a
+ factor of two. Closes ticket 40098.
+
+ o Minor bugfixes (guard selection algorithm):
+ - Avoid needless guard-related warning when upgrading from 0.4.3 to
+ 0.4.4. Fixes bug 40105; bugfix on 0.4.4.1-alpha.
+
+ o Minor bugfixes (tests):
+ - Fix the behavior of the rend_cache/clean_v2_descs_as_dir when run
+ on its own. Previously, it would exit with an error. Fixes bug
+ 40099; bugfix on 0.2.8.1-alpha.
+
+
+Changes in version 0.4.4.3-alpha - 2020-07-27
+ Tor 0.4.4.3-alpha fixes several annoyances in previous versions,
+ including one affecting NSS users, and several affecting the Linux
+ seccomp2 sandbox.
+
+ o Major features (fallback directory list):
+ - Replace the 148 fallback directories originally included in Tor
+ 0.4.1.4-rc (of which around 105 are still functional) with a list
+ of 144 fallbacks generated in July 2020. Closes ticket 40061.
+
+ o Major bugfixes (NSS):
+ - When running with NSS enabled, make sure that NSS knows to expect
+ nonblocking sockets. Previously, we set our TCP sockets as
+ nonblocking, but did not tell NSS, which in turn could lead to
+ unexpected blocking behavior. Fixes bug 40035; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor bugfixes (linux seccomp2 sandbox):
+ - Fix a regression on sandboxing rules for the openat() syscall. The
+ fix for bug 25440 fixed the problem on systems with glibc >= 2.27
+ but broke with versions of glibc. We now choose a rule based on
+ the glibc version. Patch from Daniel Pinto. Fixes bug 27315;
+ bugfix on 0.3.5.11.
+ - Makes the seccomp sandbox allow the correct syscall for opendir
+ according to the running glibc version. This fixes crashes when
+ reloading torrc with sandbox enabled when running on glibc 2.15 to
+ 2.21 and 2.26. Patch from Daniel Pinto. Fixes bug 40020; bugfix
+ on 0.3.5.11.
+
+ o Minor bugfixes (relay, usability):
+ - Adjust the rules for when to warn about having too many
+ connections to other relays. Previously we'd tolerate up to 1.5
+ connections per relay on average. Now we tolerate more connections
+ for directory authorities, and raise the number of total
+ connections we need to see before we warn. Fixes bug 33880; bugfix
+ on 0.3.1.1-alpha.
+
+ o Documentation:
+ - Replace most http:// URLs in our code and documentation with
+ https:// URLs. (We have left unchanged the code in src/ext/, and
+ the text in LICENSE.) Closes ticket 31812. Patch from Jeremy Rand.
+
+ 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.
+
+
+Changes in version 0.3.5.11 - 2020-07-09
+ Tor 0.3.5.11 backports fixes from later tor releases, including several
+ usability, portability, and reliability fixes.
+
+ This release also fixes TROVE-2020-001, a medium-severity denial of
+ service vulnerability affecting all versions of Tor when compiled with
+ the NSS encryption library. (This is not the default configuration.)
+ Using this vulnerability, an attacker could cause an affected Tor
+ instance to crash remotely. This issue is also tracked as CVE-2020-
+ 15572. Anybody running a version of Tor built with the NSS library
+ should upgrade to 0.3.5.11, 0.4.2.8, 0.4.3.6, or 0.4.4.2-alpha
+ or later.
+
+ o Major bugfixes (NSS, security, backport from 0.4.4.2-alpha):
+ - Fix a crash due to an out-of-bound memory access when Tor is
+ compiled with NSS support. Fixes bug 33119; bugfix on
+ 0.3.5.1-alpha. This issue is also tracked as TROVE-2020-001
+ and CVE-2020-15572.
+
+ o Major bugfixes (DoS defenses, bridges, pluggable transport, backport from 0.4.3.4-rc):
+ - Fix a bug that was preventing DoS defenses from running on bridges
+ with a pluggable transport. Previously, the DoS subsystem was not
+ given the transport name of the client connection, thus failed to
+ find the GeoIP cache entry for that client address. Fixes bug
+ 33491; bugfix on 0.3.3.2-alpha.
+
+ o Minor features (testing, backport from 0.4.3.4-rc):
+ - The unit tests now support a "TOR_SKIP_TESTCASES" environment
+ variable to specify a list of space-separated test cases that
+ should not be executed. We will use this to disable certain tests
+ that are failing on Appveyor because of mismatched OpenSSL
+ libraries. Part of ticket 33643.
+
+ o Minor bugfix (CI, Windows, backport from 0.4.4.2-alpha):
+ - Use the correct 64-bit printf format when compiling with MINGW on
+ Appveyor. Fixes bug 40026; bugfix on 0.3.5.5-alpha.
+
+ o Minor bugfix (relay, configuration, backport from 0.4.3.3-alpha):
+ - Warn if the ContactInfo field is not set, and tell the relay
+ operator that not having a ContactInfo field set might cause their
+ relay to get rejected in the future. Fixes bug 33361; bugfix
+ on 0.1.1.10-alpha.
+
+ o Minor bugfixes (client performance, backport from 0.4.4.1-alpha):
+ - Resume use of preemptively-built circuits when UseEntryGuards is set
+ to 0. We accidentally disabled this feature with that config
+ setting, leading to slower load times. Fixes bug 34303; bugfix
+ on 0.3.3.2-alpha.
+
+ o Minor bugfixes (compiler compatibility, backport from 0.4.3.5):
+ - Avoid compiler warnings from Clang 10 related to the use of GCC-
+ style "/* falls through */" comments. Both Clang and GCC allow
+ __attribute__((fallthrough)) instead, so that's what we're using
+ now. Fixes bug 34078; bugfix on 0.3.1.3-alpha.
+
+ o Minor bugfixes (compiler warnings, backport from 0.4.4.2-alpha):
+ - Fix a compiler warning on platforms with 32-bit time_t values.
+ Fixes bug 40028; bugfix on 0.3.2.8-rc.
+
+ o Minor bugfixes (embedded Tor, backport from 0.4.3.1-alpha):
+ - 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 (key portability, backport from 0.4.3.4-rc):
+ - When reading PEM-encoded key data, tolerate CRLF line-endings even
+ if we are not running on Windows. Previously, non-Windows hosts
+ would reject these line-endings in certain positions, making
+ certain key files hard to move from one host to another. Fixes bug
+ 33032; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.4.2-alpha):
+ - Downgrade a noisy log message that could occur naturally when
+ receiving an extrainfo document that we no longer want. Fixes bug
+ 16016; bugfix on 0.2.6.3-alpha.
+
+ o Minor bugfixes (onion service v3, client, backport from 0.4.3.3-alpha):
+ - Remove a BUG() warning that would cause a stack trace if an onion
+ service descriptor was freed while we were waiting for a
+ rendezvous circuit to complete. Fixes bug 28992; bugfix
+ on 0.3.2.1-alpha.
+
+ o Testing (CI, backport from 0.4.3.4-rc):
+ - In our Appveyor Windows CI, copy required DLLs to test and app
+ directories, before running tor's tests. This ensures that tor.exe
+ and test*.exe use the correct version of each DLL. This fix is not
+ required, but we hope it will avoid DLL search issues in future.
+ Fixes bug 33673; bugfix on 0.3.4.2-alpha.
+ - On Appveyor, skip the crypto/openssl_version test, which is
+ failing because of a mismatched library installation. Fix
+ for 33643.
+
+
+Changes in version 0.4.2.8 - 2020-07-09
+ Tor 0.4.2.8 backports various fixes from later releases, including
+ several that affect usability and portability.
+
+ This release also fixes TROVE-2020-001, a medium-severity denial of
+ service vulnerability affecting all versions of Tor when compiled with
+ the NSS encryption library. (This is not the default configuration.)
+ Using this vulnerability, an attacker could cause an affected Tor
+ instance to crash remotely. This issue is also tracked as CVE-2020-
+ 15572. Anybody running a version of Tor built with the NSS library
+ should upgrade to 0.3.5.11, 0.4.2.8, 0.4.3.6, or 0.4.4.2-alpha
+ or later.
+
+ o Major bugfixes (NSS, security, backport from 0.4.4.2-alpha):
+ - Fix a crash due to an out-of-bound memory access when Tor is
+ compiled with NSS support. Fixes bug 33119; bugfix on
+ 0.3.5.1-alpha. This issue is also tracked as TROVE-2020-001
+ and CVE-2020-15572.
+
+ o Major bugfixes (DoS defenses, bridges, pluggable transport, backport from 0.4.3.4-rc):
+ - Fix a bug that was preventing DoS defenses from running on bridges
+ with a pluggable transport. Previously, the DoS subsystem was not
+ given the transport name of the client connection, thus failed to
+ find the GeoIP cache entry for that client address. Fixes bug
+ 33491; bugfix on 0.3.3.2-alpha.
+
+ o Minor feature (sendme, flow control, backport form 0.4.3.4-rc):
+ - Default to sending SENDME version 1 cells. (Clients are already
+ sending these, because of a consensus parameter telling them to do
+ so: this change only affects what clients would do if the
+ consensus didn't contain a recommendation.) Closes ticket 33623.
+
+ o Minor features (diagnostic, backport from 0.4.3.3-alpha):
+ - Improve assertions and add some memory-poisoning code to try to
+ track down possible causes of a rare crash (32564) in the EWMA
+ code. Closes ticket 33290.
+
+ o Minor features (testing, backport from 0.4.3.4-rc):
+ - The unit tests now support a "TOR_SKIP_TESTCASES" environment
+ variable to specify a list of space-separated test cases that
+ should not be executed. We will use this to disable certain tests
+ that are failing on Appveyor because of mismatched OpenSSL
+ libraries. Part of ticket 33643.
+
+ o Minor bugfix (CI, Windows, backport from 0.4.4.2-alpha):
+ - Use the correct 64-bit printf format when compiling with MINGW on
+ Appveyor. Fixes bug 40026; bugfix on 0.3.5.5-alpha.
+
+ o Minor bugfix (relay, configuration, backport from 0.4.3.3-alpha):
+ - Warn if the ContactInfo field is not set, and tell the relay
+ operator that not having a ContactInfo field set might cause their
+ relay to get rejected in the future. Fixes bug 33361; bugfix
+ on 0.1.1.10-alpha.
+
+ o Minor bugfixes (client performance, backport from 0.4.4.1-alpha):
+ - Resume use of preemptively-built circuits when UseEntryGuards is set
+ to 0. We accidentally disabled this feature with that config
+ setting, leading to slower load times. Fixes bug 34303; bugfix
+ on 0.3.3.2-alpha.
+
+ o Minor bugfixes (compiler compatibility, backport from 0.4.3.5):
+ - Avoid compiler warnings from Clang 10 related to the use of GCC-
+ style "/* falls through */" comments. Both Clang and GCC allow
+ __attribute__((fallthrough)) instead, so that's what we're using
+ now. Fixes bug 34078; bugfix on 0.3.1.3-alpha.
+ - Fix compilation warnings with GCC 10.0.1. Fixes bug 34077; bugfix
+ on 0.4.0.3-alpha.
+
+ o Minor bugfixes (compiler warnings, backport from 0.4.4.2-alpha):
+ - Fix a compiler warning on platforms with 32-bit time_t values.
+ Fixes bug 40028; bugfix on 0.3.2.8-rc.
+
+ o Minor bugfixes (controller protocol, backport from 0.4.3.2-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 (embedded Tor, backport from 0.4.3.1-alpha):
+ - 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 (key portability, backport from 0.4.3.4-rc):
+ - When reading PEM-encoded key data, tolerate CRLF line-endings even
+ if we are not running on Windows. Previously, non-Windows hosts
+ would reject these line-endings in certain positions, making
+ certain key files hard to move from one host to another. Fixes bug
+ 33032; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.3.2-rc):
+ - 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 (logging, backport from 0.4.3.4-rc):
+ - 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.
+
+ o Minor bugfixes (logging, backport from 0.4.4.2-alpha):
+ - Downgrade a noisy log message that could occur naturally when
+ receiving an extrainfo document that we no longer want. Fixes bug
+ 16016; bugfix on 0.2.6.3-alpha.
+
+ o Minor bugfixes (onion service v3, client, backport from 0.4.3.3-alpha):
+ - Remove a BUG() warning that would cause a stack trace if an onion
+ service descriptor was freed while we were waiting for a
+ rendezvous circuit to complete. Fixes bug 28992; bugfix
+ on 0.3.2.1-alpha.
+
+ o Testing (CI, backport from 0.4.3.4-rc):
+ - In our Appveyor Windows CI, copy required DLLs to test and app
+ directories, before running tor's tests. This ensures that tor.exe
+ and test*.exe use the correct version of each DLL. This fix is not
+ required, but we hope it will avoid DLL search issues in future.
+ Fixes bug 33673; bugfix on 0.3.4.2-alpha.
+ - On Appveyor, skip the crypto/openssl_version test, which is
+ failing because of a mismatched library installation. Fix
+ for 33643.
+
+
+Changes in version 0.4.3.6 - 2020-07-09
+ Tor 0.4.3.6 backports several bugfixes from later releases, including
+ some affecting usability.
+
+ This release also fixes TROVE-2020-001, a medium-severity denial of
+ service vulnerability affecting all versions of Tor when compiled with
+ the NSS encryption library. (This is not the default configuration.)
+ Using this vulnerability, an attacker could cause an affected Tor
+ instance to crash remotely. This issue is also tracked as CVE-2020-
+ 15572. Anybody running a version of Tor built with the NSS library
+ should upgrade to 0.3.5.11, 0.4.2.8, 0.4.3.6, or 0.4.4.2-alpha
+ or later.
+
+ o Major bugfixes (NSS, security, backport from 0.4.4.2-alpha):
+ - Fix a crash due to an out-of-bound memory access when Tor is
+ compiled with NSS support. Fixes bug 33119; bugfix on
+ 0.3.5.1-alpha. This issue is also tracked as TROVE-2020-001
+ and CVE-2020-15572.
+
+ o Minor bugfix (CI, Windows, backport from 0.4.4.2-alpha):
+ - Use the correct 64-bit printf format when compiling with MINGW on
+ Appveyor. Fixes bug 40026; bugfix on 0.3.5.5-alpha.
+
+ o Minor bugfixes (client performance, backport from 0.4.4.1-alpha):
+ - Resume use of preemptively-built circuits when UseEntryGuards is set
+ to 0. We accidentally disabled this feature with that config
+ setting, leading to slower load times. Fixes bug 34303; bugfix
+ on 0.3.3.2-alpha.
+
+ o Minor bugfixes (compiler warnings, backport from 0.4.4.2-alpha):
+ - Fix a compiler warning on platforms with 32-bit time_t values.
+ Fixes bug 40028; bugfix on 0.3.2.8-rc.
+
+ o Minor bugfixes (linux seccomp sandbox, nss, backport from 0.4.4.1-alpha):
+ - Fix a 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.
+
+ o Minor bugfixes (logging, backport from 0.4.4.2-alpha):
+ - Downgrade a noisy log message that could occur naturally when
+ receiving an extrainfo document that we no longer want. Fixes bug
+ 16016; bugfix on 0.2.6.3-alpha.
+
+ o Minor bugfixes (manual page, backport from 0.4.4.1-alpha):
+ - Update the man page to reflect that MinUptimeHidServDirectoryV2
+ defaults to 96 hours. Fixes bug 34299; bugfix on 0.2.6.3-alpha.
+
+ o Minor bugfixes (onion service v3, backport from 0.4.4.1-alpha):
+ - Prevent an assert() that would occur when cleaning the client
+ descriptor cache, and attempting to close circuits for a non-
+ decrypted descriptor (lacking client authorization). Fixes bug
+ 33458; bugfix on 0.4.2.1-alpha.
+
+ o Minor bugfixes (portability, backport from 0.4.4.1-alpha):
+ - Fix a portability error in the configure script, where we were
+ using "==" instead of "=". Fixes bug 34233; bugfix on 0.4.3.5.
+
+ o Minor bugfixes (relays, backport from 0.4.4.1-alpha):
+ - 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.
+
+ o Documentation (backport from 0.4.4.1-alpha):
+ - Fix several doxygen warnings related to imbalanced groups. Closes
+ ticket 34255.
+
+
+Changes in version 0.4.4.2-alpha - 2020-07-09
+ This is the second alpha release in the 0.4.4.x series. It fixes a few
+ bugs in the previous release, and solves a few usability,
+ compatibility, and portability issues.
+
+ This release also fixes TROVE-2020-001, a medium-severity denial of
+ service vulnerability affecting all versions of Tor when compiled with
+ the NSS encryption library. (This is not the default configuration.)
+ Using this vulnerability, an attacker could cause an affected Tor
+ instance to crash remotely. This issue is also tracked as CVE-2020-
+ 15572. Anybody running a version of Tor built with the NSS library
+ should upgrade to 0.3.5.11, 0.4.2.8, 0.4.3.6, or 0.4.4.2-alpha
+ or later.
+
+ o Major bugfixes (NSS, security):
+ - Fix a crash due to an out-of-bound memory access when Tor is
+ compiled with NSS support. Fixes bug 33119; bugfix on
+ 0.3.5.1-alpha. This issue is also tracked as TROVE-2020-001
+ and CVE-2020-15572.
+
+ o Minor features (bootstrap reporting):
+ - Report more detailed reasons for bootstrap failure when the
+ failure happens due to a TLS error. Previously we would just call
+ these errors "MISC" when they happened during read, and "DONE"
+ when they happened during any other TLS operation. Closes
+ ticket 32622.
+
+ o Minor features (directory authority):
+ - Authorities now recommend the protocol versions that are supported
+ by Tor 0.3.5 and later. (Earlier versions of Tor have been
+ deprecated since January of this year.) This recommendation will
+ cause older clients and relays to give a warning on startup, or
+ when they download a consensus directory. Closes ticket 32696.
+
+ o Minor features (entry guards):
+ - Reinstate support for GUARD NEW/UP/DOWN control port events.
+ Closes ticket 40001.
+
+ o Minor features (linux seccomp2 sandbox, portability):
+ - Allow Tor to build on platforms where it doesn't know how to
+ report which syscall caused the linux seccomp2 sandbox to fail.
+ This change should make the sandbox code more portable to less
+ common Linux architectures. Closes ticket 34382.
+ - Permit the unlinkat() syscall, which some Libc implementations use
+ to implement unlink(). Closes ticket 33346.
+
+ o Minor bugfix (CI, Windows):
+ - Use the correct 64-bit printf format when compiling with MINGW on
+ Appveyor. Fixes bug 40026; bugfix on 0.3.5.5-alpha.
+
+ o Minor bugfix (onion service v3 client):
+ - Remove a BUG() warning that could occur naturally. Fixes bug
+ 34087; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfix (SOCKS, onion service client):
+ - Detect v3 onion service addresses of the wrong length when
+ returning the F6 ExtendedErrors code. Fixes bug 33873; bugfix
+ on 0.4.3.1-alpha.
+
+ o Minor bugfixes (compiler warnings):
+ - Fix a compiler warning on platforms with 32-bit time_t values.
+ Fixes bug 40028; bugfix on 0.3.2.8-rc.
+
+ o Minor bugfixes (control port, onion service):
+ - Consistently use 'address' in "Invalid v3 address" response to
+ ONION_CLIENT_AUTH commands. Previously, we would sometimes say
+ 'addr'. Fixes bug 40005; bugfix on 0.4.3.1-alpha.
+
+ o Minor bugfixes (logging):
+ - Downgrade a noisy log message that could occur naturally when
+ receiving an extrainfo document that we no longer want. Fixes bug
+ 16016; bugfix on 0.2.6.3-alpha.
+
+ o Minor bugfixes (onion services v3):
+ - Avoid a non-fatal assertion failure in certain edge-cases when
+ opening an intro circuit as a client. Fixes bug 34084; bugfix
+ on 0.3.2.1-alpha.
+
+ o Deprecated features (onion service v2):
+ - Add a deprecation warning for version 2 onion services. Closes
+ ticket 40003.
+
+ o Removed features (IPv6, revert):
+ - Revert the change in the default value of ClientPreferIPv6OrPort:
+ it breaks the torsocks use case. The SOCKS resolve command has no
+ mechanism to ask for a specific address family (v4 or v6), and so
+ prioritizing IPv6 when an IPv4 address is requested on the SOCKS
+ interface resulted in a failure. Tor Browser explicitly sets
+ PreferIPv6, so this should not affect the majority of our users.
+ Closes ticket 33796; bugfix on 0.4.4.1-alpha.
+
+
+Changes in version 0.4.4.1-alpha - 2020-06-16
+ This is the first alpha release in the 0.4.4.x series. It improves
+ our guard selection algorithms, improves the amount of code that
+ can be disabled when running without relay support, and includes numerous
+ small bugfixes and enhancements. It also lays the ground for some IPv6
+ features that we'll be developing more in the next (0.4.5) series.
+
+ Here are the changes since 0.4.3.5.
+
+ o Major features (Proposal 310, performance + security):
+ - Implements Proposal 310, "Bandaid on guard selection". Proposal
+ 310 solves load-balancing issues with older versions of the guard
+ selection algorithm, and improves its security. Under this new
+ algorithm, a newly selected guard never becomes Primary unless all
+ previously sampled guards are unreachable. Implements
+ recommendation from 32088. (Proposal 310 is linked to the CLAPS
+ project researching optimal client location-aware path selections.
+ This project is a collaboration between the UCLouvain Crypto Group,
+ the U.S. Naval Research Laboratory, and Princeton University.)
+
+ o Major features (IPv6, relay):
+ - Consider IPv6-only EXTEND2 cells valid on relays. Log a protocol
+ warning if the IPv4 or IPv6 address is an internal address, and
+ internal addresses are not allowed. But continue to use the other
+ address, if it is valid. Closes ticket 33817.
+ - If a relay can extend over IPv4 and IPv6, and both addresses are
+ provided, it chooses between them uniformly at random. Closes
+ ticket 33817.
+ - Re-use existing IPv6 connections for circuit extends. Closes
+ ticket 33817.
+ - Relays may extend circuits over IPv6, if the relay has an IPv6
+ ORPort, and the client supplies the other relay's IPv6 ORPort in
+ the EXTEND2 cell. IPv6 extends will be used by the relay IPv6
+ ORPort self-tests in 33222. Closes ticket 33817.
+
+ o Major features (v3 onion services):
+ - Allow v3 onion services to act as OnionBalance backend instances,
+ by using the HiddenServiceOnionBalanceInstance torrc option.
+ Closes ticket 32709.
+
+ o Minor feature (developer tools):
+ - Add a script to help check the alphabetical ordering of option
+ names in the manual page. Closes ticket 33339.
+
+ o Minor feature (onion service client, SOCKS5):
+ - Add 3 new SocksPort ExtendedErrors (F2, F3, F7) that reports back
+ new type of onion service connection failures. The semantics of
+ these error codes are documented in proposal 309. Closes
+ ticket 32542.
+
+ o Minor feature (onion service v3):
+ - If a service cannot upload its descriptor(s), log why at INFO
+ level. Closes ticket 33400; bugfix on 0.3.2.1-alpha.
+
+ o Minor feature (python scripts):
+ - Stop assuming that /usr/bin/python exists. Instead of using a
+ hardcoded path in scripts that still use Python 2, use
+ /usr/bin/env, similarly to the scripts that use Python 3. Fixes
+ bug 33192; bugfix on 0.4.2.
+
+ o Minor features (client-only compilation):
+ - Disable more code related to the ext_orport protocol when
+ compiling without support for relay mode. Closes ticket 33368.
+ - Disable more of our self-testing code when support for relay mode
+ is disabled. Closes ticket 33370.
+
+ o Minor features (code safety):
+ - Check for failures of tor_inet_ntop() and tor_inet_ntoa()
+ functions in DNS and IP address processing code, and adjust
+ codepaths to make them less likely to crash entire Tor instances.
+ Resolves issue 33788.
+
+ o Minor features (compilation size):
+ - Most server-side DNS code is now disabled when building without
+ support for relay mode. Closes ticket 33366.
+
+ o Minor features (continuous integration):
+ - Run unit-test and integration test (Stem, Chutney) jobs with
+ ALL_BUGS_ARE_FATAL macro being enabled on Travis and Appveyor.
+ Resolves ticket 32143.
+
+ o Minor features (control port):
+ - Return a descriptive error message from the 'GETINFO status/fresh-
+ relay-descs' command on the control port. Previously, we returned
+ a generic error of "Error generating descriptor". Closes ticket
+ 32873. Patch by Neel Chauhan.
+
+ o Minor features (developer tooling):
+ - Refrain from listing all .a files that are generated by the Tor
+ build in .gitignore. Add a single wildcard *.a entry that covers
+ all of them for present and future. Closes ticket 33642.
+ - Add a script ("git-install-tools.sh") to install git hooks and
+ helper scripts. Closes ticket 33451.
+
+ o Minor features (directory authority, shared random):
+ - Refactor more authority-only parts of the shared-random scheduling
+ code to reside in the dirauth module, and to be disabled when
+ compiling with --disable-module-dirauth. Closes ticket 33436.
+
+ o Minor features (directory):
+ - Remember the number of bytes we have downloaded for each directory
+ purpose while bootstrapping, and while fully bootstrapped. Log
+ this information as part of the heartbeat message. Closes
+ ticket 32720.
+
+ o Minor features (IPv6 support):
+ - Adds IPv6 support to tor_addr_is_valid(). Adds tests for the above
+ changes and tor_addr_is_null(). Closes ticket 33679. Patch
+ by MrSquanchee.
+ - Allow clients and relays to send dual-stack and IPv6-only EXTEND2
+ cells. Parse dual-stack and IPv6-only EXTEND2 cells on relays.
+ Closes ticket 33901.
+
+ o Minor features (logging):
+ - When trying to find our own address, add debug-level logging to
+ report the sources of candidate addresses. Closes ticket 32888.
+
+ o Minor features (testing, architecture):
+ - Our test scripts now double-check that subsystem initialization
+ order is consistent with the inter-module dependencies established
+ by our .may_include files. Implements ticket 31634.
+ - Initialize all subsystems at the beginning of our unit test
+ harness, to avoid crashes due to uninitialized subsystems. Follow-
+ up from ticket 33316.
+
+ o Minor features (v3 onion services):
+ - Add v3 onion service status to the dumpstats() call which is
+ triggered by a SIGUSR1 signal. Previously, we only did v2 onion
+ services. Closes ticket 24844. Patch by Neel Chauhan.
+
+ o Minor features (windows):
+ - Add support for console control signals like Ctrl+C in Windows.
+ Closes ticket 34211. Patch from Damon Harris (TheDcoder).
+
+ o Minor bugfix (onion service v3):
+ - Prevent an assert() that would occur when cleaning the client
+ descriptor cache, and attempting to close circuits for a non-
+ decrypted descriptor (lacking client authorization). Fixes bug
+ 33458; bugfix on 0.4.2.1-alpha.
+
+ o Minor bugfix (refactoring):
+ - Lift circuit_build_times_disabled() out of the
+ circuit_expire_building() loop, to save CPU time when there are
+ many circuits open. Fixes bug 33977; bugfix on 0.3.5.9.
+
+ o Minor bugfixes (client performance):
+ - Resume use of preemptively-built circuits when UseEntryGuards is set
+ to 0. We accidentally disabled this feature with that config
+ setting, leading to slower load times. Fixes bug 34303; bugfix
+ on 0.3.3.2-alpha.
+
+ o Minor bugfixes (directory authorities):
+ - Directory authorities now reject votes that arrive too late. In
+ particular, once an authority has started fetching missing votes,
+ it no longer accepts new votes posted by other authorities. This
+ change helps prevent a consensus split, where only some authorities
+ have the late vote. Fixes bug 4631; bugfix on 0.2.0.5-alpha.
+
+ o Minor bugfixes (git scripts):
+ - Stop executing the checked-out pre-commit hook from the pre-push
+ hook. Instead, execute the copy in the user's git directory. Fixes
+ bug 33284; bugfix on 0.4.1.1-alpha.
+
+ o Minor bugfixes (initialization):
+ - Initialize the subsystems in our code in an order more closely
+ corresponding to their dependencies, so that every system is
+ initialized before the ones that (theoretically) depend on it.
+ Fixes bug 33316; bugfix on 0.4.0.1-alpha.
+
+ o Minor bugfixes (IPv4, relay):
+ - Check for invalid zero IPv4 addresses and ports when sending and
+ receiving extend cells. Fixes bug 33900; bugfix on 0.2.4.8-alpha.
+
+ o Minor bugfixes (IPv6, relay):
+ - Consider IPv6 addresses when checking if a connection is
+ canonical. In 17604, relays assumed that a remote relay could
+ consider an IPv6 connection canonical, but did not set the
+ canonical flag on their side of the connection. Fixes bug 33899;
+ bugfix on 0.3.1.1-alpha.
+ - Log IPv6 addresses on connections where this relay is the
+ responder. Previously, responding relays would replace the remote
+ IPv6 address with the IPv4 address from the consensus. Fixes bug
+ 33899; bugfix on 0.3.1.1-alpha.
+
+ o Minor bugfixes (linux seccomp sandbox nss):
+ - Fix a 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.
+
+ o Minor bugfixes (logging, testing):
+ - Make all of tor's assertion macros support the ALL_BUGS_ARE_FATAL
+ and DISABLE_ASSERTS_IN_UNIT_TESTS debugging modes. (IF_BUG_ONCE()
+ used to log a non-fatal warning, regardless of the debugging
+ mode.) Fixes bug 33917; bugfix on 0.2.9.1-alpha.
+
+ o Minor bugfixes (logs):
+ - Remove surprising empty line in the INFO-level log about circuit
+ build timeout. Fixes bug 33531; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (mainloop):
+ - Better guard against growing a buffer past its maximum 2GB in
+ size. Fixes bug 33131; bugfix on 0.3.0.4-rc.
+
+ o Minor bugfixes (manual page):
+ - Update the man page to reflect that MinUptimeHidServDirectoryV2
+ defaults to 96 hours. Fixes bug 34299; bugfix on 0.2.6.3-alpha.
+
+ o Minor bugfixes (onion service v3, client):
+ - Remove a BUG() that was causing a stacktrace when a descriptor
+ changed at an unexpected time. Fixes bug 28992; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor bugfixes (onion service, logging):
+ - Fix a typo in a log message PublishHidServDescriptors is set to 0.
+ Fixes bug 33779; bugfix on 0.3.2.1-alpha.
+
+ 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.
+
+ o Minor bugfixes (protocol versions):
+ - Sort tor's supported protocol version lists, as recommended by the
+ tor directory specification. Fixes bug 33285; bugfix
+ on 0.4.0.1-alpha.
+
+ 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.
+
+ o Code simplification and refactoring:
+ - Define and use a new constant TOR_ADDRPORT_BUF_LEN which is like
+ TOR_ADDR_BUF_LEN but includes enough space for an IP address,
+ brackets, separating colon, and port number. Closes ticket 33956.
+ Patch by Neel Chauhan.
+ - Merge the orconn and ocirc events into the "core" subsystem, which
+ manages or connections and origin circuits. Previously they were
+ isolated in subsystems of their own.
+ - Move LOG_PROTOCOL_WARN to app/config. Resolves a dependency
+ inversion. Closes ticket 33633.
+ - Move the circuit extend code to the relay module. Split the
+ circuit extend function into smaller functions. Closes
+ ticket 33633.
+ - Rewrite port_parse_config() to use the default port flags from
+ port_cfg_new(). Closes ticket 32994. Patch by MrSquanchee.
+ - Updated comments in 'scheduler.c' to reflect old code changes, and
+ simplified the scheduler channel state change code. Closes
+ ticket 33349.
+
+ o Documentation:
+ - Document the limitations of using %include on config files with
+ seccomp sandbox enabled. Fixes documentation bug 34133; bugfix on
+ 0.3.1.1-alpha. Patch by Daniel Pinto.
+ - Fix several doxygen warnings related to imbalanced groups. Closes
+ ticket 34255.
+
+ o Removed features:
+ - Remove the ClientAutoIPv6ORPort option. This option attempted to
+ randomly choose between IPv4 and IPv6 for client connections, and
+ wasn't a true implementation of Happy Eyeballs. Often, this option
+ failed on IPv4-only or IPv6-only connections. Closes ticket 32905.
+ Patch by Neel Chauhan.
+ - Stop shipping contrib/dist/rc.subr file, as it is not being used
+ on FreeBSD anymore. Closes issue 31576.
+
+ o Testing:
+ - Add a basic IPv6 test to "make test-network". This test only runs
+ when the local machine has an IPv6 stack. Closes ticket 33300.
+ - Add test-network-ipv4 and test-network-ipv6 jobs to the Makefile.
+ These jobs run the IPv4-only and dual-stack chutney flavours from
+ test-network-all. Closes ticket 33280.
+ - Remove a redundant distcheck job. Closes ticket 33194.
+ - Run the test-network-ipv6 Makefile target in the Travis CI IPv6
+ chutney job. This job runs on macOS, so it's a bit slow. Closes
+ ticket 33303.
+ - Sort the Travis jobs in order of speed. Putting the slowest jobs
+ first takes full advantage of Travis job concurrency. Closes
+ ticket 33194.
+ - Stop allowing the Chutney IPv6 Travis job to fail. This job was
+ previously configured to fast_finish (which requires
+ allow_failure), to speed up the build. Closes ticket 33195.
+ - Test v3 onion services to tor's mixed IPv4 chutney network. And
+ add a mixed IPv6 chutney network. These networks are used in the
+ test-network-all, test-network-ipv4, and test-network-ipv6 make
+ targets. Closes ticket 33334.
+ - Use the "bridges+hs-v23" chutney network flavour in "make test-
+ network". This test requires a recent version of chutney (mid-
+ February 2020). Closes ticket 28208.
+ - When a Travis chutney job fails, use chutney's new "diagnostics.sh"
+ tool to produce detailed diagnostic output. Closes ticket 32792.
+
+ o Code simplification and refactoring (onion service):
+ - Refactor configuration parsing to use the new config subsystem
+ code. Closes ticket 33014.
+
+ o Code simplification and refactoring (relay address):
+ - Move a series of functions related to address resolving into their
+ own files. Closes ticket 33789.
+
+ o Documentation (manual page):
+ - Add cross reference links and a table of contents to the HTML tor
+ manual page. Closes ticket 33369. Work by Swati Thacker as part of
+ Google Season of Docs.
+ - Alphabetize the Denial of Service Mitigation Options, Directory
+ Authority Server Options, Hidden Service Options, and Testing
+ Network Options sections of the tor(1) manual page. Closes ticket
+ 33275. Work by Swati Thacker as part of Google Season of Docs.
+ - Refrain from mentioning nicknames in manpage section for MyFamily
+ torrc option. Resolves issue 33417.
+ - Updated the options set by TestingTorNetwork in the manual page.
+ Closes ticket 33778.
+
+
Changes in version 0.4.3.5 - 2020-05-15
Tor 0.4.3.5 is the first stable release in the 0.4.3.x series. This
series adds support for building without relay code enabled, and
@@ -27991,7 +29517,7 @@ Changes in version 0.2.0.33 - 2009-01-21
- Implement the 0x20 hack to better resist DNS poisoning: set the
case on outgoing DNS requests randomly, and reject responses that do
not match the case correctly. This logic can be disabled with the
- ServerDNSRamdomizeCase setting, if you are using one of the 0.3%
+ ServerDNSRandomizeCase setting, if you are using one of the 0.3%
of servers that do not reliably preserve case in replies. See
"Increased DNS Forgery Resistance through 0x20-Bit Encoding"
for more info.
diff --git a/Doxyfile.in b/Doxyfile.in
index 503c1302db..4374e54858 100644
--- a/Doxyfile.in
+++ b/Doxyfile.in
@@ -863,7 +863,8 @@ RECURSIVE = YES
# Note that relative paths are relative to the directory from which doxygen is
# run.
-EXCLUDE = ./src/ext \
+EXCLUDE = ./src/ext/ed25519 \
+ ./src/ext/rust \
./src/trunnel \
./src/test \
./src/rust/registry
diff --git a/Makefile.am b/Makefile.am
index a212ae19c6..3056b08446 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,6 +14,7 @@ CLEANFILES=
TESTS=
noinst_PROGRAMS=
DISTCLEANFILES=
+MOSTLYCLEANFILES=
bin_SCRIPTS=
AM_CPPFLAGS=\
-I$(top_srcdir)/src \
@@ -72,7 +73,8 @@ TOR_UTIL_LIBS = \
src/lib/libtor-version.a \
src/lib/libtor-llharden.a \
src/lib/libtor-intmath.a \
- src/lib/libtor-ctime.a
+ src/lib/libtor-ctime.a \
+ src/lib/libtor-metrics.a
# Variants of the above for linking the testing variant of tor (for coverage
# and tests)
@@ -107,7 +109,8 @@ TOR_UTIL_TESTING_LIBS = \
src/lib/libtor-version-testing.a \
src/lib/libtor-llharden-testing.a \
src/lib/libtor-intmath.a \
- src/lib/libtor-ctime-testing.a
+ src/lib/libtor-ctime-testing.a \
+ src/lib/libtor-metrics-testing.a
endif
# Internal crypto libraries used in Tor
@@ -137,6 +140,14 @@ TOR_INTERNAL_LIBS = \
src/trunnel/libor-trunnel.a \
src/lib/libtor-trace.a
+libtor.a: $(TOR_INTERNAL_LIBS)
+ $(AM_V_AR) export AR="$(AR)"; \
+ export ARFLAGS="$(ARFLAGS)"; \
+ export RANLIB="$(RANLIB)"; \
+ $(top_srcdir)/scripts/build/combine_libs libtor.a $(TOR_INTERNAL_LIBS)
+
+MOSTLYCLEANFILES += libtor.a
+
# Variants of the above for linking the testing variant of tor (for coverage
# and tests)
if UNITTESTS_ENABLED
@@ -148,6 +159,14 @@ TOR_INTERNAL_TESTING_LIBS = \
$(TOR_UTIL_TESTING_LIBS) \
src/trunnel/libor-trunnel-testing.a \
src/lib/libtor-trace.a
+
+src/test/libtor-testing.a: $(TOR_INTERNAL_TESTING_LIBS)
+ $(AM_V_AR) export AR="$(AR)"; \
+ export ARFLAGS="$(ARFLAGS)"; \
+ export RANLIB="$(RANLIB)"; \
+ $(top_srcdir)/scripts/build/combine_libs src/test/libtor-testing.a $(TOR_INTERNAL_TESTING_LIBS)
+
+MOSTLYCLEANFILES += src/test/libtor-testing.a
endif
TOR_LDFLAGS_CRYPTLIB=@TOR_LDFLAGS_openssl@
@@ -175,6 +194,7 @@ EXTRA_DIST+= \
Makefile.nmake \
README \
ReleaseNotes \
+ scripts/build/combine_libs \
scripts/maint/checkIncludes.py \
scripts/maint/checkSpace.pl \
scripts/maint/checkSpaceTest.sh \
@@ -701,10 +721,10 @@ show-distdir-core:
file $(distdir)/_build/core; fi
show-libs:
- @echo $(TOR_INTERNAL_LIBS)
+ @echo libtor.a
show-testing-libs:
- @echo $(TOR_INTERNAL_TESTING_LIBS)
+ @echo src/test/libtor-testing.a
# Note here that we hardcode this -j2 because if the user would pass too many
# cores, bear actually chockes and dies :S. For this to work, a make clean
diff --git a/README b/README
index 9bbf027d70..397f6b927e 100644
--- a/README
+++ b/README
@@ -19,13 +19,13 @@ Documentation, including links to installation and setup instructions:
https://www.torproject.org/docs/documentation.html
Making applications work with Tor:
- https://wiki.torproject.org/projects/tor/wiki/doc/TorifyHOWTO
+ https://gitlab.torproject.org/legacy/trac/-/wikis/doc/TorifyHOWTO
Frequently Asked Questions:
https://www.torproject.org/docs/faq.html
Release timeline:
- https://trac.torproject.org/projects/tor/wiki/org/teams/NetworkTeam/CoreTorReleases
+ https://gitlab.torproject.org/tpo/core/team/-/wikis/NetworkTeam/CoreTorReleases
To get started working on Tor development:
See the doc/HACKING directory.
diff --git a/ReleaseNotes b/ReleaseNotes
index a572293c07..2ce9ceaa90 100644
--- a/ReleaseNotes
+++ b/ReleaseNotes
@@ -2,6 +2,1017 @@ 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.4.6 - 2020-11-12
+ Tor 0.4.4.6 is the second stable release in the 0.4.4.x series. It
+ backports fixes from later releases, including a fix for TROVE-2020-
+ 005, a security issue that could be used, under certain cases, by an
+ adversary to observe traffic patterns on a limited number of circuits
+ intended for a different relay.
+
+ o Major bugfixes (security, backport from 0.4.5.1-alpha):
+ - When completing a channel, relays now check more thoroughly to
+ make sure that it matches any pending circuits before attaching
+ those circuits. Previously, address correctness and Ed25519
+ identities were not checked in this case, but only when extending
+ circuits on an existing channel. Fixes bug 40080; bugfix on
+ 0.2.7.2-alpha. Resolves TROVE-2020-005.
+
+ o Minor features (directory authorities, backport from 0.4.5.1-alpha):
+ - Authorities now list a different set of protocols as required and
+ recommended. These lists have been chosen so that only truly
+ recommended and/or required protocols are included, and so that
+ clients using 0.2.9 or later will continue to work (even though
+ they are not supported), whereas only relays running 0.3.5 or
+ later will meet the requirements. Closes ticket 40162.
+ - Make it possible to specify multiple ConsensusParams torrc lines.
+ Now directory authority operators can for example put the main
+ ConsensusParams config in one torrc file and then add to it from a
+ different torrc file. Closes ticket 40164.
+
+ o Minor features (subprotocol versions, backport from 0.4.5.1-alpha):
+ - Tor no longer allows subprotocol versions larger than 63.
+ Previously version numbers up to UINT32_MAX were allowed, which
+ significantly complicated our code. Implements proposal 318;
+ closes ticket 40133.
+
+ o Minor features (tests, v2 onion services, backport from 0.4.5.1-alpha):
+ - Fix a rendezvous cache unit test that was triggering an underflow
+ on the global rend cache allocation. Fixes bug 40125; bugfix
+ on 0.2.8.1-alpha.
+ - Fix another rendezvous cache unit test that was triggering an
+ underflow on the global rend cache allocation. Fixes bug 40126;
+ bugfix on 0.2.8.1-alpha.
+
+ o Minor bugfixes (compilation, backport from 0.4.5.1-alpha):
+ - Fix compiler warnings that would occur when building with
+ "--enable-all-bugs-are-fatal" and "--disable-module-relay" at the
+ same time. Fixes bug 40129; bugfix on 0.4.4.1-alpha.
+ - Resolve a compilation warning that could occur in
+ test_connection.c. Fixes bug 40113; bugfix on 0.2.9.3-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.5.1-alpha):
+ - Remove a debug logging statement that uselessly spammed the logs.
+ Fixes bug 40135; bugfix on 0.3.5.0-alpha.
+
+ o Minor bugfixes (relay configuration, crash, backport from 0.4.5.1-alpha):
+ - Avoid a fatal assert() when failing to create a listener
+ connection for an address that was in use. Fixes bug 40073; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor bugfixes (v2 onion services, backport from 0.4.5.1-alpha):
+ - For HSFETCH commands on v2 onion services addresses, check the
+ length of bytes decoded, not the base32 length. Fixes bug 34400;
+ bugfix on 0.4.1.1-alpha. Patch by Neel Chauhan.
+
+
+Changes in version 0.4.3.7 - 2020-11-12
+ Tor 0.4.3.7 backports several bugfixes from later releases. It
+ includes a fix for TROVE-2020-005, a security issue that could be
+ used, under certain cases, by an adversary to observe traffic patterns
+ on a limited number of circuits intended for a different relay.
+
+ Please be aware that support for the 0.4.3.x series will end on 15
+ February 2021. Please upgrade to 0.4.4.x or 0.4.5.x before then, or
+ downgrade to 0.3.5.x, which will be supported until at least 1
+ February 2022.
+
+ o Major features (fallback directory list, backport form 0.4.4.3-alpha):
+ - Replace the 148 fallback directories originally included in Tor
+ 0.4.1.4-rc (of which around 105 are still functional) with a list
+ of 144 fallbacks generated in July 2020. Closes ticket 40061.
+
+ o Major bugfixes (security, backport from 0.4.5.1-alpha):
+ - When completing a channel, relays now check more thoroughly to
+ make sure that it matches any pending circuits before attaching
+ those circuits. Previously, address correctness and Ed25519
+ identities were not checked in this case, but only when extending
+ circuits on an existing channel. Fixes bug 40080; bugfix on
+ 0.2.7.2-alpha. Resolves TROVE-2020-005.
+
+ o Major bugfixes (NSS, backport from 0.4.4.3-alpha):
+ - When running with NSS enabled, make sure that NSS knows to expect
+ nonblocking sockets. Previously, we set our TCP sockets as
+ nonblocking, but did not tell NSS, which in turn could lead to
+ unexpected blocking behavior. Fixes bug 40035; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor features (security, backport from 0.4.4.4-rc):
+ - Channels using obsolete versions of the Tor link protocol are no
+ longer allowed to circumvent address-canonicity checks. (This is
+ only a minor issue, since such channels have no way to set ed25519
+ keys, and therefore should always be rejected for circuits that
+ specify ed25519 identities.) Closes ticket 40081.
+
+ o Minor features (subprotocol versions, backport from 0.4.5.1-alpha):
+ - Tor no longer allows subprotocol versions larger than 63.
+ Previously version numbers up to UINT32_MAX were allowed, which
+ significantly complicated our code. Implements proposal 318;
+ closes ticket 40133.
+
+ o Minor features (tests, backport from 0.4.4.5):
+ - Our "make check" target now runs the unit tests in 8 parallel
+ chunks. Doing this speeds up hardened CI builds by more than a
+ factor of two. Closes ticket 40098.
+
+ o Minor features (tests, v2 onion services, backport from 0.4.5.1-alpha):
+ - Fix a rendezvous cache unit test that was triggering an underflow
+ on the global rend cache allocation. Fixes bug 40125; bugfix
+ on 0.2.8.1-alpha.
+ - Fix another rendezvous cache unit test that was triggering an
+ underflow on the global rend cache allocation. Fixes bug 40126;
+ bugfix on 0.2.8.1-alpha.
+
+ o Minor bugfixes (correctness, buffers, backport from 0.4.4.4-rc):
+ - Fix a correctness bug that could cause an assertion failure if we
+ ever tried using the buf_move_all() function with an empty input
+ buffer. As far as we know, no released versions of Tor do this.
+ Fixes bug 40076; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.5.1-alpha):
+ - Remove a debug logging statement that uselessly spammed the logs.
+ Fixes bug 40135; bugfix on 0.3.5.0-alpha.
+
+ o Minor bugfixes (rate limiting, bridges, pluggable transports, backport from 0.4.4.4-rc):
+ - On a bridge, treat all connections from an ExtORPort as remote by
+ default for the purposes of rate-limiting. Previously, bridges
+ would treat the connection as local unless they explicitly
+ received a "USERADDR" command. ExtORPort connections still count
+ as local if there is a USERADDR command with an explicit local
+ address. Fixes bug 33747; bugfix on 0.2.5.1-alpha.
+
+ o Minor bugfixes (relay configuration, crash, backport from 0.4.5.1-alpha):
+ - Avoid a fatal assert() when failing to create a listener
+ connection for an address that was in use. Fixes bug 40073; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor bugfixes (relay, usability, backport from 0.4.4.3-alpha):
+ - Adjust the rules for when to warn about having too many
+ connections to other relays. Previously we'd tolerate up to 1.5
+ connections per relay on average. Now we tolerate more connections
+ for directory authorities, and raise the number of total
+ connections we need to see before we warn. Fixes bug 33880; bugfix
+ on 0.3.1.1-alpha.
+
+ o Minor bugfixes (tests, 0.4.4.5):
+ - Fix the behavior of the rend_cache/clean_v2_descs_as_dir when run
+ on its own. Previously, it would exit with an error. Fixes bug
+ 40099; bugfix on 0.2.8.1-alpha.
+
+ o Minor bugfixes (v2 onion services, backport from 0.4.5.1-alpha):
+ - For HSFETCH commands on v2 onion services addresses, check the
+ length of bytes decoded, not the base32 length. Fixes bug 34400;
+ bugfix on 0.4.1.1-alpha. Patch by Neel Chauhan.
+
+ o Minor bugfixes (windows, backport from 0.4.4.4-rc):
+ - Fix a bug that prevented Tor from starting if its log file grew
+ above 2GB. Fixes bug 31036; bugfix on 0.2.1.8-alpha.
+
+ o Deprecated features (onion service v2, backport form 0.4.4.2-alpha):
+ - Add a deprecation warning for version 2 onion services. Closes
+ ticket 40003.
+
+ o Removed features (backport from 0.4.4.3-alpha):
+ - 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. ticket 40030.
+
+
+Changes in version 0.3.5.12 - 2020-11-12
+ Tor 0.4.3.7 backports several bugfixes from later releases. It
+ includes a fix for TROVE-2020-005, a security issue that could be
+ used, under certain cases, by an adversary to observe traffic patterns
+ on a limited number of circuits intended for a different relay.
+
+ o Major features (fallback directory list, backport form 0.4.4.3-alpha):
+ - Replace the 148 fallback directories originally included in Tor
+ 0.4.1.4-rc (of which around 105 are still functional) with a list
+ of 144 fallbacks generated in July 2020. Closes ticket 40061.
+
+ o Major bugfixes (security, backport from 0.4.5.1-alpha):
+ - When completing a channel, relays now check more thoroughly to
+ make sure that it matches any pending circuits before attaching
+ those circuits. Previously, address correctness and Ed25519
+ identities were not checked in this case, but only when extending
+ circuits on an existing channel. Fixes bug 40080; bugfix on
+ 0.2.7.2-alpha. Resolves TROVE-2020-005.
+
+ o Major bugfixes (NSS, backport from 0.4.4.3-alpha):
+ - When running with NSS enabled, make sure that NSS knows to expect
+ nonblocking sockets. Previously, we set our TCP sockets as
+ nonblocking, but did not tell NSS, which in turn could lead to
+ unexpected blocking behavior. Fixes bug 40035; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor features (security, backport from 0.4.4.4-rc):
+ - Channels using obsolete versions of the Tor link protocol are no
+ longer allowed to circumvent address-canonicity checks. (This is
+ only a minor issue, since such channels have no way to set ed25519
+ keys, and therefore should always be rejected for circuits that
+ specify ed25519 identities.) Closes ticket 40081.
+
+ 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 (subprotocol versions, backport from 0.4.5.1-alpha):
+ - Tor no longer allows subprotocol versions larger than 63.
+ Previously version numbers up to UINT32_MAX were allowed, which
+ significantly complicated our code. Implements proposal 318;
+ closes ticket 40133.
+
+ o Minor features (tests, backport from 0.4.4.5):
+ - Our "make check" target now runs the unit tests in 8 parallel
+ chunks. Doing this speeds up hardened CI builds by more than a
+ factor of two. Closes ticket 40098.
+
+ o Minor features (tests, v2 onion services, backport from 0.4.5.1-alpha):
+ - Fix a rendezvous cache unit test that was triggering an underflow
+ on the global rend cache allocation. Fixes bug 40125; bugfix
+ on 0.2.8.1-alpha.
+ - Fix another rendezvous cache unit test that was triggering an
+ underflow on the global rend cache allocation. Fixes bug 40126;
+ bugfix on 0.2.8.1-alpha.
+
+ o Minor bugfixes (correctness, buffers, backport from 0.4.4.4-rc):
+ - Fix a correctness bug that could cause an assertion failure if we
+ ever tried using the buf_move_all() function with an empty input
+ buffer. As far as we know, no released versions of Tor do this.
+ Fixes bug 40076; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.5.1-alpha):
+ - Remove a debug logging statement that uselessly spammed the logs.
+ Fixes bug 40135; bugfix on 0.3.5.0-alpha.
+
+ o Minor bugfixes (rate limiting, bridges, pluggable transports, backport from 0.4.4.4-rc):
+ - On a bridge, treat all connections from an ExtORPort as remote by
+ default for the purposes of rate-limiting. Previously, bridges
+ would treat the connection as local unless they explicitly
+ received a "USERADDR" command. ExtORPort connections still count
+ as local if there is a USERADDR command with an explicit local
+ address. Fixes bug 33747; bugfix on 0.2.5.1-alpha.
+
+ o Minor bugfixes (relay configuration, crash, backport from 0.4.5.1-alpha):
+ - Avoid a fatal assert() when failing to create a listener
+ connection for an address that was in use. Fixes bug 40073; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor bugfixes (relay, usability, backport from 0.4.4.3-alpha):
+ - Adjust the rules for when to warn about having too many
+ connections to other relays. Previously we'd tolerate up to 1.5
+ connections per relay on average. Now we tolerate more connections
+ for directory authorities, and raise the number of total
+ connections we need to see before we warn. Fixes bug 33880; bugfix
+ on 0.3.1.1-alpha.
+
+ o Minor bugfixes (relays, backport from 0.4.4.1-alpha):
+ - 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.
+
+ o Minor bugfixes (tests, 0.4.4.5):
+ - Fix the behavior of the rend_cache/clean_v2_descs_as_dir when run
+ on its own. Previously, it would exit with an error. Fixes bug
+ 40099; bugfix on 0.2.8.1-alpha.
+
+ o Minor bugfixes (windows, backport from 0.4.4.4-rc):
+ - Fix a bug that prevented Tor from starting if its log file grew
+ above 2GB. Fixes bug 31036; bugfix on 0.2.1.8-alpha.
+
+ o Deprecated features (onion service v2, backport form 0.4.4.2-alpha):
+ - Add a deprecation warning for version 2 onion services. Closes
+ ticket 40003.
+
+Changes in version 0.4.4.5 - 2020-09-15
+ Tor 0.4.4.5 is the first stable release in the 0.4.4.x series. This
+ series improves our guard selection algorithms, adds v3 onion balance
+ support, improves the amount of code that can be disabled when running
+ without relay support, and includes numerous small bugfixes and
+ enhancements. It also lays the ground for some IPv6 features that
+ we'll be developing more in the next (0.4.5) series.
+
+ Per our support policy, we support each stable release series for nine
+ months after its first stable release, or three months after the first
+ stable release of the next series: whichever is longer. This means
+ that 0.4.4.x will be supported until around June 2021--or later, if
+ 0.4.5.x is later than anticipated.
+
+ Note also that support for 0.4.2.x has just ended; support for 0.4.3
+ will continue until Feb 15, 2021. We still plan to continue supporting
+ 0.3.5.x, our long-term stable series, until Feb 2022.
+
+ Below are the changes since 0.4.3.6-rc. For a complete list of changes
+ since 0.4.4.4-rc, see the ChangeLog file.
+
+ o Major features (Proposal 310, performance + security):
+ - Implements Proposal 310, "Bandaid on guard selection". Proposal
+ 310 solves load-balancing issues with older versions of the guard
+ selection algorithm, and improves its security. Under this new
+ algorithm, a newly selected guard never becomes Primary unless all
+ previously sampled guards are unreachable. Implements
+ recommendation from 32088. (Proposal 310 is linked to the CLAPS
+ project researching optimal client location-aware path selections.
+ This project is a collaboration between the UCLouvain Crypto Group,
+ the U.S. Naval Research Laboratory, and Princeton University.)
+
+ o Major features (fallback directory list):
+ - Replace the 148 fallback directories originally included in Tor
+ 0.4.1.4-rc (of which around 105 are still functional) with a list
+ of 144 fallbacks generated in July 2020. Closes ticket 40061.
+
+ o Major features (IPv6, relay):
+ - Consider IPv6-only EXTEND2 cells valid on relays. Log a protocol
+ warning if the IPv4 or IPv6 address is an internal address, and
+ internal addresses are not allowed. But continue to use the other
+ address, if it is valid. Closes ticket 33817.
+ - If a relay can extend over IPv4 and IPv6, and both addresses are
+ provided, it chooses between them uniformly at random. Closes
+ ticket 33817.
+ - Re-use existing IPv6 connections for circuit extends. Closes
+ ticket 33817.
+ - Relays may extend circuits over IPv6, if the relay has an IPv6
+ ORPort, and the client supplies the other relay's IPv6 ORPort in
+ the EXTEND2 cell. IPv6 extends will be used by the relay IPv6
+ ORPort self-tests in 33222. Closes ticket 33817.
+
+ o Major features (v3 onion services):
+ - Allow v3 onion services to act as OnionBalance backend instances,
+ by using the HiddenServiceOnionBalanceInstance torrc option.
+ Closes ticket 32709.
+
+ o Major bugfixes (NSS):
+ - When running with NSS enabled, make sure that NSS knows to expect
+ nonblocking sockets. Previously, we set our TCP sockets as
+ nonblocking, but did not tell NSS, which in turn could lead to
+ unexpected blocking behavior. Fixes bug 40035; bugfix
+ on 0.3.5.1-alpha.
+
+ o Major bugfixes (onion services, DoS):
+ - Correct handling of parameters for the onion service DoS defense.
+ Previously, the consensus parameters for the onion service DoS
+ defenses were overwriting the parameters set by the service
+ operator using HiddenServiceEnableIntroDoSDefense. Fixes bug
+ 40109; bugfix on 0.4.2.1-alpha.
+
+ o Major bugfixes (stats, onion services):
+ - Fix a bug where we were undercounting the Tor network's total
+ onion service traffic, by ignoring any traffic originating from
+ clients. Now we count traffic from both clients and services.
+ Fixes bug 40117; bugfix on 0.2.6.2-alpha.
+
+ o Minor features (security):
+ - Channels using obsolete versions of the Tor link protocol are no
+ longer allowed to circumvent address-canonicity checks. (This is
+ only a minor issue, since such channels have no way to set ed25519
+ keys, and therefore should always be rejected for circuits that
+ specify ed25519 identities.) Closes ticket 40081.
+
+ o Minor features (bootstrap reporting):
+ - Report more detailed reasons for bootstrap failure when the
+ failure happens due to a TLS error. Previously we would just call
+ these errors "MISC" when they happened during read, and "DONE"
+ when they happened during any other TLS operation. Closes
+ ticket 32622.
+
+ o Minor features (client-only compilation):
+ - Disable more code related to the ext_orport protocol when
+ compiling without support for relay mode. Closes ticket 33368.
+ - Disable more of our self-testing code when support for relay mode
+ is disabled. Closes ticket 33370.
+ - Most server-side DNS code is now disabled when building without
+ support for relay mode. Closes ticket 33366.
+
+ o Minor features (code safety):
+ - Check for failures of tor_inet_ntop() and tor_inet_ntoa()
+ functions in DNS and IP address processing code, and adjust
+ codepaths to make them less likely to crash entire Tor instances.
+ Resolves issue 33788.
+
+ o Minor features (continuous integration):
+ - Run unit-test and integration test (Stem, Chutney) jobs with
+ ALL_BUGS_ARE_FATAL macro being enabled on Travis and Appveyor.
+ Resolves ticket 32143.
+
+ o Minor features (control port):
+ - If a ClientName was specified in ONION_CLIENT_AUTH_ADD for an
+ onion service, display it when we use ONION_CLIENT_AUTH_VIEW.
+ Closes ticket 40089. Patch by Neel Chauhan.
+ - Return a descriptive error message from the 'GETINFO status/fresh-
+ relay-descs' command on the control port. Previously, we returned
+ a generic error of "Error generating descriptor". Closes ticket
+ 32873. Patch by Neel Chauhan.
+
+ o Minor features (defense in depth):
+ - Wipe more data from connection address fields before returning
+ them to the memory heap. Closes ticket 6198.
+
+ o Minor features (denial-of-service memory limiter):
+ - Allow the user to configure even lower values for the
+ MaxMemInQueues parameter. Relays now enforce a minimum of 64 MB,
+ when previously the minimum was 256 MB. On clients, there is no
+ minimum. Relays and clients will both warn if the value is set so
+ low that Tor is likely to stop working. Closes ticket 24308.
+
+ o Minor features (developer tooling):
+ - Add a script to help check the alphabetical ordering of option
+ names in the manual page. Closes ticket 33339.
+ - Refrain from listing all .a files that are generated by the Tor
+ build in .gitignore. Add a single wildcard *.a entry that covers
+ all of them for present and future. Closes ticket 33642.
+ - Add a script ("git-install-tools.sh") to install git hooks and
+ helper scripts. Closes ticket 33451.
+
+ o Minor features (directory authority):
+ - Authorities now recommend the protocol versions that are supported
+ by Tor 0.3.5 and later. (Earlier versions of Tor have been
+ deprecated since January of this year.) This recommendation will
+ cause older clients and relays to give a warning on startup, or
+ when they download a consensus directory. Closes ticket 32696.
+
+ o Minor features (directory authority, shared random):
+ - Refactor more authority-only parts of the shared-random scheduling
+ code to reside in the dirauth module, and to be disabled when
+ compiling with --disable-module-dirauth. Closes ticket 33436.
+
+ o Minor features (directory):
+ - Remember the number of bytes we have downloaded for each directory
+ purpose while bootstrapping, and while fully bootstrapped. Log
+ this information as part of the heartbeat message. Closes
+ ticket 32720.
+
+ o Minor features (entry guards):
+ - Reinstate support for GUARD NEW/UP/DOWN control port events.
+ Closes ticket 40001.
+
+ o Minor features (IPv6 support):
+ - Adds IPv6 support to tor_addr_is_valid(). Adds tests for the above
+ changes and tor_addr_is_null(). Closes ticket 33679. Patch
+ by MrSquanchee.
+ - Allow clients and relays to send dual-stack and IPv6-only EXTEND2
+ cells. Parse dual-stack and IPv6-only EXTEND2 cells on relays.
+ Closes ticket 33901.
+
+ o Minor features (linux seccomp2 sandbox, portability):
+ - Allow Tor to build on platforms where it doesn't know how to
+ report which syscall caused the linux seccomp2 sandbox to fail.
+ This change should make the sandbox code more portable to less
+ common Linux architectures. Closes ticket 34382.
+ - Permit the unlinkat() syscall, which some Libc implementations use
+ to implement unlink(). Closes ticket 33346.
+
+ o Minor features (logging):
+ - When trying to find our own address, add debug-level logging to
+ report the sources of candidate addresses. Closes ticket 32888.
+
+ o Minor features (onion service client, SOCKS5):
+ - Add 3 new SocksPort ExtendedErrors (F2, F3, F7) that reports back
+ new type of onion service connection failures. The semantics of
+ these error codes are documented in proposal 309. Closes
+ ticket 32542.
+
+ o Minor features (onion service v3):
+ - If a service cannot upload its descriptor(s), log why at INFO
+ level. Closes ticket 33400; bugfix on 0.3.2.1-alpha.
+
+ o Minor features (python scripts):
+ - Stop assuming that /usr/bin/python exists. Instead of using a
+ hardcoded path in scripts that still use Python 2, use
+ /usr/bin/env, similarly to the scripts that use Python 3. Fixes
+ bug 33192; bugfix on 0.4.2.
+
+ o Minor features (testing, architecture):
+ - Our test scripts now double-check that subsystem initialization
+ order is consistent with the inter-module dependencies established
+ by our .may_include files. Implements ticket 31634.
+ - Initialize all subsystems at the beginning of our unit test
+ harness, to avoid crashes due to uninitialized subsystems. Follow-
+ up from ticket 33316.
+ - Our "make check" target now runs the unit tests in 8 parallel
+ chunks. Doing this speeds up hardened CI builds by more than a
+ factor of two. Closes ticket 40098.
+
+ o Minor features (v3 onion services):
+ - Add v3 onion service status to the dumpstats() call which is
+ triggered by a SIGUSR1 signal. Previously, we only did v2 onion
+ services. Closes ticket 24844. Patch by Neel Chauhan.
+
+ o Minor features (windows):
+ - Add support for console control signals like Ctrl+C in Windows.
+ Closes ticket 34211. Patch from Damon Harris (TheDcoder).
+
+ o Minor bugfixes (control port, onion service):
+ - Consistently use 'address' in "Invalid v3 address" response to
+ ONION_CLIENT_AUTH commands. Previously, we would sometimes say
+ 'addr'. Fixes bug 40005; bugfix on 0.4.3.1-alpha.
+
+ o Minor bugfixes (correctness, buffers):
+ - Fix a correctness bug that could cause an assertion failure if we
+ ever tried using the buf_move_all() function with an empty input
+ buffer. As far as we know, no released versions of Tor do this.
+ Fixes bug 40076; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (directory authorities):
+ - Directory authorities now reject votes that arrive too late. In
+ particular, once an authority has started fetching missing votes,
+ it no longer accepts new votes posted by other authorities. This
+ change helps prevent a consensus split, where only some authorities
+ have the late vote. Fixes bug 4631; bugfix on 0.2.0.5-alpha.
+
+ o Minor bugfixes (git scripts):
+ - Stop executing the checked-out pre-commit hook from the pre-push
+ hook. Instead, execute the copy in the user's git directory. Fixes
+ bug 33284; bugfix on 0.4.1.1-alpha.
+
+ o Minor bugfixes (initialization):
+ - Initialize the subsystems in our code in an order more closely
+ corresponding to their dependencies, so that every system is
+ initialized before the ones that (theoretically) depend on it.
+ Fixes bug 33316; bugfix on 0.4.0.1-alpha.
+
+ o Minor bugfixes (IPv4, relay):
+ - Check for invalid zero IPv4 addresses and ports when sending and
+ receiving extend cells. Fixes bug 33900; bugfix on 0.2.4.8-alpha.
+
+ o Minor bugfixes (IPv6, relay):
+ - Consider IPv6 addresses when checking if a connection is
+ canonical. In 17604, relays assumed that a remote relay could
+ consider an IPv6 connection canonical, but did not set the
+ canonical flag on their side of the connection. Fixes bug 33899;
+ bugfix on 0.3.1.1-alpha.
+ - Log IPv6 addresses on connections where this relay is the
+ responder. Previously, responding relays would replace the remote
+ IPv6 address with the IPv4 address from the consensus. Fixes bug
+ 33899; bugfix on 0.3.1.1-alpha.
+
+ o Minor bugfixes (linux seccomp2 sandbox):
+ - Fix a regression on sandboxing rules for the openat() syscall. The
+ fix for bug 25440 fixed the problem on systems with glibc >= 2.27
+ but broke with versions of glibc. We now choose a rule based on
+ the glibc version. Patch from Daniel Pinto. Fixes bug 27315;
+ bugfix on 0.3.5.11.
+ - Makes the seccomp sandbox allow the correct syscall for opendir
+ according to the running glibc version. This fixes crashes when
+ reloading torrc with sandbox enabled when running on glibc 2.15 to
+ 2.21 and 2.26. Patch from Daniel Pinto. Fixes bug 40020; bugfix
+ on 0.3.5.11.
+
+ o Minor bugfixes (logging, testing):
+ - Make all of tor's assertion macros support the ALL_BUGS_ARE_FATAL
+ and DISABLE_ASSERTS_IN_UNIT_TESTS debugging modes. (IF_BUG_ONCE()
+ used to log a non-fatal warning, regardless of the debugging
+ mode.) Fixes bug 33917; bugfix on 0.2.9.1-alpha.
+ - Remove surprising empty line in the INFO-level log about circuit
+ build timeout. Fixes bug 33531; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (mainloop):
+ - Better guard against growing a buffer past its maximum 2GB in
+ size. Fixes bug 33131; bugfix on 0.3.0.4-rc.
+
+ o Minor bugfixes (onion service v3 client):
+ - Remove a BUG() warning that could occur naturally. Fixes bug
+ 34087; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (onion service, logging):
+ - Fix a typo in a log message PublishHidServDescriptors is set to 0.
+ Fixes bug 33779; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (onion services v3):
+ - Avoid a non-fatal assertion failure in certain edge-cases when
+ opening an intro circuit as a client. Fixes bug 34084; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor bugfixes (protocol versions):
+ - Sort tor's supported protocol version lists, as recommended by the
+ tor directory specification. Fixes bug 33285; bugfix
+ on 0.4.0.1-alpha.
+
+ o Minor bugfixes (rate limiting, bridges, pluggable transports):
+ - On a bridge, treat all connections from an ExtORPort as remote by
+ default for the purposes of rate-limiting. Previously, bridges
+ would treat the connection as local unless they explicitly
+ received a "USERADDR" command. ExtORPort connections still count
+ as local if there is a USERADDR command with an explicit local
+ address. Fixes bug 33747; bugfix on 0.2.5.1-alpha.
+
+ o Minor bugfixes (refactoring):
+ - Lift circuit_build_times_disabled() out of the
+ circuit_expire_building() loop, to save CPU time when there are
+ many circuits open. Fixes bug 33977; bugfix on 0.3.5.9.
+
+ o Minor bugfixes (relay, self-testing):
+ - When starting up as a relay, if we haven't been able to verify
+ that we're reachable, only launch reachability tests at most once
+ a minute. Previously, we had been launching tests up to once a
+ second, which was needlessly noisy. Fixes bug 40083; bugfix
+ on 0.2.8.1-alpha.
+
+ o Minor bugfixes (relay, usability):
+ - Adjust the rules for when to warn about having too many
+ connections to other relays. Previously we'd tolerate up to 1.5
+ connections per relay on average. Now we tolerate more connections
+ for directory authorities, and raise the number of total
+ connections we need to see before we warn. Fixes bug 33880; bugfix
+ on 0.3.1.1-alpha.
+
+ o Minor bugfixes (SOCKS, onion service client):
+ - Detect v3 onion service addresses of the wrong length when
+ returning the F6 ExtendedErrors code. Fixes bug 33873; bugfix
+ on 0.4.3.1-alpha.
+
+ o Minor bugfixes (tests):
+ - Fix the behavior of the rend_cache/clean_v2_descs_as_dir when run
+ on its own. Previously, it would exit with an error. Fixes bug
+ 40099; bugfix on 0.2.8.1-alpha.
+
+ o Minor bugfixes (v3 onion services):
+ - Remove a BUG() warning that could trigger in certain unlikely
+ edge-cases. Fixes bug 34086; bugfix on 0.3.2.1-alpha.
+ - Remove a BUG() that was causing a stacktrace when a descriptor
+ changed at an unexpected time. Fixes bug 28992; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor bugfixes (windows):
+ - Fix a bug that prevented Tor from starting if its log file grew
+ above 2GB. Fixes bug 31036; bugfix on 0.2.1.8-alpha.
+
+ o Code simplification and refactoring:
+ - Define and use a new constant TOR_ADDRPORT_BUF_LEN which is like
+ TOR_ADDR_BUF_LEN but includes enough space for an IP address,
+ brackets, separating colon, and port number. Closes ticket 33956.
+ Patch by Neel Chauhan.
+ - Merge the orconn and ocirc events into the "core" subsystem, which
+ manages or connections and origin circuits. Previously they were
+ isolated in subsystems of their own.
+ - Move LOG_PROTOCOL_WARN to app/config. Resolves a dependency
+ inversion. Closes ticket 33633.
+ - Move the circuit extend code to the relay module. Split the
+ circuit extend function into smaller functions. Closes
+ ticket 33633.
+ - Rewrite port_parse_config() to use the default port flags from
+ port_cfg_new(). Closes ticket 32994. Patch by MrSquanchee.
+ - Updated comments in 'scheduler.c' to reflect old code changes, and
+ simplified the scheduler channel state change code. Closes
+ ticket 33349.
+ - Refactor configuration parsing to use the new config subsystem
+ code. Closes ticket 33014.
+ - Move a series of functions related to address resolving into their
+ own files. Closes ticket 33789.
+
+ o Documentation:
+ - Replace most http:// URLs in our code and documentation with
+ https:// URLs. (We have left unchanged the code in src/ext/, and
+ the text in LICENSE.) Closes ticket 31812. Patch from Jeremy Rand.
+ - Document the limitations of using %include on config files with
+ seccomp sandbox enabled. Fixes documentation bug 34133; bugfix on
+ 0.3.1.1-alpha. Patch by Daniel Pinto.
+
+ 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.
+ - Remove the ClientAutoIPv6ORPort option. This option attempted to
+ randomly choose between IPv4 and IPv6 for client connections, and
+ wasn't a true implementation of Happy Eyeballs. Often, this option
+ failed on IPv4-only or IPv6-only connections. Closes ticket 32905.
+ Patch by Neel Chauhan.
+ - Stop shipping contrib/dist/rc.subr file, as it is not being used
+ on FreeBSD anymore. Closes issue 31576.
+
+ o Testing:
+ - Add a basic IPv6 test to "make test-network". This test only runs
+ when the local machine has an IPv6 stack. Closes ticket 33300.
+ - Add test-network-ipv4 and test-network-ipv6 jobs to the Makefile.
+ These jobs run the IPv4-only and dual-stack chutney flavours from
+ test-network-all. Closes ticket 33280.
+ - Remove a redundant distcheck job. Closes ticket 33194.
+ - Run the test-network-ipv6 Makefile target in the Travis CI IPv6
+ chutney job. This job runs on macOS, so it's a bit slow. Closes
+ ticket 33303.
+ - Sort the Travis jobs in order of speed. Putting the slowest jobs
+ first takes full advantage of Travis job concurrency. Closes
+ ticket 33194.
+ - Stop allowing the Chutney IPv6 Travis job to fail. This job was
+ previously configured to fast_finish (which requires
+ allow_failure), to speed up the build. Closes ticket 33195.
+ - Test v3 onion services to tor's mixed IPv4 chutney network. And
+ add a mixed IPv6 chutney network. These networks are used in the
+ test-network-all, test-network-ipv4, and test-network-ipv6 make
+ targets. Closes ticket 33334.
+ - Use the "bridges+hs-v23" chutney network flavour in "make test-
+ network". This test requires a recent version of chutney (mid-
+ February 2020). Closes ticket 28208.
+ - When a Travis chutney job fails, use chutney's new "diagnostics.sh"
+ tool to produce detailed diagnostic output. Closes ticket 32792.
+
+ o Deprecated features (onion service v2):
+ - Add a deprecation warning for version 2 onion services. Closes
+ ticket 40003.
+
+ o Documentation (manual page):
+ - Add cross reference links and a table of contents to the HTML tor
+ manual page. Closes ticket 33369. Work by Swati Thacker as part of
+ Google Season of Docs.
+ - Alphabetize the Denial of Service Mitigation Options, Directory
+ Authority Server Options, Hidden Service Options, and Testing
+ Network Options sections of the tor(1) manual page. Closes ticket
+ 33275. Work by Swati Thacker as part of Google Season of Docs.
+ - Refrain from mentioning nicknames in manpage section for MyFamily
+ torrc option. Resolves issue 33417.
+ - Updated the options set by TestingTorNetwork in the manual page.
+ Closes ticket 33778.
+
+
+Changes in version 0.3.5.11 - 2020-07-09
+ Tor 0.3.5.11 backports fixes from later tor releases, including several
+ usability, portability, and reliability fixes.
+
+ This release also fixes TROVE-2020-001, a medium-severity denial of
+ service vulnerability affecting all versions of Tor when compiled with
+ the NSS encryption library. (This is not the default configuration.)
+ Using this vulnerability, an attacker could cause an affected Tor
+ instance to crash remotely. This issue is also tracked as CVE-2020-
+ 15572. Anybody running a version of Tor built with the NSS library
+ should upgrade to 0.3.5.11, 0.4.2.8, 0.4.3.6, or 0.4.4.2-alpha
+ or later.
+
+ o Major bugfixes (NSS, security, backport from 0.4.4.2-alpha):
+ - Fix a crash due to an out-of-bound memory access when Tor is
+ compiled with NSS support. Fixes bug 33119; bugfix on
+ 0.3.5.1-alpha. This issue is also tracked as TROVE-2020-001
+ and CVE-2020-15572.
+
+ o Major bugfixes (DoS defenses, bridges, pluggable transport, backport from 0.4.3.4-rc):
+ - Fix a bug that was preventing DoS defenses from running on bridges
+ with a pluggable transport. Previously, the DoS subsystem was not
+ given the transport name of the client connection, thus failed to
+ find the GeoIP cache entry for that client address. Fixes bug
+ 33491; bugfix on 0.3.3.2-alpha.
+
+ o Minor features (testing, backport from 0.4.3.4-rc):
+ - The unit tests now support a "TOR_SKIP_TESTCASES" environment
+ variable to specify a list of space-separated test cases that
+ should not be executed. We will use this to disable certain tests
+ that are failing on Appveyor because of mismatched OpenSSL
+ libraries. Part of ticket 33643.
+
+ o Minor bugfix (CI, Windows, backport from 0.4.4.2-alpha):
+ - Use the correct 64-bit printf format when compiling with MINGW on
+ Appveyor. Fixes bug 40026; bugfix on 0.3.5.5-alpha.
+
+ o Minor bugfix (relay, configuration, backport from 0.4.3.3-alpha):
+ - Warn if the ContactInfo field is not set, and tell the relay
+ operator that not having a ContactInfo field set might cause their
+ relay to get rejected in the future. Fixes bug 33361; bugfix
+ on 0.1.1.10-alpha.
+
+ o Minor bugfixes (client performance, backport from 0.4.4.1-alpha):
+ - Resume use of preemptively-built circuits when UseEntryGuards is set
+ to 0. We accidentally disabled this feature with that config
+ setting, leading to slower load times. Fixes bug 34303; bugfix
+ on 0.3.3.2-alpha.
+
+ o Minor bugfixes (compiler compatibility, backport from 0.4.3.5):
+ - Avoid compiler warnings from Clang 10 related to the use of GCC-
+ style "/* falls through */" comments. Both Clang and GCC allow
+ __attribute__((fallthrough)) instead, so that's what we're using
+ now. Fixes bug 34078; bugfix on 0.3.1.3-alpha.
+
+ o Minor bugfixes (compiler warnings, backport from 0.4.4.2-alpha):
+ - Fix a compiler warning on platforms with 32-bit time_t values.
+ Fixes bug 40028; bugfix on 0.3.2.8-rc.
+
+ o Minor bugfixes (embedded Tor, backport from 0.4.3.1-alpha):
+ - 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 (key portability, backport from 0.4.3.4-rc):
+ - When reading PEM-encoded key data, tolerate CRLF line-endings even
+ if we are not running on Windows. Previously, non-Windows hosts
+ would reject these line-endings in certain positions, making
+ certain key files hard to move from one host to another. Fixes bug
+ 33032; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.4.2-alpha):
+ - Downgrade a noisy log message that could occur naturally when
+ receiving an extrainfo document that we no longer want. Fixes bug
+ 16016; bugfix on 0.2.6.3-alpha.
+
+ o Minor bugfixes (onion service v3, client, backport from 0.4.3.3-alpha):
+ - Remove a BUG() warning that would cause a stack trace if an onion
+ service descriptor was freed while we were waiting for a
+ rendezvous circuit to complete. Fixes bug 28992; bugfix
+ on 0.3.2.1-alpha.
+
+ o Testing (CI, backport from 0.4.3.4-rc):
+ - In our Appveyor Windows CI, copy required DLLs to test and app
+ directories, before running tor's tests. This ensures that tor.exe
+ and test*.exe use the correct version of each DLL. This fix is not
+ required, but we hope it will avoid DLL search issues in future.
+ Fixes bug 33673; bugfix on 0.3.4.2-alpha.
+ - On Appveyor, skip the crypto/openssl_version test, which is
+ failing because of a mismatched library installation. Fix
+ for 33643.
+
+
+Changes in version 0.4.2.8 - 2020-07-09
+ Tor 0.4.2.8 backports various fixes from later releases, including
+ several that affect usability and portability.
+
+ This release also fixes TROVE-2020-001, a medium-severity denial of
+ service vulnerability affecting all versions of Tor when compiled with
+ the NSS encryption library. (This is not the default configuration.)
+ Using this vulnerability, an attacker could cause an affected Tor
+ instance to crash remotely. This issue is also tracked as CVE-2020-
+ 15572. Anybody running a version of Tor built with the NSS library
+ should upgrade to 0.3.5.11, 0.4.2.8, 0.4.3.6, or 0.4.4.2-alpha
+ or later.
+
+ o Major bugfixes (NSS, security, backport from 0.4.4.2-alpha):
+ - Fix a crash due to an out-of-bound memory access when Tor is
+ compiled with NSS support. Fixes bug 33119; bugfix on
+ 0.3.5.1-alpha. This issue is also tracked as TROVE-2020-001
+ and CVE-2020-15572.
+
+ o Major bugfixes (DoS defenses, bridges, pluggable transport, backport from 0.4.3.4-rc):
+ - Fix a bug that was preventing DoS defenses from running on bridges
+ with a pluggable transport. Previously, the DoS subsystem was not
+ given the transport name of the client connection, thus failed to
+ find the GeoIP cache entry for that client address. Fixes bug
+ 33491; bugfix on 0.3.3.2-alpha.
+
+ o Minor feature (sendme, flow control, backport form 0.4.3.4-rc):
+ - Default to sending SENDME version 1 cells. (Clients are already
+ sending these, because of a consensus parameter telling them to do
+ so: this change only affects what clients would do if the
+ consensus didn't contain a recommendation.) Closes ticket 33623.
+
+ o Minor features (diagnostic, backport from 0.4.3.3-alpha):
+ - Improve assertions and add some memory-poisoning code to try to
+ track down possible causes of a rare crash (32564) in the EWMA
+ code. Closes ticket 33290.
+
+ o Minor features (testing, backport from 0.4.3.4-rc):
+ - The unit tests now support a "TOR_SKIP_TESTCASES" environment
+ variable to specify a list of space-separated test cases that
+ should not be executed. We will use this to disable certain tests
+ that are failing on Appveyor because of mismatched OpenSSL
+ libraries. Part of ticket 33643.
+
+ o Minor bugfix (CI, Windows, backport from 0.4.4.2-alpha):
+ - Use the correct 64-bit printf format when compiling with MINGW on
+ Appveyor. Fixes bug 40026; bugfix on 0.3.5.5-alpha.
+
+ o Minor bugfix (relay, configuration, backport from 0.4.3.3-alpha):
+ - Warn if the ContactInfo field is not set, and tell the relay
+ operator that not having a ContactInfo field set might cause their
+ relay to get rejected in the future. Fixes bug 33361; bugfix
+ on 0.1.1.10-alpha.
+
+ o Minor bugfixes (client performance, backport from 0.4.4.1-alpha):
+ - Resume use of preemptively-built circuits when UseEntryGuards is set
+ to 0. We accidentally disabled this feature with that config
+ setting, leading to slower load times. Fixes bug 34303; bugfix
+ on 0.3.3.2-alpha.
+
+ o Minor bugfixes (compiler compatibility, backport from 0.4.3.5):
+ - Avoid compiler warnings from Clang 10 related to the use of GCC-
+ style "/* falls through */" comments. Both Clang and GCC allow
+ __attribute__((fallthrough)) instead, so that's what we're using
+ now. Fixes bug 34078; bugfix on 0.3.1.3-alpha.
+ - Fix compilation warnings with GCC 10.0.1. Fixes bug 34077; bugfix
+ on 0.4.0.3-alpha.
+
+ o Minor bugfixes (compiler warnings, backport from 0.4.4.2-alpha):
+ - Fix a compiler warning on platforms with 32-bit time_t values.
+ Fixes bug 40028; bugfix on 0.3.2.8-rc.
+
+ o Minor bugfixes (controller protocol, backport from 0.4.3.2-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 (embedded Tor, backport from 0.4.3.1-alpha):
+ - 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 (key portability, backport from 0.4.3.4-rc):
+ - When reading PEM-encoded key data, tolerate CRLF line-endings even
+ if we are not running on Windows. Previously, non-Windows hosts
+ would reject these line-endings in certain positions, making
+ certain key files hard to move from one host to another. Fixes bug
+ 33032; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.3.2-rc):
+ - 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 (logging, backport from 0.4.3.4-rc):
+ - 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.
+
+ o Minor bugfixes (logging, backport from 0.4.4.2-alpha):
+ - Downgrade a noisy log message that could occur naturally when
+ receiving an extrainfo document that we no longer want. Fixes bug
+ 16016; bugfix on 0.2.6.3-alpha.
+
+ o Minor bugfixes (onion service v3, client, backport from 0.4.3.3-alpha):
+ - Remove a BUG() warning that would cause a stack trace if an onion
+ service descriptor was freed while we were waiting for a
+ rendezvous circuit to complete. Fixes bug 28992; bugfix
+ on 0.3.2.1-alpha.
+
+ o Testing (CI, backport from 0.4.3.4-rc):
+ - In our Appveyor Windows CI, copy required DLLs to test and app
+ directories, before running tor's tests. This ensures that tor.exe
+ and test*.exe use the correct version of each DLL. This fix is not
+ required, but we hope it will avoid DLL search issues in future.
+ Fixes bug 33673; bugfix on 0.3.4.2-alpha.
+ - On Appveyor, skip the crypto/openssl_version test, which is
+ failing because of a mismatched library installation. Fix
+ for 33643.
+
+
+Changes in version 0.4.3.6 - 2020-07-09
+ Tor 0.4.3.6 backports several bugfixes from later releases, including
+ some affecting usability.
+
+ This release also fixes TROVE-2020-001, a medium-severity denial of
+ service vulnerability affecting all versions of Tor when compiled with
+ the NSS encryption library. (This is not the default configuration.)
+ Using this vulnerability, an attacker could cause an affected Tor
+ instance to crash remotely. This issue is also tracked as CVE-2020-
+ 15572. Anybody running a version of Tor built with the NSS library
+ should upgrade to 0.3.5.11, 0.4.2.8, 0.4.3.6, or 0.4.4.2-alpha
+ or later.
+
+ o Major bugfixes (NSS, security, backport from 0.4.4.2-alpha):
+ - Fix a crash due to an out-of-bound memory access when Tor is
+ compiled with NSS support. Fixes bug 33119; bugfix on
+ 0.3.5.1-alpha. This issue is also tracked as TROVE-2020-001
+ and CVE-2020-15572.
+
+ o Minor bugfix (CI, Windows, backport from 0.4.4.2-alpha):
+ - Use the correct 64-bit printf format when compiling with MINGW on
+ Appveyor. Fixes bug 40026; bugfix on 0.3.5.5-alpha.
+
+ o Minor bugfixes (client performance, backport from 0.4.4.1-alpha):
+ - Resume use of preemptively-built circuits when UseEntryGuards is set
+ to 0. We accidentally disabled this feature with that config
+ setting, leading to slower load times. Fixes bug 34303; bugfix
+ on 0.3.3.2-alpha.
+
+ o Minor bugfixes (compiler warnings, backport from 0.4.4.2-alpha):
+ - Fix a compiler warning on platforms with 32-bit time_t values.
+ Fixes bug 40028; bugfix on 0.3.2.8-rc.
+
+ o Minor bugfixes (linux seccomp sandbox, nss, backport from 0.4.4.1-alpha):
+ - Fix a 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.
+
+ o Minor bugfixes (logging, backport from 0.4.4.2-alpha):
+ - Downgrade a noisy log message that could occur naturally when
+ receiving an extrainfo document that we no longer want. Fixes bug
+ 16016; bugfix on 0.2.6.3-alpha.
+
+ o Minor bugfixes (manual page, backport from 0.4.4.1-alpha):
+ - Update the man page to reflect that MinUptimeHidServDirectoryV2
+ defaults to 96 hours. Fixes bug 34299; bugfix on 0.2.6.3-alpha.
+
+ o Minor bugfixes (onion service v3, backport from 0.4.4.1-alpha):
+ - Prevent an assert() that would occur when cleaning the client
+ descriptor cache, and attempting to close circuits for a non-
+ decrypted descriptor (lacking client authorization). Fixes bug
+ 33458; bugfix on 0.4.2.1-alpha.
+
+ o Minor bugfixes (portability, backport from 0.4.4.1-alpha):
+ - Fix a portability error in the configure script, where we were
+ using "==" instead of "=". Fixes bug 34233; bugfix on 0.4.3.5.
+
+ o Minor bugfixes (relays, backport from 0.4.4.1-alpha):
+ - 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.
+
+ o Documentation (backport from 0.4.4.1-alpha):
+ - Fix several doxygen warnings related to imbalanced groups. Closes
+ ticket 34255.
+
Changes in version 0.4.3.5 - 2020-05-15
Tor 0.4.3.5 is the first stable release in the 0.4.3.x series. This
@@ -21460,7 +22471,7 @@ Changes in version 0.2.0.33 - 2009-01-21
- Implement the 0x20 hack to better resist DNS poisoning: set the
case on outgoing DNS requests randomly, and reject responses that do
not match the case correctly. This logic can be disabled with the
- ServerDNSRamdomizeCase setting, if you are using one of the 0.3%
+ ServerDNSRandomizeCase setting, if you are using one of the 0.3%
of servers that do not reliably preserve case in replies. See
"Increased DNS Forgery Resistance through 0x20-Bit Encoding"
for more info.
diff --git a/acinclude.m4 b/acinclude.m4
index 5ecdf1d5c2..e6389ea1d4 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -166,7 +166,7 @@ AC_CACHE_CHECK([for $1 directory], tor_cv_library_$1_dir, [
for tor_trydir in "$try$1dir" "(system)" "$prefix" /usr/local /usr/pkg $8; do
LDFLAGS="$tor_saved_LDFLAGS"
- LIBS="$tor_saved_LIBS $3"
+ LIBS="$3 $tor_saved_LIBS"
CPPFLAGS="$tor_saved_CPPFLAGS"
if test -z "$tor_trydir" ; then
@@ -219,7 +219,7 @@ AC_CACHE_CHECK([for $1 directory], tor_cv_library_$1_dir, [
CPPFLAGS="$tor_saved_CPPFLAGS"
]) dnl end cache check
-LIBS="$LIBS $3"
+LIBS="$3 $LIBS"
if test "$tor_cv_library_$1_dir" != "(system)"; then
TOR_EXTEND_CODEPATH($tor_cv_library_$1_dir)
fi
diff --git a/changes/40241_v2 b/changes/40241_v2
new file mode 100644
index 0000000000..85038297f7
--- /dev/null
+++ b/changes/40241_v2
@@ -0,0 +1,4 @@
+ o Minor bugfixes (compilation):
+ - Fix another warning about unreachable fallthrough annotations
+ when building with "--enable-all-bugs-are-fatal" on some compilers.
+ Fixes bug 40241; bugfix on 0.4.5.3-rc.
diff --git a/changes/autoconf-2.70 b/changes/autoconf-2.70
new file mode 100644
index 0000000000..27a9f243b1
--- /dev/null
+++ b/changes/autoconf-2.70
@@ -0,0 +1,3 @@
+ o Minor features (compilation):
+ - Make the autoconf script build correctly with autoconf versions 2.70
+ and later. Closes part of ticket 40335.
diff --git a/changes/bug16016 b/changes/bug16016
deleted file mode 100644
index 313ef672e9..0000000000
--- a/changes/bug16016
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes (logging):
- - Downgrade a noisy log message that could occur naturally when
- receiving an extrainfo document that we no longer want.
- Fixes bug 16016; bugfix on 0.2.6.3-alpha.
diff --git a/changes/bug24857 b/changes/bug24857
new file mode 100644
index 0000000000..ea9c763332
--- /dev/null
+++ b/changes/bug24857
@@ -0,0 +1,6 @@
+ o Minor bugfixes (directory cache, performance, windows):
+ - Limit the number of items in the consensus diff cache to 64 on Windows.
+ We hope this will resolve an issue where Windows relay operators reported
+ Tor using 100% CPU while we investigate better solutions. Fixes bug 24857;
+ bugfix on 0.3.1.1-alpha.
+
diff --git a/changes/bug27315 b/changes/bug27315
deleted file mode 100644
index 8af3ac8559..0000000000
--- a/changes/bug27315
+++ /dev/null
@@ -1,6 +0,0 @@
- o Minor bugfixes (linux seccomp2 sandbox):
- - Fix a regression on sandboxing rules for the openat() syscall.
- The fix for bug 25440 fixed the problem on systems with glibc >=
- 2.27 but broke tor on previous versions of glibc. We now apply
- the correct seccomp rule according to the running glibc version.
- Patch from Daniel Pinto. Fixes bug 27315; bugfix on 0.3.5.11.
diff --git a/changes/bug30187 b/changes/bug30187
new file mode 100644
index 0000000000..2a3358d6be
--- /dev/null
+++ b/changes/bug30187
@@ -0,0 +1,5 @@
+ o Major bugfixes (relay, windows):
+ - Fix bug where running a relay on Windows would use 100%
+ CPU after some time. Makes Windows >= Vista the required
+ Windows version to build and run tor. Fixes bug 30187;
+ bugfix on 0.4.5.1-alpha. Patch by Daniel Pinto.
diff --git a/changes/bug31036 b/changes/bug31036
deleted file mode 100644
index d9921dba43..0000000000
--- a/changes/bug31036
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (windows):
- - Fix a bug that prevented Tor from starting if its log file
- grew above 2GB. Fixes bug 31036; bugfix on 0.2.1.8-alpha.
diff --git a/changes/bug32588 b/changes/bug32588
deleted file mode 100644
index f31f2ce1ad..0000000000
--- a/changes/bug32588
+++ /dev/null
@@ -1,4 +0,0 @@
- 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/bug32666 b/changes/bug32666
new file mode 100644
index 0000000000..d487b22148
--- /dev/null
+++ b/changes/bug32666
@@ -0,0 +1,3 @@
+ o Minor bugfixes (onion services):
+ - Avoid a non-fatal assertion in certain edge-cases when establishing a
+ circuit to onion service. Fixes bug 32666; bugfix on 0.3.0.3-alpha.
diff --git a/changes/bug32709 b/changes/bug32709
deleted file mode 100644
index d00b112be6..0000000000
--- a/changes/bug32709
+++ /dev/null
@@ -1,4 +0,0 @@
- o Major features (v3 onion services):
- - Allow v3 onion services to act as OnionBalance backend instances using
- the HiddenServiceOnionBalanceInstance torrc option. Closes ticket 32709.
-
diff --git a/changes/bug32880 b/changes/bug32880
new file mode 100644
index 0000000000..a25cabb7dc
--- /dev/null
+++ b/changes/bug32880
@@ -0,0 +1,5 @@
+ o Minor bugfixes (circuit, handshake):
+ - In the v3 handshaking code, Use connection_or_change_state() to change
+ the state. Previously, we changed the state directly, but this did not
+ pass a state change to the pubsub or channel object. Fixes bug 32880;
+ bugfix on 0.2.3.6-alpha. Patch by Neel Chauhan.
diff --git a/changes/bug33119 b/changes/bug33119
deleted file mode 100644
index c976654b26..0000000000
--- a/changes/bug33119
+++ /dev/null
@@ -1,4 +0,0 @@
- o Major bugfixes (NSS):
- - Fix out-of-bound memory access in `tor_tls_cert_matches_key()` when Tor is
- compiled with NSS support. Fixes bug 33119; bugfix on 0.3.5.1-alpha. This
- issue is also tracked as TROVE-2020-001.
diff --git a/changes/bug33131 b/changes/bug33131
deleted file mode 100644
index bc5ef7bc2d..0000000000
--- a/changes/bug33131
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (mainloop):
- - Better guard against growing a buffer past its maximum 2GB in size.
- Fixes bug 33131; bugfix on 0.3.0.4-rc.
diff --git a/changes/bug33284 b/changes/bug33284
deleted file mode 100644
index e6aed4d2d4..0000000000
--- a/changes/bug33284
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes (git scripts):
- - Stop executing the checked-out pre-commit hook from the pre-push hook.
- Instead, execute the copy in the user's git dir. Fixes bug 33284; bugfix
- on 0.4.1.1-alpha.
diff --git a/changes/bug33285 b/changes/bug33285
deleted file mode 100644
index a4d06a7eb8..0000000000
--- a/changes/bug33285
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (protocol versions):
- - Sort tor's supported protocol version lists, as recommended by the
- tor directory specification. Fixes bug 33285; bugfix on 0.4.0.1-alpha.
diff --git a/changes/bug33531 b/changes/bug33531
deleted file mode 100644
index c4284c55c9..0000000000
--- a/changes/bug33531
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (logs):
- - Remove surprising empty line in info-level log about circuit build
- timeout. Fixes bug 33531; bugfix on 0.3.3.1-alpha.
diff --git a/changes/bug33781 b/changes/bug33781
deleted file mode 100644
index 9f63ab0a2c..0000000000
--- a/changes/bug33781
+++ /dev/null
@@ -1,7 +0,0 @@
- o Minor bugfixes (compatibility):
- - Strip '\r' characters when reading text files on Unix platforms.
- This should resolve an issue where a relay operator migrates a relay from
- Windows to Unix, but does not change the line ending of Tor's various state
- files to match the platform, the CRLF line endings from Windows ends up leaking
- into other files such as the extra-info document. Fixes bug 33781; bugfix on
- 0.0.9pre5.
diff --git a/changes/bug33899 b/changes/bug33899
deleted file mode 100644
index b9b7d7cf13..0000000000
--- a/changes/bug33899
+++ /dev/null
@@ -1,9 +0,0 @@
- o Minor bugfixes (IPv6, relay):
- - Consider IPv6 addresses when checking if a connection is canonical.
- In 17604, relays assumed that a remote relay could consider an IPv6
- connection canonical, but did not set the canonical flag on their side
- of the connection. Fixes bug 33899; bugfix on 0.3.1.1-alpha.
- - Log IPv6 addresses on connections where this relay is the responder.
- Previously, responding relays would replace the remote IPv6 address with
- the IPv4 address from the consensus.
- Fixes bug 33899; bugfix on 0.3.1.1-alpha.
diff --git a/changes/bug33900 b/changes/bug33900
deleted file mode 100644
index c1649d2284..0000000000
--- a/changes/bug33900
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (IPv4, relay):
- - Check for invalid zero IPv4 addresses and ports, when sending and
- receiving extend cells. Fixes bug 33900; bugfix on 0.2.4.8-alpha.
diff --git a/changes/bug33917 b/changes/bug33917
deleted file mode 100644
index 6a8daa9e26..0000000000
--- a/changes/bug33917
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes (logging, testing):
- - Make all of tor's assertion macros support the ALL_BUGS_ARE_FATAL and
- DISABLE_ASSERTS_IN_UNIT_TESTS debugging modes. Implements these modes
- for IF_BUG_ONCE(). (It used to log a non-fatal warning, regardless of
- the debugging mode.) Fixes bug 33917; bugfix on 0.2.9.1-alpha.
diff --git a/changes/bug33977 b/changes/bug33977
deleted file mode 100644
index b424a811a2..0000000000
--- a/changes/bug33977
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfix (refactoring):
- - Lift circuit_build_times_disabled out of circuit_expire_building loop to
- save CPU time with many circuits open. Fixes bug 33977; bugfix on
- 0.3.5.9.
diff --git a/changes/bug34084 b/changes/bug34084
deleted file mode 100644
index 524c4cf68e..0000000000
--- a/changes/bug34084
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (onion services v3):
- - Avoid a non-fatal assert log in an edge-case of opening an intro circuit
- as a client. Fixes bug 34084; bugfix on 0.3.2.1-alpha.
diff --git a/changes/bug34086 b/changes/bug34086
deleted file mode 100644
index 245992f8f4..0000000000
--- a/changes/bug34086
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (onion service v3):
- - Remove a BUG() warning that could trigger in certain unlikely edge-cases.
- Fixes bug 34086; bugfix on 0.3.2.1-alpha.
diff --git a/changes/bug34130 b/changes/bug34130
deleted file mode 100644
index b1e5715fdf..0000000000
--- a/changes/bug34130
+++ /dev/null
@@ -1,4 +0,0 @@
- 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/bug34233 b/changes/bug34233
deleted file mode 100644
index 24c7869783..0000000000
--- a/changes/bug34233
+++ /dev/null
@@ -1,4 +0,0 @@
- 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
deleted file mode 100644
index 464cf0d18a..0000000000
--- a/changes/bug34299
+++ /dev/null
@@ -1,3 +0,0 @@
- 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/bug34303 b/changes/bug34303
deleted file mode 100644
index dce57f4646..0000000000
--- a/changes/bug34303
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes (client performance):
- - Resume being willing to use preemptively-built circuits when
- UseEntryGuards is set to 0. We accidentally disabled this feature
- with that config setting, leading to slower load times. Fixes bug
- 34303; bugfix on 0.3.3.2-alpha.
diff --git a/changes/bug34400 b/changes/bug34400
deleted file mode 100644
index e2b56688b9..0000000000
--- a/changes/bug34400
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes (v2 onion services):
- - For HSFETCH commands on v2 onion services addresses, check the length of
- bytes decoded, not the base32 length. This takes the behavior introduced
- in commit a517daa56f5848d25ba79617a1a7b82ed2b0a7c0 into consideration.
- Fixes bug 34400; bugfix on 0.4.1.1-alpha. Patch by Neel Chauhan.
diff --git a/changes/bug40001 b/changes/bug40001
deleted file mode 100644
index 0e3f454619..0000000000
--- a/changes/bug40001
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor features (entry guards):
- - Reinstate support for GUARD NEW/UP/DOWN control port events.
- Closes ticket 40001. \ No newline at end of file
diff --git a/changes/bug40015 b/changes/bug40015
new file mode 100644
index 0000000000..1d190df751
--- /dev/null
+++ b/changes/bug40015
@@ -0,0 +1,4 @@
+ o Major bugfixes (crash, relay, signing key):
+ - Avoid asserts when we run Tor from the command line with
+ `--key-expiration sign` when an ORPort is not set. Fixes
+ bug 40015; bugfix on 0.3.2.1-alpha. Patch by Neel Chauhan.
diff --git a/changes/bug40017 b/changes/bug40017
new file mode 100644
index 0000000000..3f5c2da968
--- /dev/null
+++ b/changes/bug40017
@@ -0,0 +1,5 @@
+ o Minor features (protocol, proxy support, defense in depth):
+ - Respond more deliberately to misbehaving proxies that leave leftover
+ data on their connections, so as to be even less likely as to allow
+ them to pass their data off as having come from a relay.
+ Closes ticket 40017.
diff --git a/changes/bug40020 b/changes/bug40020
deleted file mode 100644
index ca6ee2b85b..0000000000
--- a/changes/bug40020
+++ /dev/null
@@ -1,9 +0,0 @@
- o Minor bugfixes (linux seccomp2 sandbox):
- - Makes the seccomp sandbox allow the correct syscall for opendir
- according to the running glibc version. The opendir function
- either uses open or openat but the current code does not
- differenciate between opendir and open calls. This adds a new
- seccomp sandbox rule for opendir. This fixes crashes when
- reloading torrc with sandbox enabled when running on glibc
- 2.15 to 2.21 and 2.26. Patch from Daniel Pinto. Fixes bug 40020;
- bugfix on 0.3.5.11.
diff --git a/changes/bug40028 b/changes/bug40028
deleted file mode 100644
index cfd1ffe516..0000000000
--- a/changes/bug40028
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (compiler warnings):
- - Fix a compiler warning on platforms with 32-bit time_t values.
- Fixes bug 40028; bugfix on 0.3.2.8-rc.
diff --git a/changes/bug40072 b/changes/bug40072
deleted file mode 100644
index 2b82f3f18b..0000000000
--- a/changes/bug40072
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes (linux seccomp2 sandbox):
- - Fix startup crash with seccomp sandbox enabled when tor tries to
- open the data directory. Patch from Daniel Pinto. Fixes bug 40072;
- bugfix on 0.4.4.3-alpha-dev.
diff --git a/changes/bug40076 b/changes/bug40076
deleted file mode 100644
index 9ef5969ae8..0000000000
--- a/changes/bug40076
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes (correctness, buffers):
- - Fix a correctness bug that could cause an assertion failure if we ever
- tried using the buf_move_all() function with an empty input.
- As far as we know, no released versions of Tor do this.
- Fixes bug 40076; bugfix on 0.3.3.1-alpha.
diff --git a/changes/bug40080 b/changes/bug40080
deleted file mode 100644
index 8162466354..0000000000
--- a/changes/bug40080
+++ /dev/null
@@ -1,6 +0,0 @@
- o Minor bugfixes (security):
- - When completing a channel, relays now check more thoroughly to make
- sure that it matches any pending circuits before attaching those
- circuits. Previously, address correctness and Ed25519 identities were not
- checked in this case, but only when extending circuits on an existing
- channel. Fixes bug 40080; bugfix on 0.2.7.2-alpha.
diff --git a/changes/bug40083 b/changes/bug40083
deleted file mode 100644
index db26017664..0000000000
--- a/changes/bug40083
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes (relay, self-testing):
- - When starting up as a relay, if we haven't been able to verify that
- we're reachable, only launch reachability tests at most once a minute.
- Previously, we had been launching tests up to once a second, which
- was needlessly noisy. Fixes bug 40083; bugfix on 0.2.8.1-alpha.
diff --git a/changes/bug40095 b/changes/bug40095
deleted file mode 100644
index 5c4b3a2b7e..0000000000
--- a/changes/bug40095
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes (testing):
- - When running the subsystem order check, use the python binary
- configured with the PYTHON environment variable. Fixes bug 40095;
- bugfix on 0.4.4.1-alpha.
diff --git a/changes/bug40099 b/changes/bug40099
deleted file mode 100644
index 278ede2023..0000000000
--- a/changes/bug40099
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes (tests):
- - Fix the behavior of the rend_cache/clean_v2_descs_as_dir when run on
- its own. Previously, it would exit with an error.
- Fixes bug 40099; bugfix on 0.2.8.1-alpha.
diff --git a/changes/bug40105 b/changes/bug40105
deleted file mode 100644
index 330b6a9744..0000000000
--- a/changes/bug40105
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (guard selection algorithm):
- - Avoid needless guard-related warning when upgrading from 0.4.3 to 0.4.4.
- Fixes bug 40105; bugfix on 0.4.4.1-alpha. \ No newline at end of file
diff --git a/changes/bug40113 b/changes/bug40113
deleted file mode 100644
index adf4634097..0000000000
--- a/changes/bug40113
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (compilation):
- - Resolve a compilation warning that could occur in test_connection.c.
- Fixes bug 40113; bugfix on 0.2.9.3-alpha.
diff --git a/changes/bug40117 b/changes/bug40117
deleted file mode 100644
index 77646edf9c..0000000000
--- a/changes/bug40117
+++ /dev/null
@@ -1,5 +0,0 @@
- o Major bugfixes (stats, onion services):
- - Fix a bug where we were undercounting the Tor network's total onion
- service traffic, by only counting rendezvous traffic originating from
- services and ignoring any traffic originating from clients. Fixes bug
- 40117; bugfix on 0.2.6.2-alpha.
diff --git a/changes/bug40129 b/changes/bug40129
deleted file mode 100644
index 80de5ef355..0000000000
--- a/changes/bug40129
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes (compilation):
- - Fix compiler warnings that would occur when building with
- "--enable-all-bugs-are-fatal" and "--disable-module-relay"
- at the same time. Fixes bug 40129; bugfix on 0.4.4.1-alpha.
diff --git a/changes/bug40172 b/changes/bug40172
new file mode 100644
index 0000000000..a73fcb39a3
--- /dev/null
+++ b/changes/bug40172
@@ -0,0 +1,3 @@
+ o Minor bugfixes (compilation):
+ - Fix a compilation issue in which the correct 'ranlib' program was not
+ used when building libtor.a. Fixes bug 40172; bugfix on 0.4.5.1-alpha.
diff --git a/changes/bug40177 b/changes/bug40177
new file mode 100644
index 0000000000..b08be64e47
--- /dev/null
+++ b/changes/bug40177
@@ -0,0 +1,3 @@
+ o Minor bugfixes (compilation):
+ - Remove a duplicate typedef in metrics_store.c. Fixes bug 40177;
+ bugfix on 0.4.5.1-alpha.
diff --git a/changes/bug40187 b/changes/bug40187
new file mode 100644
index 0000000000..563e4b4d76
--- /dev/null
+++ b/changes/bug40187
@@ -0,0 +1,5 @@
+ o Minor bugfixes (testing):
+ - Fix unit tests that used newly generated list of routers so that they
+ check them with respect to the date when they were generated, not
+ with respect to the current time. Fixes bug 40187; bugfix on
+ 0.4.5.1-alpha.
diff --git a/changes/bug40238 b/changes/bug40238
new file mode 100644
index 0000000000..35784a16bb
--- /dev/null
+++ b/changes/bug40238
@@ -0,0 +1,3 @@
+ o Minor bugfixes (logging):
+ - Reject obsolete router/extrainfo descs earlier and more quietly.
+ Fixes bug 40238; bugfix on 0.4.5.1-alpha. \ No newline at end of file
diff --git a/changes/bug40256_045 b/changes/bug40256_045
new file mode 100644
index 0000000000..14e67659e0
--- /dev/null
+++ b/changes/bug40256_045
@@ -0,0 +1,3 @@
+ o Minor bugfixes (documentation):
+ - Fix a formatting error on the documentation for
+ VirtualAddrNetworkIPv6. Fixes bug 40256; bugfix on 0.2.9.4-alpha.
diff --git a/changes/bug40281 b/changes/bug40281
new file mode 100644
index 0000000000..0708039f04
--- /dev/null
+++ b/changes/bug40281
@@ -0,0 +1,6 @@
+ o Minor bugfixes (logging):
+ - Avoid a spurious log message about missing subprotocol versions, when
+ the consensus that we're reading from is older than the current
+ release. . Previously we had made this message nonfatal in this case,
+ but in practice, it is never relevant when the consensus is older than
+ the current release. Fixes bug 40281; bugfix on 0.4.0.1-alpha.
diff --git a/changes/bug40285_045 b/changes/bug40285_045
new file mode 100644
index 0000000000..db4f73cde0
--- /dev/null
+++ b/changes/bug40285_045
@@ -0,0 +1,4 @@
+ o Minor bugfixes (controller):
+ - Fix a "BUG" warning that would appear when a controller chooses the
+ first hop for a circuit, and that circuit completes. Fixes
+ bug 40285; bugfix on 0.3.2.1-alpha.
diff --git a/changes/bug40287 b/changes/bug40287
new file mode 100644
index 0000000000..5a9c899d52
--- /dev/null
+++ b/changes/bug40287
@@ -0,0 +1,4 @@
+ o Minor bugfixes (directory authority):
+ - Now that exit relays don't allow exit connections to directory authority
+ DirPorts (network reentry), disable authorities' reachability self test
+ on the DirPort. Fixes bug 40287; bugfix on 0.4.5.5-rc.
diff --git a/changes/bug40298 b/changes/bug40298
new file mode 100644
index 0000000000..8b8b0bbc12
--- /dev/null
+++ b/changes/bug40298
@@ -0,0 +1,3 @@
+ o Minor bugfixes (portability):
+ - Fix a non-portable usage of "==" with "test" in the configure script.
+ Fixes bug 40298; bugfix on 0.4.5.1-alpha.
diff --git a/changes/bug40315 b/changes/bug40315
new file mode 100644
index 0000000000..9e9c740d96
--- /dev/null
+++ b/changes/bug40315
@@ -0,0 +1,5 @@
+ o Minor bugfixes (Linux, relay):
+ - Fix a bug in determining total available system memory that would have
+ been triggered if the format of /proc/meminfo had ever changed
+ to include "MemTotal:" in the middle of a line. Fixes bug 40315;
+ bugfix on 0.2.5.4-alpha.
diff --git a/changes/bug40318 b/changes/bug40318
new file mode 100644
index 0000000000..cc02f08ca0
--- /dev/null
+++ b/changes/bug40318
@@ -0,0 +1,4 @@
+ o Minor bugfixes (configuration tests bsd):
+ - Fix glob processing errors when globs expand to invalid paths on
+ BSD systems. Fixes bug 40318; bugfix on 0.4.5.1-alpha. Patch by
+ Daniel Pinto.
diff --git a/changes/bug4631 b/changes/bug4631
deleted file mode 100644
index be3dd2b43e..0000000000
--- a/changes/bug4631
+++ /dev/null
@@ -1,6 +0,0 @@
- o Minor bugfixes (directory authorities):
- - Directory authorities reject votes that arrive too late. In particular,
- once an authority has started fetching missing votes, it no longer
- accepts new votes posted by other authorities. This change helps prevent
- a consensus split, where only some authorities have the late vote.
- Fixes bug 4631; bugfix on 0.2.0.5-alpha.
diff --git a/changes/doc33417 b/changes/doc33417
deleted file mode 100644
index 0fc868fc65..0000000000
--- a/changes/doc33417
+++ /dev/null
@@ -1,3 +0,0 @@
- o Documentation (manpage):
- - Refrain from mentioning nicknames in manpage section for MyFamily torrc
- option. Resolves issue 33417.
diff --git a/changes/doc34133 b/changes/doc34133
deleted file mode 100644
index abe9db6148..0000000000
--- a/changes/doc34133
+++ /dev/null
@@ -1,6 +0,0 @@
- o Documentation:
- - Correctly document that we search for a system torrc file before
- Document the limitations of using %include on config files with
- seccomp sandbox enabled. No new files can be added to the
- %included directories. Fixes documentation bug 34133; bugfix
- on 0.3.1.1-alpha. Patch by Daniel Pinto.
diff --git a/changes/parallel_unit_test b/changes/parallel_unit_test
deleted file mode 100644
index 79de28636d..0000000000
--- a/changes/parallel_unit_test
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features (tests):
- - Our "make check" target now runs the unit tests in 8 parallel chunks.
- Doing this speeds up hardened CI builds by more than a factor of two.
- Closes ticket 40098.
diff --git a/changes/ticket18888 b/changes/ticket18888
new file mode 100644
index 0000000000..279eab76ad
--- /dev/null
+++ b/changes/ticket18888
@@ -0,0 +1,3 @@
+ o Minor features (safety):
+ - Log a warning at startup if Tor is built with compile-time options that
+ are likely to make it less stable or reliable. Closes ticket 18888.
diff --git a/changes/ticket22473 b/changes/ticket22473
new file mode 100644
index 0000000000..c7496f9da7
--- /dev/null
+++ b/changes/ticket22473
@@ -0,0 +1,3 @@
+ o Removed features (controller):
+ - Remove the "GETINFO network-status" controller command. It has
+ been deprecated since 0.3.1.1-alpha. Closes ticket 22473.
diff --git a/changes/ticket24308 b/changes/ticket24308
deleted file mode 100644
index e614785265..0000000000
--- a/changes/ticket24308
+++ /dev/null
@@ -1,6 +0,0 @@
- o Minor features (denial-of-service memory limiter):
- - Allow the user to configure even lower values for the MaxMemInQueues
- parameter. Relays now enforce a minimum of 64 MB, when previously
- the minimum was 256 MB. On clients, there is no minimum. Relays and
- clients will both warn if the value is set so low that Tor is likely
- to stop working. Closes ticket 24308.
diff --git a/changes/ticket24844 b/changes/ticket24844
deleted file mode 100644
index da55b4cf67..0000000000
--- a/changes/ticket24844
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features (v3 onion servies):
- - Add v3 onion service status to the dumpstats() call which is
- triggered by a SIGUSR1 signal. Previously, we only did v2
- onion services. Closes ticket 24844. Patch by Neel Chauhan.
diff --git a/changes/ticket25528 b/changes/ticket25528
new file mode 100644
index 0000000000..cfc6c91fb7
--- /dev/null
+++ b/changes/ticket25528
@@ -0,0 +1,6 @@
+ o Minor bugfixes (client, bridge, configuration):
+ - Exit tor on a misconfiguration when the Bridge line has a transport but
+ no corresponding ClientTransportPlugin can be found. Prior to this fix,
+ tor would attempt to connect to the bridge directly without using the
+ transport leading to a possible leak on the wire. Fixes bug 25528;
+ bugfix on 0.2.6.1-alpha.
diff --git a/changes/ticket28208 b/changes/ticket28208
deleted file mode 100644
index 8818aad1d5..0000000000
--- a/changes/ticket28208
+++ /dev/null
@@ -1,4 +0,0 @@
- o Testing:
- - Use the "bridges+hs-v23" chutney network flavor in "make test-network".
- This test requires a recent version of chutney (mid-February 2020).
- Closes ticket 28208.
diff --git a/changes/ticket28992 b/changes/ticket28992
deleted file mode 100644
index 3e45d73e45..0000000000
--- a/changes/ticket28992
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (onion service v3, client):
- - Remove a BUG() that is causing a stacktrace for a situation that very
- rarely happens but still can. Fixes bug 28992; bugfix on 0.3.2.1-alpha.
diff --git a/changes/ticket31576 b/changes/ticket31576
deleted file mode 100644
index ab984cf3d4..0000000000
--- a/changes/ticket31576
+++ /dev/null
@@ -1,3 +0,0 @@
- o Removed features:
- - Stop shipping contrib/dist/rc.subr file, as it is not being used on
- FreeBSD anymore. Closes issue 31576.
diff --git a/changes/ticket31634 b/changes/ticket31634
deleted file mode 100644
index 2777595036..0000000000
--- a/changes/ticket31634
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features (testing, architeture):
- - Our test scripts now double-check that subsystem initialization order
- is consistent with the inter-module dependencies established by our
- .may_include files. Implements ticket 31634.
diff --git a/changes/ticket31812 b/changes/ticket31812
deleted file mode 100644
index 869e494892..0000000000
--- a/changes/ticket31812
+++ /dev/null
@@ -1,4 +0,0 @@
- o Documentation:
- - Replace most http:// URLs in our code and documentation with https://
- URLs. (We have left unchanged the code in src/ext/, and the text in
- LICENSE.) Closes ticket 31812. Patch from Jeremy Rand.
diff --git a/changes/ticket32088 b/changes/ticket32088
deleted file mode 100644
index 0d4fc74754..0000000000
--- a/changes/ticket32088
+++ /dev/null
@@ -1,13 +0,0 @@
- o Major features (Proposal 310, performance + security):
- - Implements Proposal 310 - Bandaid on guard selection.
- Proposal 310 solves a load-balancing issue within Prop271 which strongly
- impact experimental research with Shadow.
- Security improvement: Proposal 310 prevents any newly Guard relay to
- have a chance to get into the primary list of older Tor clients,
- except if the N first sampled guards of these clients are unreachable.
- Implements recommendation from 32088.
-
- Proposal 310 is linked to the CLAPS project researching optimal
- client location-aware path selections. This project is a collaboration
- between the UCLouvain Crypto Group, the U.S. Naval Research Laboratory and
- Princeton University.
diff --git a/changes/ticket32143 b/changes/ticket32143
deleted file mode 100644
index 7f8a809ba5..0000000000
--- a/changes/ticket32143
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features (continuous integration):
- - Run unit-test and integration test (Stem, Chutney) jobs with
- ALL_BUGS_ARE_FATAL macro being enabled on Travis and Appveyor.
- Resolves ticket 32143.
diff --git a/changes/ticket32178 b/changes/ticket32178
new file mode 100644
index 0000000000..c13e490cb0
--- /dev/null
+++ b/changes/ticket32178
@@ -0,0 +1,3 @@
+ o Minor bugfixes (logging):
+ - Remove trailing whitespaces from control event log messages. Fixes bug
+ 32178; bugfix on 0.1.1.1-alpha. Based on a patch by Amadeusz Pawlik.
diff --git a/changes/ticket32542 b/changes/ticket32542
deleted file mode 100644
index c52335b059..0000000000
--- a/changes/ticket32542
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor feature (onion service client, SOCKS5):
- - Add 3 new SocksPort ExtendedErrors (F2, F3, F7) that reports back new type
- of onion service connection failures. Closes ticket 32542.
diff --git a/changes/ticket32622 b/changes/ticket32622
deleted file mode 100644
index 1c663567fd..0000000000
--- a/changes/ticket32622
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor features (bootstrap reporting):
- - Report more detailed reasons for bootstrap failure when the failure
- happens due to a TLS error. Previously we would just call these errors
- "MISC" when they happened during read, and "DONE" when they
- happened during any other TLS operation. Closes ticket 32622.
diff --git a/changes/ticket32696 b/changes/ticket32696
deleted file mode 100644
index 8f56fc394e..0000000000
--- a/changes/ticket32696
+++ /dev/null
@@ -1,7 +0,0 @@
- o Minor features (directory authority):
- - Authorities now recommend protocol versions that are supported
- by Tor 0.3.5 and later. (Earlier versions of Tor have been
- deprecated since January of this year.) This recommendation
- will cause older clients and relays to give a warning on startup,
- or when they download a consensus directory.
- Closes ticket 32696.
diff --git a/changes/ticket32720 b/changes/ticket32720
deleted file mode 100644
index 87c540b7ff..0000000000
--- a/changes/ticket32720
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features (directory):
- - Remember the number of bytes we have downloaded for each directory
- purpose while bootstrapping, and while fully bootstrapped. Log this
- information as part of the heartbeat message. Closes ticket 32720.
diff --git a/changes/ticket32792 b/changes/ticket32792
deleted file mode 100644
index 553cf0ca81..0000000000
--- a/changes/ticket32792
+++ /dev/null
@@ -1,3 +0,0 @@
- o Testing:
- - When a Travis chutney job fails, use chutney's new "diagnostics.sh" tool
- to produce detailed diagnostic output. Closes ticket 32792.
diff --git a/changes/ticket32873 b/changes/ticket32873
deleted file mode 100644
index 65ea1f64ad..0000000000
--- a/changes/ticket32873
+++ /dev/null
@@ -1,6 +0,0 @@
- o Minor features (control port):
- - Return a descriptive error message from the 'GETINFO
- status/fresh-relay-descs' command on the control port.
- Previously, we returned a generic error of "Error
- generating descriptor". Closes ticket 32873. Patch by
- Neel Chauhan.
diff --git a/changes/ticket32888 b/changes/ticket32888
deleted file mode 100644
index ce7fb40b30..0000000000
--- a/changes/ticket32888
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features (logging):
- - When trying to find our own address, add debug-level logging
- to report the sources of candidate addresses. Closes ticket
- 32888.
diff --git a/changes/ticket32905 b/changes/ticket32905
deleted file mode 100644
index 6f420ec693..0000000000
--- a/changes/ticket32905
+++ /dev/null
@@ -1,6 +0,0 @@
- o Removed features:
- - Remove the ClientAutoIPv6ORPort option. This option attempted
- to randomly choose between IPv4 and IPv6 for client connections,
- and isn't a true implementation of Happy Eyeballs. Often, this
- option failed on IPv4-only or IPv6-only connections. Closes
- ticket 32905. Patch by Neel Chauhan.
diff --git a/changes/ticket32994 b/changes/ticket32994
deleted file mode 100644
index 43a32afa78..0000000000
--- a/changes/ticket32994
+++ /dev/null
@@ -1,3 +0,0 @@
- o Code simplification and refactoring:
- - Rewrite port_parse_config() to use the default port flags from
- port_cfg_new(). Closes ticket 32994. Patch by MrSquanchee.
diff --git a/changes/ticket33014 b/changes/ticket33014
deleted file mode 100644
index 885051d9cf..0000000000
--- a/changes/ticket33014
+++ /dev/null
@@ -1,3 +0,0 @@
- o Code simplification and refactoring (onion service):
- - Refactor configuration parsing to use the new config subsystem code.
- Closes ticket 33014.
diff --git a/changes/ticket33192 b/changes/ticket33192
deleted file mode 100644
index 97f976226b..0000000000
--- a/changes/ticket33192
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor feature (python):
- - Stop assuming that /usr/bin/python exists. Instead of using a
- hardcoded path in scripts that still use Python 2, use /usr/bin/env,
- similarly to the scripts that use Python 3. Fixes bug 33192; bugfix
- on 0.4.2. \ No newline at end of file
diff --git a/changes/ticket33194 b/changes/ticket33194
deleted file mode 100644
index b87e55348e..0000000000
--- a/changes/ticket33194
+++ /dev/null
@@ -1,4 +0,0 @@
- o Testing:
- - Remove a redundant distcheck job. Closes ticket 33194.
- - Sort the Travis jobs in order of speed. Putting the slowest jobs first
- takes full advantage of Travis job concurrency. Closes ticket 33194.
diff --git a/changes/ticket33195 b/changes/ticket33195
deleted file mode 100644
index 11abd4816e..0000000000
--- a/changes/ticket33195
+++ /dev/null
@@ -1,4 +0,0 @@
- o Testing:
- - Stop allowing the Chutney IPv6 Travis job to fail. This job was
- previously configured to fast_finish (which requires allow_failure), to
- speed up the build. Closes ticket 33195.
diff --git a/changes/ticket33275 b/changes/ticket33275
deleted file mode 100644
index bff3a7a3ad..0000000000
--- a/changes/ticket33275
+++ /dev/null
@@ -1,5 +0,0 @@
- o Documentation (manpage):
- - Alphabetize the Denial of Service Mitigation Options, Directory
- Authority Server Options, Hidden Service Options, and Testing
- Network Options sections of the tor(1) manpage. Closes ticket
- 33275. Work by Swati Thacker as part of Google Season of Docs.
diff --git a/changes/ticket33280 b/changes/ticket33280
deleted file mode 100644
index b90c3086ea..0000000000
--- a/changes/ticket33280
+++ /dev/null
@@ -1,4 +0,0 @@
- o Testing:
- - Add test-network-ipv4 and test-network-ipv6 jobs to the Makefile.
- These jobs run the IPv4-only and dual-stack chutney flavours from
- test-network-all. Closes ticket 33280.
diff --git a/changes/ticket33300 b/changes/ticket33300
deleted file mode 100644
index 9b0bdce372..0000000000
--- a/changes/ticket33300
+++ /dev/null
@@ -1,3 +0,0 @@
- o Testing:
- - Add a basic IPv6 test to "make test-network". This test only runs when
- the local machine has an IPv6 stack. Closes ticket 33300.
diff --git a/changes/ticket33303 b/changes/ticket33303
deleted file mode 100644
index b7ac7b5067..0000000000
--- a/changes/ticket33303
+++ /dev/null
@@ -1,4 +0,0 @@
- o Testing:
- - Run the test-network-ipv6 Makefile target in the Travis CI IPv6 chutney
- job. This job runs on macOS, so it's a bit slow.
- Closes ticket 33303.
diff --git a/changes/ticket33316 b/changes/ticket33316
deleted file mode 100644
index 25b0444078..0000000000
--- a/changes/ticket33316
+++ /dev/null
@@ -1,15 +0,0 @@
- o Minor bugfixes (initialization):
- - Initialize the subsystems in our code in an order more closely
- corresponding to their dependencies, so that every system is
- initialized before the ones that (theoretically) depend on it.
- Fixes bug 33316; bugfix on 0.4.0.1-alpha.
-
- o Minor features (tests):
- - Initialize all subsystems at the beginning of our unit test harness,
- to avoid crashes due to uninitialized subsystems.
- Follow-up from ticket 33316.
-
- o Code simplification and refactoring:
- - Merge the orconn and ocirc events into the "core" subsystem, which
- manages or connections and origin circuits. Previously they
- were isolated in subsystems of their own.
diff --git a/changes/ticket33334 b/changes/ticket33334
deleted file mode 100644
index ada3cb284c..0000000000
--- a/changes/ticket33334
+++ /dev/null
@@ -1,5 +0,0 @@
- o Testing:
- - Test v3 onion services to tor's mixed IPv4 chutney network. And add a
- mixed IPv6 chutney network. These networks are used in the
- test-network-all, test-network-ipv4, and test-network-ipv6 make targets.
- Closes ticket 33334.
diff --git a/changes/ticket33339 b/changes/ticket33339
deleted file mode 100644
index 75ccb3546f..0000000000
--- a/changes/ticket33339
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor feature (developer tools):
- - Add a script to help check the alphabetical ordering of option
- names in a manpage. Closes ticket 33339.
diff --git a/changes/ticket33346 b/changes/ticket33346
deleted file mode 100644
index acbbae5169..0000000000
--- a/changes/ticket33346
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor features (linux seccomp2 sandbox):
- - Permit the unlinkat() syscall, which some Libc implementations
- use to implement unlink(). Closes ticket 33346.
diff --git a/changes/ticket33349 b/changes/ticket33349
deleted file mode 100644
index 0458a72c8d..0000000000
--- a/changes/ticket33349
+++ /dev/null
@@ -1,4 +0,0 @@
- o Code simplification and refactoring:
- - Updated comments in 'scheduler.c' to reflect old code changes,
- and simplified the scheduler channel state change code. Closes
- ticket 33349.
diff --git a/changes/ticket33366 b/changes/ticket33366
deleted file mode 100644
index 1310c493c2..0000000000
--- a/changes/ticket33366
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor features (compilation size):
- - Most Server-side DNS code is now disabled when building without
- support for relay mode. Closes ticket 33366.
diff --git a/changes/ticket33368 b/changes/ticket33368
deleted file mode 100644
index ecc6f66f4e..0000000000
--- a/changes/ticket33368
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor features (client-only compilation):
- - Disable more code related to the ext_orport protocol when compiling
- without support for relay mode. Closes ticket 33368.
diff --git a/changes/ticket33369 b/changes/ticket33369
deleted file mode 100644
index c55335c5b7..0000000000
--- a/changes/ticket33369
+++ /dev/null
@@ -1,4 +0,0 @@
- o Documentation (manpage):
- - Add cross reference links and a table of contents to the HTML
- tor manpage. Closes ticket 33369. Work by Swati Thacker as
- part of Google Season of Docs.
diff --git a/changes/ticket33370 b/changes/ticket33370
deleted file mode 100644
index 41e03357f0..0000000000
--- a/changes/ticket33370
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor features (client-only compilation):
- - Disable more of our self-testing code when support for relay mode is
- disabled. Closes ticket 33370.
diff --git a/changes/ticket33400 b/changes/ticket33400
deleted file mode 100644
index 7603890765..0000000000
--- a/changes/ticket33400
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor feature (onion service v3):
- - Log at INFO level why the service can not upload its descriptor(s). Closes
- ticket 33400; bugfix on 0.3.2.1-alpha.
diff --git a/changes/ticket33436 b/changes/ticket33436
deleted file mode 100644
index 69b5545c6d..0000000000
--- a/changes/ticket33436
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features (directory authority, shared random):
- - Refactor more authority-only parts of the shared-random scheduling code
- to reside in the dirauth module, and to be disabled when compiling with
- --disable-module-dirauth. Closes ticket 33436.
diff --git a/changes/ticket33451 b/changes/ticket33451
deleted file mode 100644
index 74dd6d1ad8..0000000000
--- a/changes/ticket33451
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor features (developer tools):
- - Add a script ("git-install-tools.sh") to install git hooks and helper
- scripts. Closes ticket 33451.
diff --git a/changes/ticket33458 b/changes/ticket33458
deleted file mode 100644
index 885c6dc505..0000000000
--- a/changes/ticket33458
+++ /dev/null
@@ -1,4 +0,0 @@
- 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/ticket33624 b/changes/ticket33624
new file mode 100644
index 0000000000..eded3b4dee
--- /dev/null
+++ b/changes/ticket33624
@@ -0,0 +1,5 @@
+ o Minor bugfixes (configure, static build):
+ - Change our search library configure macro linker flag order so it works
+ for certain compilers that need the right order. Fixes bug 33624; bugfix
+ on 0.1.1.0-alpha.
+
diff --git a/changes/ticket33633 b/changes/ticket33633
deleted file mode 100644
index de030a6000..0000000000
--- a/changes/ticket33633
+++ /dev/null
@@ -1,6 +0,0 @@
- o Code simplification and refactoring:
- - Move the circuit extend code to the relay module.
- Split the circuit extend function into smaller functions.
- Closes ticket 33633.
- - Move LOG_PROTOCOL_WARN to app/config.c. Resolves a dependency inversion.
- Closes ticket 33633.
diff --git a/changes/ticket33642 b/changes/ticket33642
deleted file mode 100644
index b81edf7613..0000000000
--- a/changes/ticket33642
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features (developer tooling):
- - Refrain from listing all .a files that are generated by Tor build in
- .gitignore. Add a single wildcard *.a entry that covers all of them for
- present and future. Closes ticket 33642.
diff --git a/changes/ticket33679 b/changes/ticket33679
deleted file mode 100644
index d37842d065..0000000000
--- a/changes/ticket33679
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features (IPv6 Support, address.c):
- - Adds IPv6 support to tor_addr_is_valid(). Adds tests for the
- above changes and tor_addr_is_null(). Closes ticket 33679.
- Patch by MrSquanchee.
diff --git a/changes/ticket33747 b/changes/ticket33747
deleted file mode 100644
index 57c72e9d0a..0000000000
--- a/changes/ticket33747
+++ /dev/null
@@ -1,7 +0,0 @@
- o Minor bugfixes (rate limiting, bridges, pluggable transports):
- - On a bridge, treat all connections from an ExtORPort as remote
- by default for the purposes of rate-limiting. Previously,
- bridges would treat the connection as local unless they explicitly
- received a "USERADDR" command. ExtORPort connections still
- count as local if there is a USERADDR command with an explicit local
- address. Fixes bug 33747; bugfix on 0.2.5.1-alpha.
diff --git a/changes/ticket33778 b/changes/ticket33778
deleted file mode 100644
index a33c647a6e..0000000000
--- a/changes/ticket33778
+++ /dev/null
@@ -1,3 +0,0 @@
- o Documentation (manpage):
- - Updated the options set by TestingTorNetwork in the man page.
- Closes ticket 33778.
diff --git a/changes/ticket33779 b/changes/ticket33779
deleted file mode 100644
index d4bc769ebb..0000000000
--- a/changes/ticket33779
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (onion service, logging):
- - Typo in a log info level when PublishHidServDescriptors is set to 0.
- Fixes bug 33779; bugfix on 0.3.2.1-alpha.
diff --git a/changes/ticket33788 b/changes/ticket33788
deleted file mode 100644
index 236c056623..0000000000
--- a/changes/ticket33788
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features (code safety):
- - Check for failures of tor_inet_ntop() and tor_inet_ntoa() functions in
- DNS and IP address processing code and adjust codepaths to make them
- less likely to crash entire Tor instance. Resolves issue 33788.
diff --git a/changes/ticket33789 b/changes/ticket33789
deleted file mode 100644
index a7e69793e6..0000000000
--- a/changes/ticket33789
+++ /dev/null
@@ -1,4 +0,0 @@
- o Code simplification and refactoring (relay address):
- - Move a series of functions related to address resolving into their own
- files. Closes ticket 33789.
-
diff --git a/changes/ticket33796 b/changes/ticket33796
deleted file mode 100644
index 9a98bf2d9a..0000000000
--- a/changes/ticket33796
+++ /dev/null
@@ -1,7 +0,0 @@
- o Removed features (IPv6, revert):
- - Revert the client port prefer IPv6 feature because it breaks the
- torsocks use case. The SOCKS resolve command is lacking a mechanism to
- ask for a specific address family (v4 or v6) thus prioritizing IPv6 when
- an IPv4 address is asked on the resolve SOCKS interface resulting in a
- failure. Tor Browser explicitly set PreferIPv6 so this should not affect
- the majority of our users. Closes ticket 33796; bugfix on 0.4.4.1-alpha.
diff --git a/changes/ticket33817 b/changes/ticket33817
deleted file mode 100644
index 9c22d084eb..0000000000
--- a/changes/ticket33817
+++ /dev/null
@@ -1,12 +0,0 @@
- o Major features (IPv6, relay):
- - Relays may extend circuits over IPv6, if the relay has an IPv6 ORPort,
- and the client supplies the other relay's IPv6 ORPort in the EXTEND2
- cell. IPv6 extends will be used by the relay IPv6 ORPort self-tests in
- 33222. Closes ticket 33817.
- - Consider IPv6-only EXTEND2 cells valid on relays. Log a protocol warning
- if the IPv4 or IPv6 address is an internal address, and internal
- addresses are not allowed. But continue to use the other address, if it
- is valid. Closes ticket 33817.
- - If a relay can extend over IPv4 and IPv6, it chooses between them
- uniformly at random. Closes ticket 33817.
- - Re-use existing IPv6 connections for circuit extends. Closes ticket 33817.
diff --git a/changes/ticket33873 b/changes/ticket33873
deleted file mode 100644
index c45191181a..0000000000
--- a/changes/ticket33873
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfix (SOCKS, onion service client):
- - Also detect bad v3 onion service address of the wrong length when
- returning the F6 ExtendedErrors code. Fixes bug 33873; bugfix on
- 0.4.3.1-alpha.
diff --git a/changes/ticket33880 b/changes/ticket33880
deleted file mode 100644
index c1889bb134..0000000000
--- a/changes/ticket33880
+++ /dev/null
@@ -1,6 +0,0 @@
- o Minor bugfixes (relay, usability):
- - Adjust the rules for when to warn about having too many connections
- to other relays. Previously we'd tolerate up to 1.5 connections
- per relay on average. Now we tolerate more connections for directory
- authorities, and raise the number of total connections we need
- to see before we warn. Fixes bug 33880; bugfix on 0.3.1.1-alpha.
diff --git a/changes/ticket33901 b/changes/ticket33901
deleted file mode 100644
index b824cc5b07..0000000000
--- a/changes/ticket33901
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features (IPv6, relay):
- - Allow clients and relays to send dual-stack and IPv6-only EXTEND2 cells.
- Parse dual-stack and IPv6-only EXTEND2 cells on relays.
- Closes ticket 33901.
diff --git a/changes/ticket33956 b/changes/ticket33956
deleted file mode 100644
index 7ad802797d..0000000000
--- a/changes/ticket33956
+++ /dev/null
@@ -1,5 +0,0 @@
- o Code simplification and refactoring:
- - Define and use a new constant TOR_ADDRPORT_BUF_LEN which is like
- TOR_ADDR_BUF_LEN but includes enough space for an IP address,
- brackets, seperating colon, and port number. Closes ticket 33956.
- Patch by Neel Chauhan.
diff --git a/changes/ticket34087 b/changes/ticket34087
deleted file mode 100644
index 16990c305a..0000000000
--- a/changes/ticket34087
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfix (onion service v3 client):
- - Remove a BUG() warning that can occur naturally. Fixes bug 34087; bugfix
- on 0.3.2.1-alpha.
diff --git a/changes/ticket34211 b/changes/ticket34211
deleted file mode 100644
index b454873abf..0000000000
--- a/changes/ticket34211
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor features (windows):
- - Add support for console control signals like Ctrl+C in Windows
- Closes ticket 34211. Patch from Damon Harris (TheDcoder).
diff --git a/changes/ticket34255_043 b/changes/ticket34255_043
deleted file mode 100644
index 5cfec1d48d..0000000000
--- a/changes/ticket34255_043
+++ /dev/null
@@ -1,3 +0,0 @@
- o Documentation:
- - Fix several doxygen warnings related to imbalanced groups.
- Closes ticket 34255.
diff --git a/changes/ticket34382 b/changes/ticket34382
deleted file mode 100644
index 0bdfe22a5e..0000000000
--- a/changes/ticket34382
+++ /dev/null
@@ -1,6 +0,0 @@
- o Minor features (Linux seccomp2 sandbox, compilation):
- - Allow Tor to build on platforms where it doesn't know how to
- report which syscall had caused the linux seccomp2 sandbox
- to fail. This change should make the sandbox code more portable
- to less common Linux architectures.
- Closes ticket 34382.
diff --git a/changes/ticket40003 b/changes/ticket40003
deleted file mode 100644
index 240f464353..0000000000
--- a/changes/ticket40003
+++ /dev/null
@@ -1,3 +0,0 @@
- o Deprecated features (onion service v2):
- - Add deprecation warning for onion service version 2. Tor now logs a
- warning once if a version 2 service is configured. Closes ticket 40003.
diff --git a/changes/ticket40005 b/changes/ticket40005
deleted file mode 100644
index 12727e0a06..0000000000
--- a/changes/ticket40005
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfix (control port, onion service):
- - Consistently use 'address' in "Invalid v3 address" response to
- ONION_CLIENT_AUTH commands. Fixes bug 40005; bugfix on 0.4.3.1-alpha.
diff --git a/changes/ticket40026 b/changes/ticket40026
deleted file mode 100644
index f87c2964e0..0000000000
--- a/changes/ticket40026
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfix (CI, Windows):
- - Don't use stdio 64 bit printf format when compiling with MINGW on
- Appveyor. Fixes bug 40026; bugfix on 0.3.5.5-alpha.
diff --git a/changes/ticket40030 b/changes/ticket40030
deleted file mode 100644
index c5f3ca4ff9..0000000000
--- a/changes/ticket40030
+++ /dev/null
@@ -1,7 +0,0 @@
- 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/changes/ticket40035 b/changes/ticket40035
deleted file mode 100644
index 8cdd447199..0000000000
--- a/changes/ticket40035
+++ /dev/null
@@ -1,5 +0,0 @@
- o Major bugfixes (NSS):
- - When running with NSS enabled, make sure that NSS knows to expect
- nonblocking sockets. Previously, we set our TCP sockets as blocking,
- but did not tell NSS about the fact, which in turn could lead to
- unexpected blocking behavior. Fixes bug 40035; bugfix on 0.3.5.1-alpha.
diff --git a/changes/ticket40061 b/changes/ticket40061
deleted file mode 100644
index 227664d010..0000000000
--- a/changes/ticket40061
+++ /dev/null
@@ -1,5 +0,0 @@
- o Major feature (fallback directory list):
- - Replace the 148 fallback directories originally included in
- Tor 0.4.1.4-rc (of which around 105 are still functional) with
- a list of 144 fallbacks generated in July 2020.
- Closes ticket 40061.
diff --git a/changes/ticket40071 b/changes/ticket40071
new file mode 100644
index 0000000000..1e294a68e7
--- /dev/null
+++ b/changes/ticket40071
@@ -0,0 +1,7 @@
+ o Minor bugfixes (relay, address):
+ - Don't trigger an IP change if no new valid IP can be found. Fixes bug
+ 40071; bugfix on 0.4.5.1-alpha.
+ - When attempting to discover our IP, don't launch a descriptor fetch
+ anymore but rather a simple test circuit since the address discovery is
+ through the NETINFO cell now from the authorities. Fixes bug 40071; bugfix
+ on 0.4.5.1-alpha.
diff --git a/changes/ticket40073 b/changes/ticket40073
deleted file mode 100644
index 30b028c042..0000000000
--- a/changes/ticket40073
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (relay configuration, crash):
- - Avoid a fatal assert() when failing to create a listener connection for an
- address that was in use. Fixes bug 40073; bugfix on 0.3.5.1-alpha.
diff --git a/changes/ticket40081 b/changes/ticket40081
deleted file mode 100644
index 683ae33518..0000000000
--- a/changes/ticket40081
+++ /dev/null
@@ -1,6 +0,0 @@
- o Minor features (security):
- - Channels using obsolete versions of the Tor link protocol are no
- longer allowed to circumvent address-canonicity checks.
- (This is only a minor issue, since such channels have no way to
- set ed25519 keys, and therefore should always be rejected.)
- Closes ticket 40081.
diff --git a/changes/ticket40089 b/changes/ticket40089
deleted file mode 100644
index 121e8e9820..0000000000
--- a/changes/ticket40089
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features (control port):
- - If a ClientName was specified in ONION_CLIENT_AUTH_ADD for an
- onion service, display it when we use ONION_CLIENT_AUTH_VIEW
- on it. Closes ticket 40089. Patch by Neel Chauhan.
diff --git a/changes/ticket40106 b/changes/ticket40106
new file mode 100644
index 0000000000..3f344d478f
--- /dev/null
+++ b/changes/ticket40106
@@ -0,0 +1,6 @@
+ o Minor bugfixes (config, bridge):
+ - Don't initiate a connection to a bridge without a corresponding
+ transport. Fixes bug 40106; bugfix on 0.4.5.1-alpha.
+ - This also reverts an earlier fix we did for this that would validate
+ configuration to avoid such situation but turns out it wouldn't work for
+ a DisableNetwork thus the new approach.
diff --git a/changes/ticket40109 b/changes/ticket40109
deleted file mode 100644
index d99db65aa4..0000000000
--- a/changes/ticket40109
+++ /dev/null
@@ -1,6 +0,0 @@
- o Major bugfixes (onion services, DoS):
- - The consensus parameters for the onion service DoS defenses was
- overwriting the circuit parameters that could have been set by the service
- operator using HiddenServiceEnableIntroDoSDefense. Fixes bug 40109; bugfix
- on 0.4.2.1-alpha.
-
diff --git a/changes/ticket40111 b/changes/ticket40111
new file mode 100644
index 0000000000..a82ca0d489
--- /dev/null
+++ b/changes/ticket40111
@@ -0,0 +1,7 @@
+ o Minor bugfixes (configure, build):
+ - Fix the --enable-static-tor switch to properly set the -static compile
+ option onto the tor binary only. Fixes bug 40111; bugfix on
+ 0.2.3.1-alpha.
+ - Path to static libevent has been fixed as well which affects the
+ --enable-static-libevent to behave correctly now. The .a file is in
+ .libs/ of libevent repository, not at the root.
diff --git a/changes/ticket40125 b/changes/ticket40125
deleted file mode 100644
index c68e3ce7b3..0000000000
--- a/changes/ticket40125
+++ /dev/null
@@ -1,4 +0,0 @@
- o Testing (onion service v2):
- - Fix a rendezvous cache unit test that was triggering an underflow on the
- global rend cache allocation. Fixes bug 40125; bugfix on
- 0.2.8.1-alpha.
diff --git a/changes/ticket40126 b/changes/ticket40126
deleted file mode 100644
index 1f5806e6cb..0000000000
--- a/changes/ticket40126
+++ /dev/null
@@ -1,4 +0,0 @@
- o Testing (onion service v2):
- - Fix another rendezvous cache unit test that was triggering an underflow on the
- global rend cache allocation. Fixes bug 40126; bugfix on
- 0.2.8.1-alpha.
diff --git a/changes/ticket40133 b/changes/ticket40133
deleted file mode 100644
index 8bbe00b6b2..0000000000
--- a/changes/ticket40133
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor features (protocol simplification):
- - Tor no longer allows subprotocol versions larger than 63. Previously
- versions up to UINT32_MAX were allowed, which significantly complicated
- our code.
- Implements proposal 318; closes ticket 40133.
diff --git a/changes/ticket40135 b/changes/ticket40135
deleted file mode 100644
index 9b60b4f655..0000000000
--- a/changes/ticket40135
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfix (logging):
- - Remove a debug logging statement that uselessly spam the logs. Fixes bug
- 40135; bugfix on 0.3.5.0-alpha.
diff --git a/changes/ticket40142 b/changes/ticket40142
new file mode 100644
index 0000000000..25a96b3df3
--- /dev/null
+++ b/changes/ticket40142
@@ -0,0 +1,3 @@
+ o Minor bugfixes (logging, flow control):
+ - Turn a SENDME failure log warning into a debug. It can actually happen
+ naturally. Fixes bug 40142; bugfix on 0.4.1.1-alpha.
diff --git a/changes/ticket40162 b/changes/ticket40162
deleted file mode 100644
index 093042f9af..0000000000
--- a/changes/ticket40162
+++ /dev/null
@@ -1,7 +0,0 @@
- o Minor features (authorities):
- - Authorities now list a different set of protocols as required and
- recommended. These lists are chosen so that only truly recommended
- and/or required protocols are included, and so that clients using 0.2.9
- or later will continue to work (even though they are not supported),
- whereas only relays running 0.3.5 or later will meet the requirements.
- Closes ticket 40162.
diff --git a/changes/ticket40164 b/changes/ticket40164
deleted file mode 100644
index c96118d0a4..0000000000
--- a/changes/ticket40164
+++ /dev/null
@@ -1,6 +0,0 @@
- o Minor features (directory authority):
- - Make it possible to specify multiple ConsensusParams torrc lines.
- Now directory authority operators can for example put the main
- ConsensusParams config in one torrc file and then add to it from
- a different torrc file. Closes ticket 40164.
-
diff --git a/changes/ticket40174 b/changes/ticket40174
new file mode 100644
index 0000000000..869a2756f4
--- /dev/null
+++ b/changes/ticket40174
@@ -0,0 +1,4 @@
+ o Minor bugfixes (configure, build):
+ - With USDT tracing enabled, if STAP_PROBEV() is missing, don't attempt to
+ build. Linux supports that macro but not the BSDs. Fixes bug 40174; bugfix
+ on 0.4.5.1-alpha.
diff --git a/changes/ticket40183 b/changes/ticket40183
new file mode 100644
index 0000000000..3c4bdf21e2
--- /dev/null
+++ b/changes/ticket40183
@@ -0,0 +1,4 @@
+ o Minor bugfixes (port configuration):
+ - Second non ORPort of a different family (ex: SocksPort [::1]:9050) was
+ ignored due to a logical configuration parsing error. Fixes bug 40183;
+ bugfix on 0.4.5.1-alpha.
diff --git a/changes/ticket40188 b/changes/ticket40188
new file mode 100644
index 0000000000..e29b2a9438
--- /dev/null
+++ b/changes/ticket40188
@@ -0,0 +1,4 @@
+ o Minor features (documentation):
+ - Mention the !badexit directive that can appear in an authority's
+ approved-routers file, and update the description of the !invalid
+ directive. Closes ticket 40188.
diff --git a/changes/ticket40195 b/changes/ticket40195
new file mode 100644
index 0000000000..caa0bace94
--- /dev/null
+++ b/changes/ticket40195
@@ -0,0 +1,5 @@
+ o Minor bugfixes (configuration, ports):
+ - Fix an issue where an ORPort was validated against other type of ports
+ when it should have been only checked against other ORPorts. This lead to
+ "DirPort auto" to be ignored and failing to be used. Fixes bug 40195;
+ bugfix on 0.4.5.1-alpha.
diff --git a/changes/ticket40201 b/changes/ticket40201
new file mode 100644
index 0000000000..cdf8d99172
--- /dev/null
+++ b/changes/ticket40201
@@ -0,0 +1,3 @@
+ o Minor bugfixes (logging, relay):
+ - Logs the address discovered by the directory authorities if none were
+ configured or detected before. Fixes bug 40201; bugfix on 0.4.5.1-alpha.
diff --git a/changes/ticket40205 b/changes/ticket40205
new file mode 100644
index 0000000000..e21c7fab7c
--- /dev/null
+++ b/changes/ticket40205
@@ -0,0 +1,5 @@
+ o Minor bugfixes (relay, logging, reachability):
+ - When launching bandwidth testing circuit, don't log notice that we are
+ doing a reachability test. Furthermore, avoid to trigger a
+ "CHECKING_REACHABILITY" control event. Fixes bug 40205; bugfix on
+ 0.4.5.1-alpha.
diff --git a/changes/ticket40208 b/changes/ticket40208
new file mode 100644
index 0000000000..5a3a1aa55e
--- /dev/null
+++ b/changes/ticket40208
@@ -0,0 +1,6 @@
+ o Minor bugfixes (relay):
+ - Allow relays to have a RFC1918 address if PublishServerDescriptor is set
+ to 0 and AssumeReachable is set to 1. This is to support the use case of a
+ bridge on a local network that can be used by restricted users on that
+ network to reach the Tor network. Fixes bug 40208; bugfix on
+ 0.4.5.1-alpha.
diff --git a/changes/ticket40221_045 b/changes/ticket40221_045
new file mode 100644
index 0000000000..0f3ab894c2
--- /dev/null
+++ b/changes/ticket40221_045
@@ -0,0 +1,6 @@
+ o Minor features (protocol versions):
+ - Stop claiming to support the "DirCache=1" subprotocol version.
+ Technically, we stopped supporting this subprotocol back in
+ 0.4.5.1-alpha, but we needed to wait for the authorities to stop
+ listing it as "required" before we can drop support. Closes ticket
+ 40221.
diff --git a/changes/ticket40226 b/changes/ticket40226
new file mode 100644
index 0000000000..4775438f63
--- /dev/null
+++ b/changes/ticket40226
@@ -0,0 +1,5 @@
+ o Minor bugfixes (relay, statistics):
+ - The connection statistics were wrongly exported in the extrainfo document
+ due to a problem in the file loading function which would wrongly truncate
+ the file reporting the wrong information. It is now fixed. Fixes bug
+ 40226; bugfix on 0.4.5.1-alpha.
diff --git a/changes/ticket40231 b/changes/ticket40231
new file mode 100644
index 0000000000..a5ba598fd1
--- /dev/null
+++ b/changes/ticket40231
@@ -0,0 +1,4 @@
+ o Minor bugfixes (relay):
+ - If we were unable to build our descriptor, don't mark that we've
+ advertised our descriptor. Also remove an harmless BUG(). Fixes bug 40231;
+ bugfix on 0.4.5.1-alpha.
diff --git a/changes/ticket40243 b/changes/ticket40243
new file mode 100644
index 0000000000..548ec95ab4
--- /dev/null
+++ b/changes/ticket40243
@@ -0,0 +1,4 @@
+ o Major bugfixes (authority, IPv6):
+ - Do not consider multiple relays in the same IPv6 network to be sybils.
+ Sybils are selected based on the /128 now, not the /64. Fixes bug 40243;
+ bugfix on 0.4.5.1-alpha.
diff --git a/changes/ticket40245 b/changes/ticket40245
new file mode 100644
index 0000000000..641372333e
--- /dev/null
+++ b/changes/ticket40245
@@ -0,0 +1,4 @@
+ o Minor features (logging):
+ - Give more visibility to directory authority operators during the
+ consensus voting process and while processing relay descriptors.
+ Closes ticket 40245.
diff --git a/changes/ticket40254 b/changes/ticket40254
new file mode 100644
index 0000000000..9945e3d3b8
--- /dev/null
+++ b/changes/ticket40254
@@ -0,0 +1,4 @@
+ o Minor bugfixes (relay, configuration):
+ - Don't attempt to discover address (IPv4 or IPv6) if no ORPort for it can
+ be found in the configuration. Fixes bug 40254; bugfix on 0.4.5.1-alpha.
+
diff --git a/changes/ticket40257 b/changes/ticket40257
new file mode 100644
index 0000000000..4bcebc45a1
--- /dev/null
+++ b/changes/ticket40257
@@ -0,0 +1,3 @@
+ o Minor bugfixes (metrics port):
+ - Fix a bug warning when the socket was unexpectedly closed. Fixes bug
+ 40257; bugfix on 0.4.5.1-alpha
diff --git a/changes/ticket40279 b/changes/ticket40279
new file mode 100644
index 0000000000..351db40789
--- /dev/null
+++ b/changes/ticket40279
@@ -0,0 +1,4 @@
+ o Major bugfixes (IPv6, relay):
+ - Fix a bug that prevented a relay to publish its descriptor in the case of
+ an auto-discovered IPv6 that was found unreachable for which we always
+ publish if the IPv4 is correct. Fixes bug 40279; bugfix on 0.4.5.1-alpha.
diff --git a/changes/ticket40289 b/changes/ticket40289
new file mode 100644
index 0000000000..cdb36825b0
--- /dev/null
+++ b/changes/ticket40289
@@ -0,0 +1,6 @@
+ o Minor bugfixes (relay, config):
+ - Fix a problem in the removal of duplicate ORPort from the internal port
+ list when loading config file. We were removing wrong ports breaking valid
+ torrc uses cases for multiple ORPorts of the same address family. Fixes
+ bug 40289; bugfix on 0.4.5.1-alpha.
+
diff --git a/changes/ticket40295 b/changes/ticket40295
new file mode 100644
index 0000000000..e6dba80120
--- /dev/null
+++ b/changes/ticket40295
@@ -0,0 +1,3 @@
+ o Minor bugfixes (metrics port):
+ - Fix a BUG() on the MetricsPort for an internal missing handler. Fixes bug
+ 40295; bugfix on 0.4.5.1-alpha.
diff --git a/changes/ticket40300 b/changes/ticket40300
new file mode 100644
index 0000000000..b772ff60a4
--- /dev/null
+++ b/changes/ticket40300
@@ -0,0 +1,8 @@
+ o Minor bugfixes (relay):
+ - Remove a spammy log notice that should not have been indicating the
+ operator that its IPv4/v6 was missing but it was not. Fixes bug 40300;
+ bugfix on 0.4.5.1-alpha.
+ - Do not query the address cache early in the boot process when deciding
+ if we a relay needs to fetch early directory information from an
+ authority. This resulted in a relay falsely believing it didn't have an
+ address and thus triggering an authority fetch at each boot.
diff --git a/changes/ticket40334 b/changes/ticket40334
new file mode 100644
index 0000000000..c1c34384a0
--- /dev/null
+++ b/changes/ticket40334
@@ -0,0 +1,3 @@
+ o Minor bugfixes (onion service):
+ - Remove a harmless BUG() warning when reloading tor configured with onion
+ services. Fixes bug 40334; bugfix on 0.4.5.1-alpha.
diff --git a/changes/ticket40356 b/changes/ticket40356
new file mode 100644
index 0000000000..59c32ce0cc
--- /dev/null
+++ b/changes/ticket40356
@@ -0,0 +1,3 @@
+ o Minor bugfix (onion service, client, memory leak):
+ - An expired cached descriptor could have been overwritten with a new one
+ leading to a memory leak. Fixes bug 40356; bugfix on 0.3.5.1-alpha.
diff --git a/changes/ticket40360 b/changes/ticket40360
new file mode 100644
index 0000000000..4a1b2c3446
--- /dev/null
+++ b/changes/ticket40360
@@ -0,0 +1,5 @@
+ o Minor bugfixes (bridge, pluggable transport):
+ - Fix a regression that prevented to configure a Bridge line without a
+ fingerprint (which is a normal use case). Fixes bug 40360; bugfix on
+ 0.4.5.4-rc.
+
diff --git a/changes/ticket40369 b/changes/ticket40369
new file mode 100644
index 0000000000..abb59a7125
--- /dev/null
+++ b/changes/ticket40369
@@ -0,0 +1,4 @@
+ o Minor bugfixes (build, cross-compilation):
+ - Allow a custom "ar" for cross-compilation. Our previous build script
+ had used the $AR environment variable in most places, but it missed
+ one. Fixes bug 40369; bugfix on 0.4.5.1-alpha.
diff --git a/changes/ticket40373 b/changes/ticket40373
new file mode 100644
index 0000000000..e2ea297bc2
--- /dev/null
+++ b/changes/ticket40373
@@ -0,0 +1,3 @@
+ o Minor features (onion services):
+ - Add warning message when connecting to soon-to-be-deprecated v2 onions.
+ Closes ticket 40373.
diff --git a/changes/ticket6198 b/changes/ticket6198
deleted file mode 100644
index 7f3fdf2fa7..0000000000
--- a/changes/ticket6198
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor features (defense in depth):
- - Wipe more data from connection address fields before returning them to
- the memory heap. Closes ticket 6198.
diff --git a/configure.ac b/configure.ac
index 9ee5dd181a..621fbd1612 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@ dnl Copyright (c) 2007-2019, The Tor Project, Inc.
dnl See LICENSE for licensing information
AC_PREREQ([2.63])
-AC_INIT([tor],[0.4.4.8-dev])
+AC_INIT([tor],[0.4.5.8])
AC_CONFIG_SRCDIR([src/app/main/tor_main.c])
AC_CONFIG_MACRO_DIR([m4])
@@ -16,7 +16,7 @@ configure_flags="$*"
# 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, ["2021-03-16"], # for 0.4.4.8-dev
+AC_DEFINE(APPROX_RELEASE_DATE, ["2021-05-07"], # for 0.4.5.8
[Approximate date when this software was released. (Updated when the version changes.)])
# "foreign" means we don't follow GNU package layout standards
@@ -24,6 +24,11 @@ AC_DEFINE(APPROX_RELEASE_DATE, ["2021-03-16"], # for 0.4.4.8-dev
# "subdir-objects" means put .o files in the same directory as the .c files
AM_INIT_AUTOMAKE([foreign 1.11 subdir-objects -Wall -Werror])
+tor_ac_n_warnings=0
+tor_incr_n_warnings() {
+ tor_ac_n_warnings=`expr $tor_ac_n_warnings + 1`
+}
+
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_CONFIG_HEADERS([orconfig.h])
@@ -124,8 +129,9 @@ if test "$enable_static_tor" = "yes"; then
enable_static_libevent="yes";
enable_static_openssl="yes";
enable_static_zlib="yes";
- CFLAGS="$CFLAGS -static"
+ TOR_STATIC_LDFLAGS="-static"
fi
+AC_SUBST(TOR_STATIC_LDFLAGS)
if test "$enable_system_torrc" = "no"; then
AC_DEFINE(DISABLE_SYSTEM_TORRC, 1,
@@ -256,16 +262,84 @@ AC_ARG_ENABLE(seccomp,
AC_ARG_ENABLE(libscrypt,
AS_HELP_STRING(--disable-libscrypt, [do not attempt to use libscrypt]))
-dnl Enable event tracing which are transformed to debug log statement.
-AC_ARG_ENABLE(event-tracing-debug,
- AS_HELP_STRING(--enable-event-tracing-debug, [build with event tracing to debug log]))
-AM_CONDITIONAL([USE_EVENT_TRACING_DEBUG], [test "x$enable_event_tracing_debug" = "xyes"])
+dnl --- Tracing Options. ---
+
+TOR_TRACE_LIBS=
+
+dnl LTTng instrumentation option.
+AC_ARG_ENABLE(tracing-instrumentation-lttng,
+ AS_HELP_STRING([--enable-tracing-instrumentation-lttng],
+ [build with LTTng-UST instrumentation]))
+AM_CONDITIONAL([USE_TRACING_INSTRUMENTATION_LTTNG],
+ [test "x$enable_tracing_instrumentation_lttng" = "xyes"])
+
+if test "x$enable_tracing_instrumentation_lttng" = "xyes"; then
+ AC_CHECK_HEADERS([lttng/tracepoint.h], [],
+ [AC_MSG_ERROR([LTTng instrumentation headers not found.
+ On Debian, apt install liblttng-ust-dev"])], [])
+ AC_DEFINE([USE_TRACING_INSTRUMENTATION_LTTNG], [1], [Using LTTng instrumentation])
+ TOR_TRACE_LIBS="-llttng-ust -ldl"
+ have_tracing=1
+fi
+
+dnl USDT instrumentation option.
+AC_ARG_ENABLE(tracing-instrumentation-usdt,
+ AS_HELP_STRING([--enable-tracing-instrumentation-usdt],
+ [build with tracing USDT instrumentation]))
+AM_CONDITIONAL([USE_TRACING_INSTRUMENTATION_USDT],
+ [test "x$enable_tracing_instrumentation_usdt" = "xyes"])
+
+if test "x$enable_tracing_instrumentation_usdt" = "xyes"; then
+ AC_CHECK_HEADERS([sys/sdt.h], [],
+ [AC_MSG_ERROR([USDT instrumentation requires sys/sdt.h header.
+ On Debian, apt install systemtap-sdt-dev])], [])
+ AC_MSG_CHECKING([STAP_PROBEV()])
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+ #define SDT_USE_VARIADIC
+ #include <sys/sdt.h>
+ void test(void)
+ {
+ STAP_PROBEV(p, n, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
+ }
+ ]])], [
+ AC_MSG_RESULT([yes])
+ dnl LTTng generates USDT probes if the UST library was built with
+ dnl --with-sdt. There is unfortunately no way to check that so we always
+ dnl build the USDT probes even though LTTng instrumentation was requested.
+ AC_DEFINE([USE_TRACING_INSTRUMENTATION_USDT], [1], [Using USDT instrumentation])
+ have_tracing=1
+ ], [
+ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([USDT tracing support requires STAP_PROBEV()])
+ ])
+fi
-if test x$enable_event_tracing_debug = xyes; then
- AC_DEFINE([USE_EVENT_TRACING_DEBUG], [1], [Tracing framework to log debug])
- AC_DEFINE([TOR_EVENT_TRACING_ENABLED], [1], [Compile the event tracing instrumentation])
+dnl Tracepoints event to debug logs.
+AC_ARG_ENABLE(tracing-instrumentation-log-debug,
+ AS_HELP_STRING([--enable-tracing-instrumentation-log-debug],
+ [build with tracing event to debug log]),
+ AC_DEFINE([USE_TRACING_INSTRUMENTATION_LOG_DEBUG], [1],
+ [Tracepoints to log debug]), [])
+AM_CONDITIONAL([USE_TRACING_INSTRUMENTATION_LOG_DEBUG],
+ [test "x$enable_tracing_instrumentation_log_debug" = "xyes"])
+if test "x$enable_tracing_instrumentation_log_debug" = "xyes"; then
+ have_tracing=1
fi
+dnl Define that tracing is supported if any instrumentation is used.
+AM_COND_IF([USE_TRACING_INSTRUMENTATION_LOG_DEBUG],
+ AC_DEFINE([HAVE_TRACING], [1], [Compiled with tracing support]))
+AM_COND_IF([USE_TRACING_INSTRUMENTATION_USDT],
+ AC_DEFINE([HAVE_TRACING], [1], [Compiled with tracing support]))
+AM_COND_IF([USE_TRACING_INSTRUMENTATION_LTTNG],
+ AC_DEFINE([HAVE_TRACING], [1], [Compiled with tracing support]))
+AM_CONDITIONAL([USE_TRACING], [test "x$have_tracing" = x1 ])
+
+dnl Finally, define the trace libs.
+AC_SUBST([TOR_TRACE_LIBS])
+
+dnl -- End Tracing Options. --
+
dnl Enable Android only features.
AC_ARG_ENABLE(android,
AS_HELP_STRING(--enable-android, [build with Android features enabled]))
@@ -274,10 +348,6 @@ AM_CONDITIONAL([USE_ANDROID], [test "x$enable_android" = "xyes"])
if test "x$enable_android" = "xyes"; then
AC_DEFINE([USE_ANDROID], [1], [Compile with Android specific features enabled])
- dnl Check if the Android log library is available.
- AC_CHECK_HEADERS([android/log.h])
- AC_SEARCH_LIBS(__android_log_write, [log])
-
fi
dnl ---
@@ -287,6 +357,12 @@ dnl ---
dnl All our modules.
m4_define(MODULES, relay dirauth dircache)
+# Some modules are only disabled through another option. For those, we don't
+# want to print the help in the summary at the end of the configure. Any entry
+# in the following set will not print the "--disable-module-NAME" command in
+# the summary.
+m4_set_add_all([MODULES_WITH_NO_OPTIONS], [dircache])
+
dnl Relay module.
AC_ARG_ENABLE([module-relay],
AS_HELP_STRING([--disable-module-relay],
@@ -365,7 +441,11 @@ AM_CONDITIONAL(BUILD_MANPAGE, [test "x$enable_manpage" != "xno"])
AM_CONDITIONAL(BUILD_HTML_DOCS, [test "x$enable_html_manual" != "xno"])
AM_PROG_CC_C_O
-AC_PROG_CC_C99
+
+dnl Before autoconf 2.70, AC_PROG_CC_C99 is supposedly necessary for some
+dnl compilers if you wan't C99 support. Starting with 2.70, it is obsolete and
+dnl forbidden.
+m4_version_prereq([2.70], [:], [AC_PROG_CC_C99])
AC_CACHE_CHECK([for Python 3], [tor_cv_PYTHON],
[AC_PATH_PROGS_FEATURE_CHECK([PYTHON], [ \
@@ -378,6 +458,7 @@ AC_SUBST([PYTHON], [$tor_cv_PYTHON])
PYTHON="$tor_cv_PYTHON"
if test "x$PYTHON" = "x"; then
+ tor_incr_n_warnings
AC_MSG_WARN([Python 3 unavailable; some tests will not be run.])
fi
@@ -504,14 +585,14 @@ fi
AH_BOTTOM([
#ifdef _WIN32
-/* Defined to access windows functions and definitions for >=WinXP */
+/* Defined to access windows functions and definitions for >=WinVista */
# ifndef WINVER
-# define WINVER 0x0501
+# define WINVER 0x0600
# endif
-/* Defined to access _other_ windows functions and definitions for >=WinXP */
+/* Defined to access _other_ windows functions and definitions for >=WinVista */
# ifndef _WIN32_WINNT
-# define _WIN32_WINNT 0x0501
+# define _WIN32_WINNT 0x0600
# endif
/* Defined to avoid including some windows headers as part of Windows.h */
@@ -679,12 +760,10 @@ AC_CHECK_FUNCS(
getdelim \
getifaddrs \
getline \
- getpass \
getrlimit \
gettimeofday \
gmtime_r \
gnu_get_libc_version \
- htonll \
inet_aton \
ioctl \
issetugid \
@@ -793,6 +872,8 @@ fi
AM_CONDITIONAL(BUILD_READPASSPHRASE_C,
test "x$ac_cv_func_readpassphrase" = "xno" && test "$bwin32" = "false")
+AC_CHECK_FUNCS(glob)
+
AC_MSG_CHECKING([whether free(NULL) works])
AC_RUN_IFELSE([AC_LANG_PROGRAM([
#include <stdlib.h>
@@ -814,10 +895,13 @@ dnl Where do you live, libevent? And how do we call you?
if test "$bwin32" = "true"; then
TOR_LIB_WS32=-lws2_32
TOR_LIB_IPHLPAPI=-liphlpapi
+ TOR_LIB_SHLWAPI=-lshlwapi
# Some of the cargo-cults recommend -lwsock32 as well, but I don't
# think it's actually necessary.
TOR_LIB_GDI=-lgdi32
TOR_LIB_USERENV=-luserenv
+ TOR_LIB_BCRYPT=-lbcrypt
+ TOR_LIB_CRYPT32=-lcrypt32
else
TOR_LIB_WS32=
TOR_LIB_GDI=
@@ -826,6 +910,9 @@ fi
AC_SUBST(TOR_LIB_WS32)
AC_SUBST(TOR_LIB_GDI)
AC_SUBST(TOR_LIB_IPHLPAPI)
+AC_SUBST(TOR_LIB_BCRYPT)
+AC_SUBST(TOR_LIB_CRYPT32)
+AC_SUBST(TOR_LIB_SHLWAPI)
AC_SUBST(TOR_LIB_USERENV)
tor_libevent_pkg_redhat="libevent"
@@ -842,7 +929,7 @@ if test "$enable_static_libevent" = "yes"; then
fi
fi
-TOR_SEARCH_LIBRARY(libevent, $trylibeventdir, [-levent $STATIC_LIBEVENT_FLAGS $TOR_LIB_WS32], [
+TOR_SEARCH_LIBRARY(libevent, $trylibeventdir, [-levent $STATIC_LIBEVENT_FLAGS $TOR_LIB_IPHLPAPI $TOR_LIB_BCRYPT $TOR_LIB_WS32], [
#ifdef _WIN32
#include <winsock2.h>
#endif
@@ -973,7 +1060,7 @@ AC_ARG_WITH(ssl-dir,
])
AC_MSG_NOTICE([Now, we'll look for OpenSSL >= 1.0.1])
-TOR_SEARCH_LIBRARY(openssl, $tryssldir, [-lssl -lcrypto $TOR_LIB_GDI $TOR_LIB_WS32],
+TOR_SEARCH_LIBRARY(openssl, $tryssldir, [-lssl -lcrypto $TOR_LIB_GDI $TOR_LIB_WS32 $TOR_LIB_CRYPT32],
[#include <openssl/ssl.h>
char *getenv(const char *);],
[struct ssl_cipher_st;
@@ -988,20 +1075,18 @@ TOR_SEARCH_LIBRARY(openssl, $tryssldir, [-lssl -lcrypto $TOR_LIB_GDI $TOR_LIB_WS
[if (getenv("THIS_SHOULDNT_BE_SET_X201803")) SSL_CIPHER_get_id((void *)0);], [],
[/usr/local/opt/openssl /usr/local/openssl /usr/lib/openssl /usr/local/ssl /usr/lib/ssl /usr/local /opt/openssl])
-dnl XXXX check for OPENSSL_VERSION_NUMBER == SSLeay()
-
if test "$enable_static_openssl" = "yes"; then
if test "$tor_cv_library_openssl_dir" = "(system)"; then
AC_MSG_ERROR("You must specify an explicit --with-openssl-dir=x option when using --enable-static-openssl")
else
- TOR_OPENSSL_LIBS="$TOR_LIBDIR_openssl/libssl.a $TOR_LIBDIR_openssl/libcrypto.a"
+ TOR_OPENSSL_LIBS="$TOR_LIBDIR_openssl/libssl.a $TOR_LIBDIR_openssl/libcrypto.a $TOR_LIB_WS32 $TOR_LIB_CRYPT32 $TOR_LIB_BCRYPT"
fi
else
TOR_OPENSSL_LIBS="-lssl -lcrypto"
fi
AC_SUBST(TOR_OPENSSL_LIBS)
-dnl Now check for particular openssl functions.
+dnl Now validate openssl, and check for particular openssl functions.
save_LIBS="$LIBS"
save_LDFLAGS="$LDFLAGS"
save_CPPFLAGS="$CPPFLAGS"
@@ -1048,6 +1133,28 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
[ : ],
[ AC_MSG_ERROR([OpenSSL is built without full ECC support, including curves P256 and P224. You can specify a path to one with ECC support with --with-openssl-dir.]) ])
+dnl Let's see if we have a version mismatch between includes and libs.
+AC_MSG_CHECKING([for significant mismatch between openssl headers and libraries])
+ac_retval=foo
+AC_RUN_IFELSE([AC_LANG_SOURCE([AC_LANG_PROGRAM([[
+ #include <openssl/opensslv.h>
+ #include <openssl/crypto.h>
+]], [[
+ /* Include major, minor, and fix, but not patch or status. */
+ unsigned long mask = 0xfffff000;
+ unsigned long linking = OpenSSL_version_num() & mask;
+ unsigned long running = OPENSSL_VERSION_NUMBER & mask;
+ return !(linking==running);
+]])])], [openssl_ver_mismatch=no], [
+ # This is a kludge to figure out whether compilation failed, or whether
+ # running the program failed.
+ if test "$ac_retval" = "1"; then
+ openssl_ver_mismatch=inconclusive
+ else
+ openssl_ver_mismatch=yes
+ fi], [openssl_ver_mismatch=cross])
+AC_MSG_RESULT([$openssl_ver_mismatch])
+
AC_CHECK_MEMBERS([struct ssl_method_st.get_cipher_by_char], , ,
[#include <openssl/ssl.h>
])
@@ -1059,7 +1166,6 @@ dnl to them.
AC_CHECK_FUNCS([ \
ERR_load_KDF_strings \
EVP_PBE_scrypt \
- EVP_sha3_256 \
SSL_CIPHER_find \
SSL_CTX_set1_groups_list \
SSL_CTX_set_security_level \
@@ -1171,6 +1277,7 @@ else
have_lzma=no)
if test "x$have_lzma" = "xno" ; then
+ tor_incr_n_warnings
AC_MSG_WARN([Unable to find liblzma, $pkg_config_user_action, or set LZMA_CFLAGS and LZMA_LIBS.])
fi
fi
@@ -1203,6 +1310,7 @@ else
have_zstd=no)
if test "x$have_zstd" = "xno" ; then
+ tor_incr_n_warnings
AC_MSG_WARN([Unable to find libzstd, $pkg_config_user_action, or set ZSTD_CFLAGS and ZSTD_LIBS.])
fi
fi
@@ -1307,6 +1415,7 @@ fi
if test "$fragile_hardening" = "yes"; then
TOR_TRY_COMPILE_WITH_CFLAGS(-ftrapv, also_link, CFLAGS_FTRAPV="-ftrapv", true)
if test "$tor_cv_cflags__ftrapv" = "yes" && test "$tor_can_link__ftrapv" != "yes"; then
+ tor_incr_n_warnings
AC_MSG_WARN([The compiler supports -ftrapv, but for some reason I was not able to link with -ftrapv. Are you missing run-time support? Run-time hardening will not work as well as it should.])
fi
@@ -1407,7 +1516,7 @@ dnl These cflags add bunches of branches, and we haven't been able to
dnl persuade ourselves that they're suitable for code that needs to be
dnl constant time.
AC_SUBST(CFLAGS_BUGTRAP)
-dnl These cflags are variant ones sutable for code that needs to be
+dnl These cflags are variant ones suitable for code that needs to be
dnl constant-time.
AC_SUBST(CFLAGS_CONSTTIME)
@@ -1586,8 +1695,6 @@ AC_CHECK_HEADERS([errno.h \
mach/vm_inherit.h \
machine/limits.h \
malloc.h \
- malloc/malloc.h \
- malloc_np.h \
netdb.h \
netinet/in.h \
netinet/in6.h \
@@ -1608,14 +1715,14 @@ AC_CHECK_HEADERS([errno.h \
sys/statvfs.h \
sys/syscall.h \
sys/sysctl.h \
- sys/syslimits.h \
sys/time.h \
sys/types.h \
sys/un.h \
sys/utime.h \
sys/wait.h \
syslog.h \
- utime.h])
+ utime.h \
+ glob.h])
AC_CHECK_HEADERS(sys/param.h)
@@ -1849,6 +1956,7 @@ void try_atomic_init(struct x *xx)
if test "$tor_cv_stdatomic_works" = "yes"; then
AC_DEFINE(STDATOMIC_WORKS, 1, [Set to 1 if we can compile a simple stdatomic example.])
elif test "$ac_cv_header_stdatomic_h" = "yes"; then
+ tor_incr_n_warnings
AC_MSG_WARN([Your compiler provides the stdatomic.h header, but it doesn't seem to work. I'll pretend it isn't there. If you are using Clang on Debian, maybe this is because of https://bugs.debian.org/903709 ])
fi
@@ -2032,6 +2140,7 @@ AS_CASE([$malloc],
],
[openbsd], [
+ tor_incr_n_warnings
AC_MSG_WARN([The openbsd malloc port is deprecated in Tor 0.3.5 and will be removed in a future version.])
enable_openbsd_malloc=yes
],
@@ -2559,6 +2668,7 @@ TOR_TRY_COMPILE_WITH_CFLAGS([@warning_flags], [],
if test "$enable_coverage" = "yes" && test "$have_clang" = "no"; then
case "$host_os" in
darwin*)
+ tor_incr_n_warnings
AC_MSG_WARN([Tried to enable coverage on OSX without using the clang compiler. This might not work! If coverage fails, use CC=clang when configuring with --enable-coverage.])
esac
fi
@@ -2570,7 +2680,6 @@ AC_CONFIG_FILES([
Makefile
config.rust
contrib/operator-tools/tor.logrotate
- contrib/dist/tor.service
src/config/torrc.sample
src/config/torrc.minimal
src/rust/.cargo/config
@@ -2579,7 +2688,7 @@ AC_CONFIG_FILES([
])
if test "x$asciidoc" = "xtrue" && test "$ASCIIDOC" = "none"; then
- regular_mans="doc/tor doc/tor-gencert doc/tor-resolve doc/torify"
+ regular_mans="doc/man/tor doc/man/tor-gencert doc/man/tor-resolve doc/man/torify"
for file in $regular_mans ; do
if ! [[ -f "$srcdir/$file.1.in" ]] || ! [[ -f "$srcdir/$file.html.in" ]] ; then
echo "==================================";
@@ -2597,6 +2706,7 @@ if test "x$asciidoc" = "xtrue" && test "$ASCIIDOC" = "none"; then
fi
if test "$fragile_hardening" = "yes"; then
+ tor_incr_n_warnings
AC_MSG_WARN([
============
@@ -2606,13 +2716,27 @@ other kinds of attacks easier. A Tor instance build with this option will be
somewhat less vulnerable to remote code execution, arithmetic overflow, or
out-of-bounds read/writes... but at the cost of becoming more vulnerable to
denial of service attacks. For more information, see
-https://trac.torproject.org/projects/tor/wiki/doc/TorFragileHardening
+https://gitlab.torproject.org/tpo/core/team/-/wikis/TorFragileHardening
============
])
fi
AC_OUTPUT
+if test "$openssl_ver_mismatch" = "yes"; then
+ tor_incr_n_warnings
+ AC_MSG_WARN([
+============
+Warning! The version OpenSSL headers we get from compiling with
+ "${TOR_CPPFLAGS_OPENSSL:-(no extra options)}"
+do not match version of the OpenSSL library we get when linking with
+ "$TOR_LDFLAGS_OPENSSL $TOR_OPENSSL_LIBS".
+This might cause compilation to fail. Try using --with-openssl-dir to specify
+the exact OpenSSL path you want.
+============
+])
+fi
+
#
# Mini-report on what will be built.
#
@@ -2706,7 +2830,9 @@ 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)
+ m4_set_contains([MODULES_WITH_NO_OPTIONS], mname,
+ PPRINT_PROP_BOOL([mname], $value),
+ PPRINT_PROP_BOOL([mname (--disable-module-mname)], $value))
]
)
@@ -2741,6 +2867,18 @@ test "x$enable_oss_fuzz" = "xyes" && value=1 || value=0
PPRINT_PROP_BOOL([OSS-Fuzz support (--enable-oss-fuzz)], $value)
AS_ECHO
+PPRINT_SUBTITLE([Tracing (--enable-tracing-instrumentation-<type>)])
+
+test "x$enable_tracing_instrumentation_log_debug" = "xyes" && value=1 || value=0
+PPRINT_PROP_BOOL([Tracepoints to log_debug() (log-debug)], $value)
+
+test "x$enable_tracing_instrumentation_usdt" = "xyes" && value=1 || value=0
+PPRINT_PROP_BOOL([USDT Instrumentation (usdt)], $value)
+
+test "x$enable_tracing_instrumentation_lttng" = "xyes" && value=1 || value=0
+PPRINT_PROP_BOOL([LTTng Instrumentation (lttng)], $value)
+
+AS_ECHO
PPRINT_SUBTITLE([Install Directories])
report_mandir="`eval eval echo $mandir`"
@@ -2750,3 +2888,10 @@ PPRINT_PROP_STRING([Man Pages], [$report_mandir])
AS_ECHO
AS_ECHO(["Configure Line: ./configure $configure_flags"])
+
+if test "$tor_ac_n_warnings" != "0"; then
+ AS_ECHO
+ PPRINT_WARN([
+Encountered $tor_ac_n_warnings warning(s). See messages above for more info.
+ ])
+fi
diff --git a/contrib/README b/contrib/README
index a56065f97d..3edb0fafae 100644
--- a/contrib/README
+++ b/contrib/README
@@ -32,8 +32,6 @@ dist/ -- Scripts and files for use when packaging Tor
torctl and tor.sh are init scripts for use with SysV-style init
tools. Everybody likes to write init scripts differently, it seems.
-tor.service is a sample service file for use with systemd.
-
operator-tools/ -- Tools for Tor relay operators
------------------------------------------------
diff --git a/contrib/dist/tor.service.in b/contrib/dist/tor.service.in
deleted file mode 100644
index e857a8664e..0000000000
--- a/contrib/dist/tor.service.in
+++ /dev/null
@@ -1,35 +0,0 @@
-# tor.service -- this systemd configuration file for Tor sets up a
-# relatively conservative, hardened Tor service. You may need to
-# edit it if you are making changes to your Tor configuration that it
-# does not allow. Package maintainers: this should be a starting point
-# for your tor.service; it is not the last point.
-
-[Unit]
-Description=Anonymizing overlay network for TCP
-After=syslog.target network.target nss-lookup.target
-
-[Service]
-Type=notify
-NotifyAccess=all
-ExecStartPre=@BINDIR@/tor -f @CONFDIR@/torrc --verify-config
-ExecStart=@BINDIR@/tor -f @CONFDIR@/torrc
-ExecReload=/bin/kill -HUP ${MAINPID}
-KillSignal=SIGINT
-TimeoutSec=60
-Restart=on-failure
-WatchdogSec=1m
-LimitNOFILE=32768
-
-# Hardening
-PrivateTmp=yes
-PrivateDevices=yes
-ProtectHome=yes
-ProtectSystem=full
-ReadOnlyDirectories=/
-ReadWriteDirectories=-@LOCALSTATEDIR@/lib/tor
-ReadWriteDirectories=-@LOCALSTATEDIR@/log/tor
-NoNewPrivileges=yes
-CapabilityBoundingSet=CAP_SETUID CAP_SETGID CAP_NET_BIND_SERVICE
-
-[Install]
-WantedBy=multi-user.target
diff --git a/contrib/include.am b/contrib/include.am
index 60783dc439..7a85093b68 100644
--- a/contrib/include.am
+++ b/contrib/include.am
@@ -2,7 +2,6 @@
EXTRA_DIST+= \
contrib/README \
contrib/client-tools/torify \
- contrib/dist/tor.service.in \
contrib/operator-tools/tor-exit-notice.html \
contrib/or-tools/exitlist \
contrib/win32build/tor-mingw.nsi.in \
diff --git a/contrib/or-tools/exitlist b/contrib/or-tools/exitlist
index 3fd26b5166..709e9a198c 100755
--- a/contrib/or-tools/exitlist
+++ b/contrib/or-tools/exitlist
@@ -6,7 +6,7 @@
"""
exitlist -- Given a Tor directory on stdin, lists the Tor servers
- that accept connections to given addreses.
+ that accept connections to given addresses.
example usage:
diff --git a/contrib/win32build/tor-mingw.nsi.in b/contrib/win32build/tor-mingw.nsi.in
index 38046e7c5d..580f189525 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.4.8-dev"
+!define VERSION "0.4.5.8"
!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
index a4e65697b8..95ffbae4dd 100644
--- a/doc/HACKING/CircuitPaddingDevelopment.md
+++ b/doc/HACKING/CircuitPaddingDevelopment.md
@@ -150,13 +150,13 @@ 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),
+transports](https://gitlab.torproject.org/tpo/anti-censorship/team/-/wikis/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
+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
@@ -178,7 +178,7 @@ 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.
+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
@@ -186,7 +186,7 @@ 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.
+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
@@ -1024,11 +1024,11 @@ 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),
+researchers may find useful is labeled in our bugtracker with
+[Padding Research](https://gitlab.torproject.org/tpo/core/tor/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=Padding%20Research),
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).
+areas are labeled with
+[Padding Research Requires](https://gitlab.torproject.org/tpo/core/tor/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=Padding%20Research%20Requires).
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
diff --git a/doc/HACKING/CircuitPaddingQuickStart.md b/doc/HACKING/CircuitPaddingQuickStart.md
index 2780b5c6ea..25bf05048c 100644
--- a/doc/HACKING/CircuitPaddingQuickStart.md
+++ b/doc/HACKING/CircuitPaddingQuickStart.md
@@ -7,7 +7,7 @@ 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.
+useful pointers along the way, not create a useful machine.
The quick and dirty plan is to:
1. clone and compile tor
@@ -18,20 +18,20 @@ The quick and dirty plan is to:
## Clone and compile tor
-```bash
-git clone https://git.torproject.org/tor.git
-cd tor
-git checkout tor-0.4.1.5
+```console
+$ 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
+```console
+$ 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
@@ -73,7 +73,7 @@ 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.
+by looking at the circuit display.
## Add a bare-bones APE padding machine
@@ -89,10 +89,10 @@ might be broken in the future, just search for the headings):
[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.
+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`.
+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`:
@@ -107,8 +107,8 @@ The definitions go into `circuitpadding_machines.c`:
```c
/**************** Adaptive Padding Early (APE) machine ****************/
-/**
- * Create a relay-side padding machine based on the APE design.
+/**
+ * Create a relay-side padding machine based on the APE design.
*/
void
circpad_machine_relay_wf_ape(smartlist_t *machines_sl)
@@ -137,14 +137,14 @@ circpad_machine_relay_wf_ape(smartlist_t *machines_sl)
// 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.
+/**
+ * Create a client-side padding machine based on the APE design.
*/
void
circpad_machine_client_wf_ape(smartlist_t *machines_sl)
@@ -186,18 +186,18 @@ 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);
+/* 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.
+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.
+[circ]info notice stdout` to `torrc` of TB.
Running TB to visit example.com we first find in the log:
@@ -224,13 +224,13 @@ Aug 30 18:36:55.000 [info] circpad_handle_padding_negotiated(): Middle node did
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.
+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.
+machine is running at the middle as well.
## Implementing the APE state machine
@@ -239,14 +239,14 @@ 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.
+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 .
+- `tor-0.4.1.5` did not support two machines on the same circuit, the following
+ fix had to be made: https://bugs.torproject.org/tpo/core/tor/31111 .
The good news is that everything else seems to work after the small change in
- the fix.
+ 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
diff --git a/doc/HACKING/CodeStructure.md b/doc/HACKING/CodeStructure.md
deleted file mode 100644
index d387018f9b..0000000000
--- a/doc/HACKING/CodeStructure.md
+++ /dev/null
@@ -1,123 +0,0 @@
-# Code Structure
-
-TODO: revise this to talk about how things are, rather than how things
-have changed.
-
-For quite a while now, the program *tor* has been built from source
-code in just two directories: **src/common** and **src/or**.
-
-This has become more-or-less untenable, for a few reasons -- most
-notably of which is that it has led our code to become more
-spaghetti-ish than I can endorse with a clean conscience.
-
-So to fix that, we've gone and done a huge code movement in our git
-master branch, which will land in a release once Tor `0.3.5.1-alpha` is
-out.
-
-Here's what we did:
-
- * **src/common** has been turned into a set of static libraries. These
-all live in the **src/lib/*** directories. The dependencies between
-these libraries should have no cycles. The libraries are:
-
- - **arch** -- Headers to handle architectural differences
- - **cc** -- headers to handle differences among compilers
- - **compress** -- wraps zlib, zstd, lzma
- - **container** -- high-level container types
- - **crypt_ops** -- Cryptographic operations. Planning to split this into
-a higher and lower level library
- - **ctime** -- Operations that need to run in constant-time. (Properly,
-data-invariant time)
- - **defs** -- miscelaneous definitions needed throughout Tor.
- - **encoding** -- transforming one data type into another, and various
-data types into strings.
- - **err** -- lowest-level error handling, in cases where we can't use
-the logs because something that the logging system needs has broken.
- - **evloop** -- Generic event-loop handling logic
- - **fdio** -- Low-level IO wrapper functions for file descriptors.
- - **fs** -- Operations on the filesystem
- - **intmath** -- low-level integer math and misc bit-twiddling hacks
- - **lock** -- low-level locking code
- - **log** -- Tor's logging module. This library sits roughly halfway up
-the library dependency diagram, since everything it depends on has to
-be carefully crafted to *not* log.
- - **malloc** -- Low-level wrappers for the platform memory allocation functions.
- - **math** -- Higher-level mathematical functions, and floating-point math
- - **memarea** -- An arena allocator
- - **meminfo** -- Functions for querying the current process's memory
-status and resources
- - **net** -- Networking compatibility and convenience code
- - **osinfo** -- Querying information about the operating system
- - **process** -- Launching and querying the status of other processes
- - **sandbox** -- Backend for the linux seccomp2 sandbox
- - **smartlist_core** -- The lowest-level of the smartlist_t data type.
-Separated from the rest of the containers library because the logging
-subsystem depends on it.
- - **string** -- Compatibility and convenience functions for manipulating
-C strings.
- - **term** -- Terminal-related functions (currently limited to a getpass
-function).
- - **testsupport** -- Macros for mocking, unit tests, etc.
- - **thread** -- Higher-level thread compatibility code
- - **time** -- Higher-level time management code, including format
-conversions and monotonic time
- - **tls** -- Our wrapper around our TLS library
- - **trace** -- Formerly src/trace -- a generic event tracing API
- - **wallclock** -- Low-level time code, used by the log module.
-
- * To ensure that the dependency graph in **src/common** remains under
-control, there is a tool that you can run called `make
-check-includes`. It verifies that each module in Tor only includes
-the headers that it is permitted to include, using a per-directory
-*.may_include* file.
-
- * The **src/or/or.h** header has been split into numerous smaller
-headers. Notably, many important structures are now declared in a
-header called *foo_st.h*, where "foo" is the name of the structure.
-
- * The **src/or** directory, which had most of Tor's code, had been split
-up into several directories. This is still a work in progress: This
-code has not itself been refactored, and its dependency graph is still
-a tangled web. I hope we'll be working on that over the coming
-releases, but it will take a while to do.
-
- - The new top-level source directories are:
- - **src/core** -- Code necessary to actually perform or use onion routing.
- - **src/feature** -- Code used only by some onion routing
-configurations, or only for a special purpose.
- - **src/app** -- Top-level code to run, invoke, and configure the
-lower-level code
-
- - The new second-level source directories are:
- - **src/core/crypto** -- High-level cryptographic protocols used in Tor
- - **src/core/mainloop** -- Tor's event loop, connection-handling, and
-traffic-routing code.
- - **src/core/or** -- Parts related to handling onion routing itself
- - **src/core/proto** -- support for encoding and decoding different
-wire protocols
- - **src/feature/api** -- Support for making Tor embeddable
- - **src/feature/client** -- Functionality which only Tor clients need
- - **src/feature/control** -- Controller implementation
- - **src/feature/dirauth** -- Directory authority
- - **src/feature/dircache** -- Directory cache
- - **src/feature/dirclient** -- Directory client
- - **src/feature/dircommon** -- Shared code between the other directory modules
- - **src/feature/hibernate** -- Hibernating when Tor is out of bandwidth
-or shutting down
- - **src/feature/hs** -- v3 onion service implementation
- - **src/feature/hs_common** -- shared code between both onion service
-implementations
- - **src/feature/nodelist** -- storing and accessing the list of relays on
-the network.
- - **src/feature/relay** -- code that only relay servers and exit servers need.
- - **src/feature/rend** -- v2 onion service implementation
- - **src/feature/stats** -- statistics and history
- - **src/app/config** -- configuration and state for Tor
- - **src/app/main** -- Top-level functions to invoke the rest or Tor.
-
- * The `tor` executable is now built in **src/app/tor** rather than **src/or/tor**.
-
- * There are more static libraries than before that you need to build
-into your application if you want to embed Tor. Rather than
-maintaining this list yourself, I recommend that you run `make
-show-libs` to have Tor emit a list of what you need to link.
diff --git a/doc/HACKING/CodingStandards.md b/doc/HACKING/CodingStandards.md
index 150acf1852..cd3417d0b5 100644
--- a/doc/HACKING/CodingStandards.md
+++ b/doc/HACKING/CodingStandards.md
@@ -118,27 +118,36 @@ instance of the feature (--reverse).
For example, for #30224, we wanted to know when the bridge-distribution-request
feature was introduced into Tor:
- $ git log -S bridge-distribution-request --reverse
- commit ebab521525
- Author: Roger Dingledine <arma@torproject.org>
- Date: Sun Nov 13 02:39:16 2016 -0500
- Add new BridgeDistribution config option
+```console
+$ git log -S bridge-distribution-request --reverse commit ebab521525
+Author: Roger Dingledine <arma@torproject.org>
+Date: Sun Nov 13 02:39:16 2016 -0500
- $ git describe --contains ebab521525
- tor-0.3.2.3-alpha~15^2~4
+ Add new BridgeDistribution config option
+
+$ git describe --contains ebab521525
+tor-0.3.2.3-alpha~15^2~4
+```
If you need to know all the Tor versions that contain a commit, use:
- $ git tag --contains 9f2efd02a1 | sort -V
- tor-0.2.5.16
- tor-0.2.8.17
- tor-0.2.9.14
- tor-0.2.9.15
- ...
- tor-0.3.0.13
- tor-0.3.1.9
- tor-0.3.1.10
- ...
+
+```console
+$ git tag --contains 9f2efd02a1 | sort -V
+tor-0.2.5.16
+tor-0.2.8.17
+tor-0.2.9.14
+tor-0.2.9.15
+...
+tor-0.3.0.13
+tor-0.3.1.9
+tor-0.3.1.10
+...
+```
+
+If a bug was introduced before the oldest currently supported release series
+of Tor, and it's hard to track down where it was introduced, you may say
+"bugfix on all supported versions of Tor."
If at all possible, try to create the changes file in the same commit where
you are making the change. Please give it a distinctive name that no other
@@ -180,6 +189,14 @@ What needs a changes file?
What does not need a changes file?
* Bugfixes for code that hasn't shipped in any released version of Tor
+ * Any change to a file that is not distributed in the tarball. This
+ includes:
+ * Any change to our CI configuration that does not affect the distributed
+ source.
+ * Any change to developer-only tools, unless those tools are distributed
+ in the tarball.
+ * Non-functional code movement.
+ * Identifier re-namings, comment edits, spelling fixes, and so on.
Why use changes files instead of Git commit messages?
@@ -438,8 +455,10 @@ use `tor_assert_nonfatal()` in place of `tor_assert()`. If you'd like to
write a conditional that incorporates a nonfatal assertion, use the `BUG()`
macro, as in:
- if (BUG(ptr == NULL))
- return -1;
+```c
+if (BUG(ptr == NULL))
+ return -1;
+```
## Allocator conventions
@@ -451,33 +470,39 @@ Also, a type named `abc_t` should be freed by a function named `abc_free_()`.
Don't call this `abc_free_()` function directly -- instead, wrap it in a
macro called `abc_free()`, using the `FREE_AND_NULL` macro:
- void abc_free_(abc_t *obj);
- #define abc_free(obj) FREE_AND_NULL(abc_t, abc_free_, (obj))
+```c
+void abc_free_(abc_t *obj);
+#define abc_free(obj) FREE_AND_NULL(abc_t, abc_free_, (obj))
+```
This macro will free the underlying `abc_t` object, and will also set
the object pointer to NULL.
You should define all `abc_free_()` functions to accept NULL inputs:
- void
- abc_free_(abc_t *obj)
- {
- if (!obj)
- return;
- tor_free(obj->name);
- thing_free(obj->thing);
- tor_free(obj);
- }
+```c
+void
+abc_free_(abc_t *obj)
+{
+ if (!obj)
+ return;
+ tor_free(obj->name);
+ thing_free(obj->thing);
+ tor_free(obj);
+}
+```
If you need a free function that takes a `void *` argument (for example,
to use it as a function callback), define it with a name like
`abc_free_void()`:
- static void
- abc_free_void_(void *obj)
- {
- abc_free_(obj);
- }
+```c
+static void
+abc_free_void_(void *obj)
+{
+ 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.
@@ -488,24 +513,28 @@ Say what functions do as a series of one or more imperative sentences, as
though you were telling somebody how to be the function. In other words, DO
NOT say:
- /** The strtol function parses a number.
- *
- * nptr -- the string to parse. It can include whitespace.
- * endptr -- a string pointer to hold the first thing that is not part
- * of the number, if present.
- * base -- the numeric base.
- * returns: the resulting number.
- */
- long strtol(const char *nptr, char **nptr, int base);
+```c
+/** The strtol function parses a number.
+ *
+ * nptr -- the string to parse. It can include whitespace.
+ * endptr -- a string pointer to hold the first thing that is not part
+ * of the number, if present.
+ * base -- the numeric base.
+ * returns: the resulting number.
+ */
+long strtol(const char *nptr, char **nptr, int base);
+```
Instead, please DO say:
- /** Parse a number in radix <b>base</b> from the string <b>nptr</b>,
- * and return the result. Skip all leading whitespace. If
- * <b>endptr</b> is not NULL, set *<b>endptr</b> to the first character
- * after the number parsed.
- **/
- long strtol(const char *nptr, char **nptr, int base);
+```c
+/** Parse a number in radix <b>base</b> from the string <b>nptr</b>,
+ * and return the result. Skip all leading whitespace. If
+ * <b>endptr</b> is not NULL, set *<b>endptr</b> to the first character
+ * after the number parsed.
+ **/
+long strtol(const char *nptr, char **nptr, int base);
+```
Doxygen comments are the contract in our abstraction-by-contract world: if
the functions that call your function rely on it doing something, then your
diff --git a/doc/HACKING/CodingStandardsRust.md b/doc/HACKING/CodingStandardsRust.md
index 36a0dcda2a..c821465173 100644
--- a/doc/HACKING/CodingStandardsRust.md
+++ b/doc/HACKING/CodingStandardsRust.md
@@ -22,20 +22,26 @@ For example, in a hypothetical `tor_addition` Rust module:
In `src/rust/tor_addition/addition.rs`:
- pub fn get_sum(a: i32, b: i32) -> i32 {
- a + b
- }
+```rust
+pub fn get_sum(a: i32, b: i32) -> i32 {
+ a + b
+}
+```
In `src/rust/tor_addition/lib.rs`:
- pub use addition::*;
+```rust
+pub use addition::*;
+```
In `src/rust/tor_addition/ffi.rs`:
- #[no_mangle]
- pub extern "C" fn tor_get_sum(a: c_int, b: c_int) -> c_int {
- get_sum(a, b)
- }
+```rust
+#[no_mangle]
+pub extern "C" fn tor_get_sum(a: c_int, b: c_int) -> c_int {
+ get_sum(a, b)
+}
+```
If your Rust code must call out to parts of Tor's C code, you must
declare the functions you are calling in the `external` crate, located
@@ -129,16 +135,18 @@ crate. Unittests SHOULD go into their own module inside the module
they are testing, e.g. in `src/rust/tor_addition/addition.rs` you
should put:
- #[cfg(test)]
- mod test {
- use super::*;
+```rust
+#[cfg(test)]
+mod test {
+ use super::*;
- #[test]
- fn addition_with_zero() {
- let sum: i32 = get_sum(5i32, 0i32);
- assert_eq!(sum, 5);
- }
+#[test]
+ fn addition_with_zero() {
+ let sum: i32 = get_sum(5i32, 0i32);
+ assert_eq!(sum, 5);
}
+}
+```
## Benchmarking
@@ -151,13 +159,17 @@ benchmarks in the following manner.
If you wish to benchmark some of your Rust code, you MUST put the
following in the `[features]` section of your crate's `Cargo.toml`:
- [features]
- bench = []
+```toml
+[features]
+bench = []
+```
Next, in your crate's `lib.rs` you MUST put:
- #[cfg(all(test, feature = "bench"))]
- extern crate test;
+```rust
+#[cfg(all(test, feature = "bench"))]
+extern crate test;
+```
This ensures that the external crate `test`, which contains utilities
for basic benchmarks, is only used when running benchmarks via `cargo
@@ -166,16 +178,18 @@ bench --features bench`.
Finally, to write your benchmark code, in
`src/rust/tor_addition/addition.rs` you SHOULD put:
- #[cfg(all(test, features = "bench"))]
- mod bench {
- use test::Bencher;
- use super::*;
+```rust
+#[cfg(all(test, features = "bench"))]
+mod bench {
+ use test::Bencher;
+ use super::*;
- #[bench]
- fn addition_small_integers(b: &mut Bencher) {
- b.iter(| | get_sum(5i32, 0i32));
- }
+#[bench]
+ fn addition_small_integers(b: &mut Bencher) {
+ b.iter(| | get_sum(5i32, 0i32));
}
+}
+```
## Fuzzing
@@ -247,39 +261,47 @@ Here are some additional bits of advice and rules:
potential error with the eel operator, `?` or another non panicking way.
For example, consider a function which parses a string into an integer:
- fn parse_port_number(config_string: &str) -> u16 {
- u16::from_str_radix(config_string, 10).unwrap()
- }
+ ```rust
+ fn parse_port_number(config_string: &str) -> u16 {
+ u16::from_str_radix(config_string, 10).unwrap()
+ }
+ ```
There are numerous ways this can fail, and the `unwrap()` will cause the
whole program to byte the dust! Instead, either you SHOULD use `ok()`
(or another equivalent function which will return an `Option` or a `Result`)
and change the return type to be compatible:
- fn parse_port_number(config_string: &str) -> Option<u16> {
- u16::from_str_radix(config_string, 10).ok()
- }
+ ```rust
+ fn parse_port_number(config_string: &str) -> Option<u16> {
+ u16::from_str_radix(config_string, 10).ok()
+ }
+ ```
or you SHOULD use `or()` (or another similar method):
- fn parse_port_number(config_string: &str) -> Option<u16> {
- u16::from_str_radix(config_string, 10).or(Err("Couldn't parse port into a u16")
- }
+ ```rust
+ fn parse_port_number(config_string: &str) -> Option<u16> {
+ u16::from_str_radix(config_string, 10).or(Err("Couldn't parse port into a u16")
+ }
+ ```
Using methods like `or()` can be particularly handy when you must do
something afterwards with the data, for example, if we wanted to guarantee
that the port is high. Combining these methods with the eel operator (`?`)
makes this even easier:
- fn parse_port_number(config_string: &str) -> Result<u16, Err> {
- let port = u16::from_str_radix(config_string, 10).or(Err("Couldn't parse port into a u16"))?;
+ ```rust
+ fn parse_port_number(config_string: &str) -> Result<u16, Err> {
+ let port = u16::from_str_radix(config_string, 10).or(Err("Couldn't parse port into a u16"))?;
- if port > 1024 {
- return Ok(port);
- } else {
- return Err("Low ports not allowed");
- }
+ if port > 1024 {
+ return Ok(port);
+ } else {
+ return Err("Low ports not allowed");
}
+ }
+ ```
2. `unsafe`
@@ -292,25 +314,29 @@ Here are some additional bits of advice and rules:
When creating an FFI in Rust for C code to call, it is NOT REQUIRED
to declare the entire function `unsafe`. For example, rather than doing:
- #[no_mangle]
- pub unsafe extern "C" fn increment_and_combine_numbers(mut numbers: [u8; 4]) -> u32 {
- for number in &mut numbers {
- *number += 1;
- }
- std::mem::transmute::<[u8; 4], u32>(numbers)
+ ```rust
+ #[no_mangle]
+ pub unsafe extern "C" fn increment_and_combine_numbers(mut numbers: [u8; 4]) -> u32 {
+ for number in &mut numbers {
+ *number += 1;
}
+ std::mem::transmute::<[u8; 4], u32>(numbers)
+ }
+ ```
You SHOULD instead do:
- #[no_mangle]
- pub extern "C" fn increment_and_combine_numbers(mut numbers: [u8; 4]) -> u32 {
- for index in 0..numbers.len() {
- numbers[index] += 1;
- }
- unsafe {
- std::mem::transmute::<[u8; 4], u32>(numbers)
- }
+ ```rust
+ #[no_mangle]
+ pub extern "C" fn increment_and_combine_numbers(mut numbers: [u8; 4]) -> u32 {
+ for index in 0..numbers.len() {
+ numbers[index] += 1;
}
+ unsafe {
+ std::mem::transmute::<[u8; 4], u32>(numbers)
+ }
+ }
+ ```
3. Pass only C-compatible primitive types and bytes over the boundary
@@ -385,45 +411,51 @@ Here are some additional bits of advice and rules:
rather than using an untyped mapping between strings and integers
like so:
- use std::collections::HashMap;
+ ```rust
+ use std::collections::HashMap;
- pub fn get_elements_with_over_9000_points(map: &HashMap<String, usize>) -> Vec<String> {
- ...
- }
+ pub fn get_elements_with_over_9000_points(map: &HashMap<String, usize>) -> Vec<String> {
+ ...
+ }
+ ```
It would be safer to define a new type, such that some other usage
of `HashMap<String, usize>` cannot be confused for this type:
- pub struct DragonBallZPowers(pub HashMap<String, usize>);
+ ```rust
+ pub struct DragonBallZPowers(pub HashMap<String, usize>);
- impl DragonBallZPowers {
- pub fn over_nine_thousand<'a>(&'a self) -> Vec<&'a String> {
- let mut powerful_enough: Vec<&'a String> = Vec::with_capacity(5);
+ impl DragonBallZPowers {
+ pub fn over_nine_thousand<'a>(&'a self) -> Vec<&'a String> {
+ let mut powerful_enough: Vec<&'a String> = Vec::with_capacity(5);
- for (character, power) in &self.0 {
- if *power > 9000 {
- powerful_enough.push(character);
- }
- }
- powerful_enough
- }
- }
+ for (character, power) in &self.0 {
+ if *power > 9000 {
+ powerful_enough.push(character);
+ }
+ }
+ powerful_enough
+ }
+ }
+ ```
Note the following code, which uses Rust's type aliasing, is valid
but it does NOT meet the desired type safety goals:
- pub type Power = usize;
+ ```rust
+ pub type Power = usize;
- pub fn over_nine_thousand(power: &Power) -> bool {
- if *power > 9000 {
- return true;
- }
- false
+ pub fn over_nine_thousand(power: &Power) -> bool {
+ if *power > 9000 {
+ return true;
}
+ false
+ }
- // We can still do the following:
- let his_power: usize = 9001;
- over_nine_thousand(&his_power);
+ // We can still do the following:
+ let his_power: usize = 9001;
+ over_nine_thousand(&his_power);
+ ```
7. Unsafe mucking around with lifetimes
@@ -431,15 +463,17 @@ Here are some additional bits of advice and rules:
family of types, individual lifetimes can be treated as types. For example,
one can arbitrarily extend and shorten lifetime using `std::mem::transmute`:
- struct R<'a>(&'a i32);
+ ```rust
+ struct R<'a>(&'a i32);
- unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> {
- std::mem::transmute::<R<'b>, R<'static>>(r)
- }
+ unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> {
+ std::mem::transmute::<R<'b>, R<'static>>(r)
+ }
- unsafe fn shorten_invariant_lifetime<'b, 'c>(r: &'b mut R<'static>) -> &'b mut R<'c> {
- std::mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>(r)
- }
+ unsafe fn shorten_invariant_lifetime<'b, 'c>(r: &'b mut R<'static>) -> &'b mut R<'c> {
+ std::mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>(r)
+ }
+ ```
Calling `extend_lifetime()` would cause an `R` passed into it to live forever
for the life of the program (the `'static` lifetime). Similarly,
@@ -460,12 +494,14 @@ Here are some additional bits of advice and rules:
For example, `std::mem::transmute` can be abused in ways where casting with
`as` would be both simpler and safer:
- // Don't do this
- let ptr = &0;
- let ptr_num_transmute = unsafe { std::mem::transmute::<&i32, usize>(ptr)};
+ ```rust
+ // Don't do this
+ let ptr = &0;
+ let ptr_num_transmute = unsafe { std::mem::transmute::<&i32, usize>(ptr)};
- // Use an `as` cast instead
- let ptr_num_cast = ptr as *const i32 as usize;
+ // Use an `as` cast instead
+ let ptr_num_cast = ptr as *const i32 as usize;
+ ```
In fact, using `std::mem::transmute` for *any* reason is a code smell and as
such SHOULD be avoided.
@@ -475,8 +511,10 @@ Here are some additional bits of advice and rules:
This is generally fine to do, but it has some behaviours which you should be
aware of. Casting down chops off the high bits, e.g.:
- let x: u32 = 4294967295;
- println!("{}", x as u16); // prints 65535
+ ```rust
+ let x: u32 = 4294967295;
+ println!("{}", x as u16); // prints 65535
+ ```
Some cases which you MUST NOT do include:
@@ -487,24 +525,28 @@ Here are some additional bits of advice and rules:
* Casting between integers and floats when the thing being cast
cannot fit into the type it is being casted into, e.g.:
- println!("{}", 42949.0f32 as u8); // prints 197 in debug mode and 0 in release
- println!("{}", 1.04E+17 as u8); // prints 0 in both modes
- println!("{}", (0.0/0.0) as i64); // prints whatever the heck LLVM wants
+ ```rust
+ println!("{}", 42949.0f32 as u8); // prints 197 in debug mode and 0 in release
+ println!("{}", 1.04E+17 as u8); // prints 0 in both modes
+ println!("{}", (0.0/0.0) as i64); // prints whatever the heck LLVM wants
+ ```
Because this behaviour is undefined, it can even produce segfaults in
safe Rust code. For example, the following program built in release
mode segfaults:
- #[inline(never)]
- pub fn trigger_ub(sl: &[u8; 666]) -> &[u8] {
- // Note that the float is out of the range of `usize`, invoking UB when casting.
- let idx = 1e99999f64 as usize;
- &sl[idx..] // The bound check is elided due to `idx` being of an undefined value.
- }
-
- fn main() {
- println!("{}", trigger_ub(&[1; 666])[999999]); // ~ out of bound
- }
+ ```rust
+ #[inline(never)]
+ pub fn trigger_ub(sl: &[u8; 666]) -> &[u8] {
+ // Note that the float is out of the range of `usize`, invoking UB when casting.
+ let idx = 1e99999f64 as usize;
+ &sl[idx..] // The bound check is elided due to `idx` being of an undefined value.
+ }
+
+ fn main() {
+ println!("{}", trigger_ub(&[1; 666])[999999]); // ~ out of bound
+ }
+ ```
And in debug mode panics with:
diff --git a/doc/HACKING/Fuzzing.md b/doc/HACKING/Fuzzing.md
index 487716bb6d..1a9185aebf 100644
--- a/doc/HACKING/Fuzzing.md
+++ b/doc/HACKING/Fuzzing.md
@@ -6,7 +6,10 @@ Check out fuzzing-corpora, and set TOR_FUZZ_CORPORA to point to the place
where you checked it out.
To run the fuzzing test cases in a deterministic fashion, use:
- make test-fuzz-corpora
+
+```console
+$ make test-fuzz-corpora
+```
This won't actually fuzz Tor! It will just run all the fuzz binaries
on our existing set of testcases for the fuzzer.
@@ -58,11 +61,13 @@ machine you care about, anyway.
To Build:
Get AFL from http://lcamtuf.coredump.cx/afl/ and unpack it
- cd afl
- make
- cd ../tor
- PATH=$PATH:../afl/ CC="../afl/afl-gcc" ./configure --enable-expensive-hardening
- AFL_HARDEN=1 make clean fuzzers
+ ```console
+ $ cd afl
+ $ make
+ $ cd ../tor
+ $ PATH=$PATH:../afl/ CC="../afl/afl-gcc" ./configure --enable-expensive-hardening
+ $ AFL_HARDEN=1 make clean fuzzers
+ ```
To Find The ASAN Memory Limit: (64-bit only)
@@ -75,10 +80,12 @@ Read afl/docs/notes_for_asan.txt for more details.
Download recidivm from https://jwilk.net/software/recidivm
Download the signature
Check the signature
- tar xvzf recidivm*.tar.gz
- cd recidivm*
- make
- /path/to/recidivm -v src/test/fuzz/fuzz-http
+ ```console
+ $ tar xvzf recidivm*.tar.gz
+ $ cd recidivm*
+ $ make
+ $ /path/to/recidivm -v src/test/fuzz/fuzz-http
+ ```
Use the final "ok" figure as the input to -m when calling afl-fuzz
(Normally, recidivm would output a figure automatically, but in some cases,
the fuzzing harness will hang when the memory limit is too small.)
@@ -88,9 +95,11 @@ don't care about memory limits.
To Run:
- mkdir -p src/test/fuzz/fuzz_http_findings
- ../afl/afl-fuzz -i ${TOR_FUZZ_CORPORA}/http -o src/test/fuzz/fuzz_http_findings -m <asan-memory-limit> -- src/test/fuzz/fuzz-http
+```console
+$ mkdir -p src/test/fuzz/fuzz_http_findings
+$ ../afl/afl-fuzz -i ${TOR_FUZZ_CORPORA}/http -o src/test/fuzz/fuzz_http_findings -m <asan-memory-limit> -- src/test/fuzz/fuzz-http
+```
AFL has a multi-core mode, check the documentation for details.
You might find the included fuzz-multi.sh script useful for this.
@@ -109,7 +118,10 @@ valid inputs may take a second or so, particularly with the fuzzer and
sanitizers enabled.
To see what fuzz-http is doing with a test case, call it like this:
- src/test/fuzz/fuzz-http --debug < /path/to/test.case
+
+```console
+$ src/test/fuzz/fuzz-http --debug < /path/to/test.case
+```
(Logging is disabled while fuzzing to increase fuzzing speed.)
@@ -118,4 +130,4 @@ To see what fuzz-http is doing with a test case, call it like this:
Please report any issues discovered using the process in Tor's security issue
policy:
-https://trac.torproject.org/projects/tor/wiki/org/meetings/2016SummerDevMeeting/Notes/SecurityIssuePolicy
+https://gitlab.torproject.org/tpo/core/team/-/wikis/NetworkTeam/SecurityPolicy
diff --git a/doc/HACKING/GettingStarted.md b/doc/HACKING/GettingStarted.md
index 633a7f0417..6d61be9881 100644
--- a/doc/HACKING/GettingStarted.md
+++ b/doc/HACKING/GettingStarted.md
@@ -37,13 +37,17 @@ Once you've reached this point, here's what you need to know.
We keep our source under version control in Git. To get the latest
version, run:
- git clone https://git.torproject.org/git/tor
+ ```console
+ $ git clone https://git.torproject.org/git/tor
+ ```
This will give you a checkout of the master branch. If you're
going to fix a bug that appears in a stable version, check out the
appropriate "maint" branch, as in:
- git checkout maint-0.4.3
+ ```console
+ $ git checkout maint-0.4.3
+ ```
2. Find your way around the source.
@@ -67,10 +71,11 @@ Once you've reached this point, here's what you need to know.
Many people have gotten started by looking for an area where they
personally felt Tor was underperforming, and investigating ways to
fix it. If you're looking for ideas, you can head to
- [trac](https://trac.torproject.org) our bug tracking tool and look for
- tickets that have received the "easy" tag: these are ones that developers
+ [gitlab](https://gitlab.torproject.org) our bug tracking tool and look for
+ tickets that have received the "First Contribution" label: these are ones
+ that developers
think would be pretty simple for a new person to work on. For a bigger
- challenge, you might want to look for tickets with the "lorax"
+ challenge, you might want to look for tickets with the "Project Ideas"
keyword: these are tickets that the developers think might be a
good idea to build, but which we have no time to work on any time
soon.
@@ -136,10 +141,10 @@ Once you've reached this point, here's what you need to know.
8. Submitting your patch
We review patches through tickets on our bugtracker at
- [trac](https://trac.torproject.org). You can either upload your patches there, or
+ [gitlab](https://gitlab.torproject.org). You can either upload your patches there, or
put them at a public git repository somewhere we can fetch them
(like gitlab, github or bitbucket) and then paste a link on the appropriate
- trac ticket.
+ ticket.
Once your patches are available, write a short explanation of what
you've done on trac, and then change the status of the ticket to
diff --git a/doc/HACKING/GettingStartedRust.md b/doc/HACKING/GettingStartedRust.md
index af80018f4e..beef825226 100644
--- a/doc/HACKING/GettingStartedRust.md
+++ b/doc/HACKING/GettingStartedRust.md
@@ -54,7 +54,9 @@ fetching dependencies from Cargo or specifying a local directory.
**Fetch dependencies from Cargo**
- ./configure --enable-rust --enable-cargo-online-mode
+```console
+$ ./configure --enable-rust --enable-cargo-online-mode
+```
**Using a local dependency cache**
@@ -66,13 +68,17 @@ We vendor our Rust dependencies in a separate repo using
[cargo-vendor](https://github.com/alexcrichton/cargo-vendor). To use
them, do:
- git submodule init
- git submodule update
+```console
+$ git submodule init
+$ git submodule update
+```
To specify the local directory containing the dependencies, (assuming
you are in the top level of the repository) configure tor with:
- TOR_RUST_DEPENDENCIES='path_to_dependencies_directory' ./configure --enable-rust
+```console
+$ TOR_RUST_DEPENDENCIES='path_to_dependencies_directory' ./configure --enable-rust
+```
(Note that `TOR_RUST_DEPENDENCIES` must be the full path to the directory; it
cannot be relative.)
@@ -80,7 +86,9 @@ cannot be relative.)
Assuming you used the above `git submodule` commands and you're in the
topmost directory of the repository, this would be:
- TOR_RUST_DEPENDENCIES=`pwd`/src/ext/rust/crates ./configure --enable-rust
+```console
+$ TOR_RUST_DEPENDENCIES=`pwd`/src/ext/rust/crates ./configure --enable-rust
+```
## Identifying which modules to rewrite
@@ -102,10 +110,12 @@ areas of responsibility.
A good first step is to build a module-level callgraph to understand how
interconnected your target module is.
- git clone https://git.torproject.org/user/nickm/calltool.git
- cd tor
- CFLAGS=0 ./configure
- ../calltool/src/main.py module_callgraph
+```console
+$ git clone https://git.torproject.org/user/nickm/calltool.git
+$ cd tor
+$ CFLAGS=0 ./configure
+$ ../calltool/src/main.py module_callgraph
+```
The output will tell you each module name, along with a set of every module that
the module calls. Modules which call fewer other modules are better targets.
@@ -114,7 +124,7 @@ the module calls. Modules which call fewer other modules are better targets.
Strive to change the C API as little as possible.
-We are currently targetting Rust stable. (See `CodingStandardsRust.md` for more
+We are currently targeting Rust stable. (See `CodingStandardsRust.md` for more
details.)
It is on our TODO list to try to cultivate good
@@ -156,15 +166,21 @@ run on your crate.
Configure Tor's build system to build with Rust enabled:
- ./configure --enable-fatal-warnings --enable-rust --enable-cargo-online-mode
+```console
+$ ./configure --enable-fatal-warnings --enable-rust --enable-cargo-online-mode
+```
Tor's test should be run by doing:
- make check
+```console
+$ make check
+```
Tor's integration tests should also pass:
- make test-stem
+```console
+$ make test-stem
+```
## Submitting a patch
diff --git a/doc/HACKING/HelpfulTools.md b/doc/HACKING/HelpfulTools.md
index 15bd153318..0ce59576f0 100644
--- a/doc/HACKING/HelpfulTools.md
+++ b/doc/HACKING/HelpfulTools.md
@@ -43,7 +43,9 @@ Builds should show up on the web at jenkins.torproject.org and on IRC at
## Valgrind
- valgrind --leak-check=yes --error-limit=no --show-reachable=yes src/app/tor
+```console
+$ valgrind --leak-check=yes --error-limit=no --show-reachable=yes src/app/tor
+```
(Note that if you get a zillion openssl warnings, you will also need to
pass `--undef-value-errors=no` to valgrind, or rebuild your openssl
@@ -77,10 +79,12 @@ we wish to permit are also documented in the blacklist file.
Lcov is a utility that generates pretty HTML reports of test code coverage.
To generate such a report:
- ./configure --enable-coverage
- make
- make coverage-html
- $BROWSER ./coverage_html/index.html
+```console
+$ ./configure --enable-coverage
+$ make
+$ make coverage-html
+$ $BROWSER ./coverage_html/index.html
+```
This will run the tor unit test suite `./src/test/test` and generate the HTML
coverage code report under the directory `./coverage_html/`. To change the
@@ -93,36 +97,48 @@ investigated (as of July 2014).
To quickly run all the tests distributed with Tor:
- make check
+```console
+$ make check
+```
To run the fast unit tests only:
- make test
+```console
+$ make test
+```
To selectively run just some tests (the following can be combined
arbitrarily):
- ./src/test/test <name_of_test> [<name of test 2>] ...
- ./src/test/test <prefix_of_name_of_test>.. [<prefix_of_name_of_test2>..] ...
- ./src/test/test :<name_of_excluded_test> [:<name_of_excluded_test2]...
+```console
+$ ./src/test/test <name_of_test> [<name of test 2>] ...
+$ ./src/test/test <prefix_of_name_of_test>.. [<prefix_of_name_of_test2>..] ...
+$ ./src/test/test :<name_of_excluded_test> [:<name_of_excluded_test2]...
+```
To run all tests, including those based on Stem or Chutney:
- make test-full
+```console
+$ make test-full
+```
To run all tests, including those based on Stem or Chutney that require a
working connection to the internet:
- make test-full-online
+```console
+$ make test-full-online
+```
## Running gcov for unit test coverage
- ./configure --enable-coverage
- make
- make check
- # or--- make test-full ? make test-full-online?
- mkdir coverage-output
- ./scripts/test/coverage coverage-output
+```console
+$ ./configure --enable-coverage
+$ make
+$ make check
+$ # or--- make test-full ? make test-full-online?
+$ mkdir coverage-output
+$ ./scripts/test/coverage coverage-output
+```
(On OSX, you'll need to start with `--enable-coverage CC=clang`.)
@@ -145,7 +161,9 @@ you can run `make reset-gcov` to clear the intermediary gcov output.
If you have two different `coverage-output` directories, and you want to see
a meaningful diff between them, you can run:
- ./scripts/test/cov-diff coverage-output1 coverage-output2 | less
+```console
+$ ./scripts/test/cov-diff coverage-output1 coverage-output2 | less
+```
In this diff, any lines that were visited at least once will have coverage "1",
and line numbers are deleted. This lets you inspect what you (probably) really
@@ -313,12 +331,16 @@ that you're using the emacs-specific version of `etags` (bundled under the
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' .
+```console
+$ 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}' .
+```console
+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.
@@ -330,50 +352,58 @@ source code. Here's how to use it:
1. Begin every file that should be documented with
- /**
- * \file filename.c
- * \brief Short description of the file.
- */
+```
+ /**
+ * \file filename.c
+ * \brief Short description of the file.
+ */
+```
- (Doxygen will recognize any comment beginning with /** as special.)
+ (Doxygen will recognize any comment beginning with /** as special.)
2. Before any function, structure, #define, or variable you want to
document, add a comment of the form:
- /** Describe the function's actions in imperative sentences.
- *
- * Use blank lines for paragraph breaks
- * - and
- * - hyphens
- * - for
- * - lists.
- *
- * Write <b>argument_names</b> in boldface.
- *
- * \code
- * place_example_code();
- * between_code_and_endcode_commands();
- * \endcode
- */
+```
+/** Describe the function's actions in imperative sentences.
+ *
+ * Use blank lines for paragraph breaks
+ * - and
+ * - hyphens
+ * - for
+ * - lists.
+ *
+ * Write <b>argument_names</b> in boldface.
+ *
+ * \code
+ * place_example_code();
+ * between_code_and_endcode_commands();
+ * \endcode
+ */
+```
3. Make sure to escape the characters `<`, `>`, `\`, `%` and `#` as `\<`,
`\>`, `\\`, `\%` and `\#`.
4. To document structure members, you can use two forms:
- struct foo {
- /** You can put the comment before an element; */
- int a;
- int b; /**< Or use the less-than symbol to put the comment
- * after the element. */
- };
+```c
+struct foo {
+ /** You can put the comment before an element; */
+ int a;
+ int b; /**< Or use the less-than symbol to put the comment
+ * after the element. */
+};
+```
5. To generate documentation from the Tor source code, type:
- $ doxygen -g
+```console
+$ doxygen -g
+```
- to generate a file called `Doxyfile`. Edit that file and run
- `doxygen` to generate the API documentation.
+ to generate a file called `Doxyfile`. Edit that file and run
+ `doxygen` to generate the API documentation.
6. See the Doxygen manual for more information; this summary just
scratches the surface.
diff --git a/doc/HACKING/Module.md b/doc/HACKING/Module.md
index f8a9773d47..b9d3a654eb 100644
--- a/doc/HACKING/Module.md
+++ b/doc/HACKING/Module.md
@@ -70,7 +70,7 @@ There are couples of "rules" you want to follow:
base. Every entry point should have a second definition if the module is
disabled. For instance:
- ```
+ ```c
#ifdef HAVE_MODULE_DIRAUTH
int sr_init(int save_to_disk);
@@ -109,7 +109,9 @@ There are couples of "rules" you want to follow:
* When you include headers from the module, **always** use the full module
path in your statement. Example:
- `#include "feature/dirauth/dirvote.h"`
+```c
+#include "feature/dirauth/dirvote.h"`
+```
The main reason is that we do **not** add the module include path by default
so it needs to be specified. But also, it helps our human brain understand
diff --git a/doc/HACKING/README.1st.md b/doc/HACKING/README.1st.md
index 2278a61d6c..4bc3298c67 100644
--- a/doc/HACKING/README.1st.md
+++ b/doc/HACKING/README.1st.md
@@ -32,7 +32,9 @@ For an explanation of how to change Tor's design to work differently, look at
For the latest version of the code, get a copy of git, and
- git clone https://git.torproject.org/git/tor
+```console
+$ git clone https://git.torproject.org/git/tor
+```
## Stay in touch
diff --git a/doc/HACKING/ReleaseSeriesLifecycle.md b/doc/HACKING/ReleaseSeriesLifecycle.md
index e4068ed806..8536fbbd08 100644
--- a/doc/HACKING/ReleaseSeriesLifecycle.md
+++ b/doc/HACKING/ReleaseSeriesLifecycle.md
@@ -102,7 +102,7 @@ they do not apply to security-related patch release versions.
4. Open tickets for connecting the new branches to various other
places. See section 2 above for a list of affected locations.
-5. Stop running practracker on maintainence and release branches:
+5. Stop running practracker on maintenance and release branches:
* Remove "check-best-practices" from the check-local Makefile
target in the maint-x.y.z branch only.
* Delete the file scripts/maint/practracker/.enable_practracker_in_hooks
diff --git a/doc/HACKING/ReleasingTor.md b/doc/HACKING/ReleasingTor.md
index 2464d8afb4..24b66a069a 100644
--- a/doc/HACKING/ReleasingTor.md
+++ b/doc/HACKING/ReleasingTor.md
@@ -9,8 +9,20 @@ new Tor release:
version number in their approved versions list. Give them a few
days to do this if you can.
-2. If this is going to be an important security release, give the packagers
- some advance warning: See this list of packagers in IV.3 below.
+2. If this is going to be an important security release, give these packagers
+ some advance warning:
+
+ - {weasel,sysrqb,mikeperry} at torproject dot org
+ - {blueness} at gentoo dot org
+ - {paul} at invizbox dot io
+ - {vincent} at invizbox dot com
+ - {lfleischer} at archlinux dot org
+ - {Nathan} at freitas dot net
+ - {mike} at tig dot as
+ - {tails-rm} at boum dot org
+ - {simon} at sdeziel.info
+ - {yuri} at freebsd.org
+ - {mh+tor} at scrit.ch
3. Given the release date for Tor, ask the TB team about the likely release
date of a TB that contains it. See note below in "commit, upload,
@@ -36,19 +48,6 @@ new Tor release:
* On OSS-Fuzz
-3. Run checks that aren't covered above, including:
-
- * clang scan-build. (See the script in ./scripts/test/scan_build.sh)
-
- * make test-network and make test-network-all (with
- --enable-fragile-hardening)
-
- * Running Tor yourself and making sure that it actually works for you.
-
- * Running Tor under valgrind. (Our 'fragile hardening' doesn't cover
- libevent and openssl, so using valgrind will sometimes find extra
- memory leaks.)
-
## II. Write a changelog
1a. (Alpha release variant)
@@ -57,11 +56,12 @@ new Tor release:
of them and reordering to focus on what users and funders would find
interesting and understandable.
- To do this, run
- `./scripts/maint/sortChanges.py changes/* > changelog.in`
- to combine headings and sort the entries. Copy the changelog.in file
- into the ChangeLog. Run 'format_changelog.py' (see below) to clean
- up the line breaks.
+ To do this, run `./scripts/maint/sortChanges.py changes/* > changelog.in`
+ to combine headings and sort the entries. Copy the changelog.in file into
+ the ChangeLog. Run `format_changelog.py --inplace` (see below) to clean up
+ the line breaks.
+
+ Remove the `changes/*` files that you just merged into the ChangeLog.
After that, it's time to hand-edit and fix the issues that
lintChanges can't find:
@@ -141,10 +141,11 @@ new Tor release:
places, and commit. Then merge `maint-0.?.x` into `release-0.?.x`.
When you merge the maint branch forward to the next maint branch, or into
- master, merge it with "-s ours" to avoid a needless version bump.
+ master, merge it with "-s ours" to avoid conflict with the version
+ bump.
2. Make distcheck, put the tarball up in somewhere (how about your
- homedir on your homedir on people.torproject.org?) , and tell `#tor-dev`
+ homedir on people.torproject.org?) , and tell `#tor-dev`
about it.
If you want, wait until at least one person has built it
@@ -152,7 +153,6 @@ new Tor release:
CI has successfully caught these kinds of errors for the last several
years.)
-
3. Make sure that the new version is recommended in the latest consensus.
(Otherwise, users will get confused when it complains to them
about its status.)
@@ -164,9 +164,11 @@ new Tor release:
1. Sign the tarball, then sign and push the git tag:
- gpg -ba <the_tarball>
- git tag -s tor-0.4.x.y-<status>
- git push origin tag tor-0.4.x.y-<status>
+```console
+$ gpg -ba <the_tarball>
+$ git tag -s tor-0.4.x.y-<status>
+$ git push origin tag tor-0.4.x.y-<status>
+```
(You must do this before you update the website: the website scripts
rely on finding the version by tag.)
@@ -178,7 +180,6 @@ new Tor release:
`/srv/dist-master.torproject.org/htdocs/` on dist-master. Run
"static-update-component dist.torproject.org" on dist-master.
- In the webwml.git repository, `include/versions.wmi` and `Makefile`.
In the project/web/tpo.git repository, update `databags/versions.ini`
to note the new version. Push these changes to master.
@@ -189,20 +190,8 @@ new Tor release:
(NOTE: It will take a while for the website update scripts to update
the website.)
-3. Email the packagers (cc'ing tor-team) that a new tarball is up.
- The current list of packagers is:
-
- - {weasel,sysrqb,mikeperry} at torproject dot org
- - {blueness} at gentoo dot org
- - {paul} at invizbox dot io
- - {vincent} at invizbox dot com
- - {lfleischer} at archlinux dot org
- - {Nathan} at freitas dot net
- - {mike} at tig dot as
- - {tails-rm} at boum dot org
- - {simon} at sdeziel.info
- - {yuri} at freebsd.org
- - {mh+tor} at scrit.ch
+3. Email the tor-packagers@lists.torproject.org mailing list to tell them
+ about the new release.
Also, email tor-packagers@lists.torproject.org.
@@ -210,22 +199,15 @@ new Tor release:
Include a link to the changelog.
-4. Add the version number to Trac. To do this, go to Trac, log in,
- select "Admin" near the top of the screen, then select "Versions" from
- the menu on the left. At the right, there will be an "Add version"
- box. By convention, we enter the version in the form "Tor:
- 0.4.0.1-alpha" (or whatever the version is), and we select the date as
- the date in the ChangeLog.
-
-5. Wait for the download page to be updated. (If you don't do this before you
+4. Wait for the download page to be updated. (If you don't do this before you
announce, people will be confused.)
-6. Mail the release blurb and ChangeLog to tor-talk (development release) or
+5. Mail the release blurb and ChangeLog to tor-talk (development release) or
tor-announce (stable).
Post the changelog on the blog as well. You can generate a
blog-formatted version of the changelog with
- `./scripts/maint/format_changelog.py --B`
+ `./scripts/maint/format_changelog.py -B`
When you post, include an estimate of when the next TorBrowser
releases will come out that include this Tor release. This will
@@ -233,13 +215,13 @@ new Tor release:
can vary.
For templates to use when announcing, see:
- https://trac.torproject.org/projects/tor/wiki/org/teams/NetworkTeam/AnnouncementTemplates
+ https://gitlab.torproject.org/tpo/core/team/-/wikis/NetworkTeam/AnnouncementTemplates
## V. Aftermath and cleanup
1. If it's a stable release, bump the version number in the
- `maint-x.y.z` branch to "newversion-dev", and do a `merge -s ours`
- merge to avoid taking that change into master.
+ `maint-x.y.z` branch to "newversion-dev", and do a `merge -s ours`
+ merge to avoid taking that change into master.
2. If there is a new `maint-x.y.z` branch, create a Travis CI cron job that
builds the release every week. (It's ok to skip the weekly build if the
diff --git a/doc/HACKING/Tracing.md b/doc/HACKING/Tracing.md
deleted file mode 100644
index e1e97abe6d..0000000000
--- a/doc/HACKING/Tracing.md
+++ /dev/null
@@ -1,91 +0,0 @@
-# Tracing
-
-This document describes how the event tracing subsystem works in tor so
-developers can add events to the code base but also hook them to an event
-tracing framework.
-
-## Basics
-
-Event tracing is separated in two concepts, trace events and a tracer. The
-tracing subsystem can be found in `src/trace`. The `events.h` header file is
-the main file that maps the different tracers to trace events.
-
-### Events
-
-A trace event is basically a function from which we can pass any data that
-we want to collect. In addition, we specify a context for the event such as
-a subsystem and an event name.
-
-A trace event in tor has the following standard format:
-
- tor_trace(subsystem, event\_name, args...)
-
-The `subsystem` parameter is the name of the subsytem the trace event is in.
-For example that could be "scheduler" or "vote" or "hs". The idea is to add
-some context to the event so when we collect them we know where it's coming
-from. The `event_name` is the name of the event which helps a lot with
-adding some semantic to the event. Finally, `args` is any number of
-arguments we want to collect.
-
-Here is an example of a possible tracepoint in main():
-
- tor_trace(main, init_phase, argc)
-
-The above is a tracepoint in the `main` subsystem with `init_phase` as the
-event name and the `int argc` is passed to the event as well.
-
-How `argc` is collected or used has nothing to do with the instrumentation
-(adding trace events to the code). It is the work of the tracer so this is why
-the trace events and collection framework (tracer) are decoupled. You _can_
-have trace events without a tracer.
-
-### Tracer
-
-In `src/trace/events.h`, we map the `tor_trace()` function to the right
-tracer. A tracer support is only enabled at compile time. For instance, the
-file `src/trace/debug.h` contains the mapping of the generic tracing function
-`tor_trace()` to the `log_debug()` function. More specialized function can be
-mapped depending on the tracepoint.
-
-## Build System
-
-This section describes how it is integrated into the build system of tor.
-
-By default, every tracing events are disabled in tor that is `tor_trace()`
-is a NOP.
-
-To enable a tracer, there is a configure option on the form of:
-
- --enable-tracing-<tracer>
-
-We have an option that will send every trace events to a `log_debug()` (as
-mentionned above) which will print you the subsystem and name of the event but
-not the arguments for technical reasons. This is useful if you want to quickly
-see if your trace event is being hit or well written. To do so, use this
-configure option:
-
- --enable-tracing-debug
-
-## Instrument Tor
-
-This is pretty easy. Let's say you want to add a trace event in
-`src/feature/rend/rendcache.c`, you only have to add this include statement:
-
- #include "trace/events.h"
-
-Once done, you can add as many as you want `tor_trace()` that you need.
-Please use the right subsystem (here it would be `hs`) and a unique name that
-tells what the event is for. For example:
-
- tor_trace(hs, store_desc_as_client, desc, desc_id);
-
-If you look in `src/trace/events.h`, you'll see that if tracing is enabled it
-will be mapped to a function called:
-
- tor_trace_hs_store_desc_as_client(desc, desc_id)
-
-And the point of all this is for that function to be defined in a new file
-that you might want to add named `src/trace/hs.{c|h}` which would defined how
-to collect the data for the `tor_trace_hs_store_desc_as_client()` function
-like for instance sending it to a `log_debug()` or do more complex operations
-or use a userspace tracer like LTTng (https://lttng.org).
diff --git a/doc/HACKING/WritingTests.md b/doc/HACKING/WritingTests.md
index d212020525..e1497a77c2 100644
--- a/doc/HACKING/WritingTests.md
+++ b/doc/HACKING/WritingTests.md
@@ -107,7 +107,9 @@ covered or uncovered.
To count new or modified uncovered lines in D2, you can run:
- ./scripts/test/cov-diff ${D1} ${D2}" | grep '^+ *\#' | wc -l
+```console
+$ ./scripts/test/cov-diff ${D1} ${D2}" | grep '^+ *\#' | wc -l
+```
## Marking lines as unreachable by tests
@@ -163,28 +165,30 @@ I use the term "unit test" and "regression tests" very sloppily here.
Here's an example of a test function for a simple function in util.c:
- static void
- test_util_writepid(void *arg)
- {
- (void) arg;
+```c
+static void
+test_util_writepid(void *arg)
+{
+ (void) arg;
- char *contents = NULL;
- const char *fname = get_fname("tmp_pid");
- unsigned long pid;
- char c;
+ char *contents = NULL;
+ const char *fname = get_fname("tmp_pid");
+ unsigned long pid;
+ char c;
- write_pidfile(fname);
+ write_pidfile(fname);
- contents = read_file_to_str(fname, 0, NULL);
- tt_assert(contents);
+ contents = read_file_to_str(fname, 0, NULL);
+ tt_assert(contents);
- int n = sscanf(contents, "%lu\n%c", &pid, &c);
- tt_int_op(n, OP_EQ, 1);
- tt_int_op(pid, OP_EQ, getpid());
+ int n = sscanf(contents, "%lu\n%c", &pid, &c);
+ tt_int_op(n, OP_EQ, 1);
+ tt_int_op(pid, OP_EQ, getpid());
- done:
- tor_free(contents);
- }
+done:
+ tor_free(contents);
+}
+```
This should look pretty familiar to you if you've read the tinytest
manual. One thing to note here is that we use the testing-specific
@@ -214,10 +218,12 @@ macro-protected declaration of the function in the module's header.
For example, `crypto_curve25519.h` contains:
- #ifdef CRYPTO_CURVE25519_PRIVATE
- STATIC int curve25519_impl(uint8_t *output, const uint8_t *secret,
- const uint8_t *basepoint);
- #endif
+```c
+#ifdef CRYPTO_CURVE25519_PRIVATE
+STATIC int curve25519_impl(uint8_t *output, const uint8_t *secret,
+ const uint8_t *basepoint);
+#endif
+```
The `crypto_curve25519.c` file and the `test_crypto.c` file both define
`CRYPTO_CURVE25519_PRIVATE`, so they can see this declaration.
@@ -231,28 +237,29 @@ the test _really tests_ the code.
For example, here is a _bad_ test for the unlink() function (which is
supposed to remove a file).
- static void
- test_unlink_badly(void *arg)
- {
- (void) arg;
- int r;
+```c
+static void
+test_unlink_badly(void *arg)
+{
+ (void) arg;
+ int r;
- const char *fname = get_fname("tmpfile");
+ const char *fname = get_fname("tmpfile");
- /* If the file isn't there, unlink returns -1 and sets ENOENT */
- r = unlink(fname);
- tt_int_op(n, OP_EQ, -1);
- tt_int_op(errno, OP_EQ, ENOENT);
+ /* If the file isn't there, unlink returns -1 and sets ENOENT */
+ r = unlink(fname);
+ tt_int_op(n, OP_EQ, -1);
+ tt_int_op(errno, OP_EQ, ENOENT);
- /* If the file DOES exist, unlink returns 0. */
- write_str_to_file(fname, "hello world", 0);
- r = unlink(fnme);
- tt_int_op(r, OP_EQ, 0);
-
- done:
- tor_free(contents);
- }
+ /* If the file DOES exist, unlink returns 0. */
+ write_str_to_file(fname, "hello world", 0);
+ r = unlink(fnme);
+ tt_int_op(r, OP_EQ, 0);
+done:
+ tor_free(contents);
+}
+```
This test might get very high coverage on unlink(). So why is it a
bad test? Because it doesn't check that unlink() *actually removes the
@@ -273,20 +280,25 @@ To write tests for this case, you can replace the underlying functions
with testing stubs while your unit test is running. You need to declare
the underlying function as 'mockable', as follows:
- MOCK_DECL(returntype, functionname, (argument list));
+```c
+MOCK_DECL(returntype, functionname, (argument list));
+```
and then later implement it as:
- MOCK_IMPL(returntype, functionname, (argument list))
- {
- /* implementation here */
- }
+```c
+MOCK_IMPL(returntype, functionname, (argument list))
+{
+ /* implementation here */
+}
+```
For example, if you had a 'connect to remote server' function, you could
declare it as:
-
- MOCK_DECL(int, connect_to_remote, (const char *name, status_t *status));
+```c
+MOCK_DECL(int, connect_to_remote, (const char *name, status_t *status));
+```
When you declare a function this way, it will be declared as normal in
regular builds, but when the module is built for testing, it is declared
@@ -295,11 +307,15 @@ as a function pointer initialized to the actual implementation.
In your tests, if you want to override the function with a temporary
replacement, you say:
- MOCK(functionname, replacement_function_name);
+```c
+MOCK(functionname, replacement_function_name);
+```
And later, you can restore the original function with:
- UNMOCK(functionname);
+```c
+UNMOCK(functionname);
+```
For more information, see the definitions of this mocking logic in
`testsupport.h`.
@@ -324,11 +340,13 @@ cases and failure csaes.
For example, consider testing this function:
- /** Remove all elements E from sl such that E==element. Preserve
- * the order of any elements before E, but elements after E can be
- * rearranged.
- */
- void smartlist_remove(smartlist_t *sl, const void *element);
+```c
+/** Remove all elements E from sl such that E==element. Preserve
+ * the order of any elements before E, but elements after E can be
+ * rearranged.
+ */
+void smartlist_remove(smartlist_t *sl, const void *element);
+```
In order to test it well, you should write tests for at least all of the
following cases. (These would be black-box tests, since we're only looking
@@ -355,19 +373,21 @@ When you consider edge cases, you might try:
Now let's look at the implementation:
- void
- smartlist_remove(smartlist_t *sl, const void *element)
- {
- int i;
- if (element == NULL)
+```c
+void
+smartlist_remove(smartlist_t *sl, const void *element)
+{
+ int i;
+ if (element == NULL)
return;
- for (i=0; i < sl->num_used; i++)
+ for (i=0; i < sl->num_used; i++)
if (sl->list[i] == element) {
- sl->list[i] = sl->list[--sl->num_used]; /* swap with the end */
- i--; /* so we process the new i'th element */
- sl->list[sl->num_used] = NULL;
+ sl->list[i] = sl->list[--sl->num_used]; /* swap with the end */
+ i--; /* so we process the new i'th element */
+ sl->list[sl->num_used] = NULL;
}
- }
+}
+```
Based on the implementation, we now see three more edge cases to test:
@@ -484,3 +504,15 @@ targets in `Makefile.am`.
(Adding new kinds of program to chutney will still require hacking the
code.)
+
+## Other integration tests
+
+It's fine to write tests that use a POSIX shell to invoke Tor or test other
+aspects of the system. When you do this, have a look at our existing tests
+of this kind in `src/test/` to make sure that you haven't forgotten anything
+important. For example: it can be tricky to make sure you're invoking Tor at
+the right path in various build scenarios.
+
+We use a POSIX shell whenever possible here, and we use the shellcheck tool
+to make sure that our scripts portable. We should only require bash for
+scripts that are developer-only.
diff --git a/doc/HACKING/android/Simpleperf.md b/doc/HACKING/android/Simpleperf.md
index c7e63a7c86..ed640f912e 100644
--- a/doc/HACKING/android/Simpleperf.md
+++ b/doc/HACKING/android/Simpleperf.md
@@ -29,7 +29,9 @@ the Android Software Development Kit (SDK) and Native Development Kit
3. Install the Android Package you generated in step 1:
+```bash
$ adb install /path/to/your/app-fullperm-debug.apk
+```
4. Check on your device that the newly installed Orbot actually works
and behaves in the way you expect it to.
@@ -76,10 +78,12 @@ was spend on the call.
To access binaries, `torrc` files, and other useful information on
the device do the following:
+```console
$ adb shell
(device):/ $ run-as org.torproject.android
(device):/data/data/org.torproject.android $ ls
app_bin app_data cache databases files lib shared_prefs
+```
Descriptors, control authentication cookie, state, and other files can be
found in the `app_data` directory. The `torrc` can be found in the `app_bin/`
@@ -88,10 +92,14 @@ was spend on the call.
- You can enable logging in Tor via the syslog (or android) log
mechanism with:
+```console
$ adb shell
(device):/ $ run-as org.torproject.android
(device):/data/data/org.torproject.android $ echo -e "\nLog info syslog" >> app_bin/torrc
+```
Start Tor the normal way via Orbot and collect the logs from your computer using
+```console
$ adb logcat
+```
diff --git a/doc/HACKING/tracing/EventsCircuit.md b/doc/HACKING/tracing/EventsCircuit.md
new file mode 100644
index 0000000000..42abdda856
--- /dev/null
+++ b/doc/HACKING/tracing/EventsCircuit.md
@@ -0,0 +1,139 @@
+# Circuit Subsystem Trace Events
+
+The circuit subsystem emits a series of tracing events related to a circuit
+object life cycle and its state change.
+
+This document describes each event as in what data they record and what they
+represent.
+
+## Background
+
+There are two types of circuits: origin and OR (onion router). Both of them
+are derived from a base object called a general circuit.
+
+- Origin circuits are the ones initiated by tor itself so client or onion
+ service circuits for instance.
+
+- OR circuits are the ones going through us that we have not initiated and
+ thus only seen by relays.
+
+Many operations are done on the base (general) circuit, and some are specific
+to an origin or OR. The following section describes each of them by circuit
+type.
+
+## Trace Events
+
+For the LTTng tracer, the subsystem name of these events is: `tor_circuit`.
+
+Also, unless specified otherwise, every event emits a common set of parameters
+thus they should always be expected in the following order:
+
+- `circ_id`: For an origin circuit, this is the global circuit identifier used
+ in a cell. For an OR circuit, the value is 0.
+
+- `purpose`: Purpose of the circuit as in what it is used for. Note that this
+ can change during the lifetime of a circuit. See `CIRCUIT_PURPOSE_*` in
+ `core/or/circuitlist.h` for an exhaustive list of the possible values.
+
+- `state`: State of a circuit. This changes during the lifetime of a circuit.
+ See `CIRCUIT_STATE_*` in `core/or/circuitlist.h` for an exhaustive list of
+ the possible values.
+
+Now, the tracing events.
+
+### General Circuit (`circuit_t`)
+
+The following events are triggered for the base circuit object and thus apply
+to all types of circuits.
+
+ * `free`: A circuit object is freed that is memory is released and not
+ usable anymore. After this event, no more events will be emitted for the
+ specific circuit object.
+
+ * `mark_for_close`: A circuit object is marked for close that is scheduled
+ to be closed in a later mainloop periodic event.
+
+ Extra parameters:
+
+ - `end_reason`: Reason why the circuit is closed. Tor often changes that
+ reason to something generic sometimes in order to avoid leaking internal
+ reasons to the end point. Thus, this value can be different from
+ orig_close_reason.
+
+ - `orig_close_reason`: Original reason why the circuit is closed. That
+ value never changes and contains the internal reason why we close it. It
+ is **never** this reason that is sent back on the circuit.
+
+ * `change_purpose`: Purpose change.
+
+ Extra parameters:
+
+ (`purpose` parameter is not present)
+
+ - `old_purpose`: Previous purpose that is no longer.
+
+ - `new_purpose`: New purpose assigned to the circuit.
+
+ * `change_state`: State change.
+
+ Extra parameters:
+
+ (`state` parameter is not present)
+
+ - `old_state`: Previous state that is no longer.
+
+ - `new_state`: New state assigned to the circuit.
+
+### Origin Circuit (`origin_circuit_t`)
+
+The following events are triggered only for origin circuits.
+
+ * `new_origin`: New origin circuit has been created meaning it has been
+ newly allocated, initialized and added to the global list.
+
+ * `establish`: Circuit is being established. This is the initial first step
+ where the path was selected and a connection to the first hop has been
+ launched.
+
+ * `cannibalized`: Circuit has been cannibalized. This happens when we have
+ an already opened unused circuit (preemptive circuits) and it was picked.
+
+ * `first_onion_skin`: First onion skin was sent that is the handshake with
+ the first hop.
+
+ Extra parameters:
+
+ - `fingerprint`: Identity digest (RSA) of the first hop.
+
+ * `intermediate_onion_skin`: An intermediate onion skin was sent which can
+ be why any hops after the first one. There is thus `N - 1` of these events
+ where `N` is the total number of hops in the path.
+
+ Extra parameters:
+
+ - `fingerprint`: Identity digest (RSA) of the next hop.
+
+ * `opened`: Circuit just became opened which means that all hops down the
+ path have negotiated the handshake between them and us and the circuit is
+ now ready to send cells.
+
+ * `timeout`: Circuit has timed out that is we waited too long for the
+ circuit to be built.
+
+ * `idle_timeout`: Circuit has timed out due to idleness. This is controlled
+ by the MaxCircuitDirtiness parameter which is 10 min by default.
+
+For the common use case of a 3-hop circuit, the following events should be
+seen in this order:
+
+ `new_origin` -> `establish` -> `first_onion_skin` ->
+ `intermediate_onion_skin` -> `intermediate_onion_skin` -> `opened`
+
+### OR Circuit (`or_circuit_t`)
+
+The following events are triggered only for OR circuits. For each of them, the
+`circ_id` parameter is not present since it would always be 0. The `purpose`
+and `state` remain.
+
+ * `new_or`: New OR circuit has been created meaning it has been newly
+ allocated, initialized and added to the global list.
diff --git a/doc/HACKING/tracing/README.md b/doc/HACKING/tracing/README.md
new file mode 100644
index 0000000000..f34709bf3a
--- /dev/null
+++ b/doc/HACKING/tracing/README.md
@@ -0,0 +1,163 @@
+# Tracing
+
+This document describes how the event tracing subsystem works in tor so
+developers can add events to the code base but also hook them to an event
+tracing framework (i.e. tracer).
+
+## WARNING ##
+
+Tracing the tor daemon **always** generates sensitive data if used in
+production (on the public network).
+
+It **is** ethical for researchers to use tracing for their own tor client (for
+example: building paths, timings, or performance).
+
+It is **NOT** ethical to archive, publish or keep data containing other users'
+activity such as relay data or anything that handles users' traffic. This
+of course includes any logs below notice level.
+
+Publishing analysis of tracing data containing user traffic is **NOT** safe
+either.
+
+In other words, tracing data that contains other users's activity is **NOT**
+safe to publish in any form.
+
+## Basics ###
+
+Tracing is separated in two different concepts. The tracing API and the
+tracing probes.
+
+The API is in `src/lib/trace/` which defines how to call tracepoints in the
+tor code. Every C files should include `src/lib/trace/events.h` if they want
+to call a tracepoint.
+
+The probes are what actually record the tracepoint data. Because they often
+need to access specific subsystem objects, the probes are within each
+subsystem. They are defined in the `trace-probes-<subsystem>.c` files.
+
+### Events
+
+A trace event is basically a function from which we can pass any data that we
+want to collect. In addition, we specify a context for the event such as the
+subsystem and an event name.
+
+A trace event in tor has the following standard format:
+
+```c
+tor_trace(subsystem, event_name, args...);
+```
+
+The `subsystem` parameter is the name of the subsystem the trace event is in.
+For example that could be "scheduler" or "vote" or "hs". The idea is to add
+some context to the event so when we collect them we know where it's coming
+from.
+
+The `event_name` is the name of the event which adds better semantic to the
+event.
+
+The `args` can be any number of arguments we want to collect.
+
+Here is an example of a possible tracepoint in main():
+
+```c
+tor_trace(main, init_phase, argc);
+```
+
+The above is a tracepoint in the `main` subsystem with `init_phase` as the
+event name and the `int argc` is passed to the event as one argument.
+
+How `argc` is collected or used has nothing to do with the instrumentation
+(adding trace events to the code). It is the work of the tracer so this is why
+the trace events and collection framework (tracer) are decoupled. You _can_
+have trace events without a tracer.
+
+### Instrumentation ###
+
+In `src/lib/trace/events.h`, we map the high level `tor_trace()` macro to one
+or many enabled instrumentation.
+
+Currently, we have 3 types of possible instrumentation:
+
+1. Debug
+
+ This will map every tracepoint to `log_debug()`. However, none of the
+ arguments will be passed on because we don't know their type nor the string
+ format of the debug log. The output is standardized like this:
+
+```
+[debug] __FUNC__: Tracepoint <event_name> from subsystem <subsystem> hit.
+```
+
+2. USDT
+
+ User Statically-Defined Tracing (USDT) is a kind of probe which can be
+ handled by a variety of tracers such as SystemTap, DTrace, perf, eBPF and
+ ftrace.
+
+ For each tracer, one will need to define the ABI in order for the tracer to
+ be able to extract the data from the tracepoint objects. For instance, the
+ tracer needs to know how to print the circuit state of a `circuit_t`
+ object.
+
+3. LTTng-UST
+
+ LTTng Userspace is a tracer that has it own type of instrumentation. The
+ probe definitions are created within the C code and is strongly typed.
+
+ For more information, see https://lttng.org/docs.
+
+## Build System
+
+This section describes how the instrumentation is integrated into the build
+system of tor.
+
+By default, every tracing events are disabled in tor that is `tor_trace()` is
+a NOP thus has no execution cost time.
+
+To enable a specific instrumentation, there are configure options:
+
+1. Debug: `--enable-tracing-instrumentation-debug`
+
+2. USDT: `--enable-tracing-instrumentation-usdt`
+
+3. LTTng: `--enable-tracing-instrumentation-lttng`
+
+They can all be used together or independently. If one of them is set,
+`HAVE_TRACING` define is set. And for each instrumentation, a
+`USE_TRACING_INSTRUMENTATION_<type>` is set.
+
+## Adding a Tracepoint ##
+
+This is pretty easy. Let's say you want to add a trace event in
+`src/feature/rend/rendcache.c`, you first need to include this file:
+
+```c
+#include "lib/trace/events.h"
+```
+
+Then, the `tor_trace()` macro can be used with the specific format detailed
+before in a previous section. As an example:
+
+```c
+tor_trace(hs, store_desc_as_client, desc, desc_id);
+```
+
+For `Debug` instrumentation, you have nothing else to do.
+
+For `USDT`, instrumentation, you will need to define the probes in a way the
+specific tracer can understand. For instance, SystemTap requires you to define
+a `tapset` for each tracepoints.
+
+For `LTTng`, you will need to define the probes in the
+`trace-probes-<subsystem>.{c|h}` file. See the `trace-probes-circuit.{c|h}`
+file as an example and https://lttng.org/docs/v2.11/#doc-instrumenting.
+
+## Performance ##
+
+A word about performance when a tracepoint is enabled. One of the goal of a
+tracepoint (USDT, LTTng-UST, ...) is that they can be enabled or disabled. By
+default, they are disabled which means the tracer will not record the data but
+it has to do a check thus the cost is basically the one of a `branch`.
+
+If enabled, then the performance depends on the tracer. In the case of
+LTTng-UST, the event costs around 110nsec.
diff --git a/doc/TUNING b/doc/TUNING
index 24552a38cb..882a6dd68d 100644
--- a/doc/TUNING
+++ b/doc/TUNING
@@ -1,23 +1,23 @@
-Most operating systems limit an amount of TCP sockets that can be used
+Most operating systems limit an amount of TCP sockets that can be used
simultaneously. It is possible for a busy Tor relay to run into these
-limits, thus being unable to fully utilize the bandwidth resources it
+limits, thus being unable to fully utilize the bandwidth resources it
has at its disposal. Following system-specific tips might be helpful
to alleviate the aforementioned problem.
Linux
-----
-Use 'ulimit -n' to raise an allowed number of file descriptors to be
+Use 'ulimit -n' to raise an allowed number of file descriptors to be
opened on your host at the same time.
FreeBSD
-------
-Tune the followind sysctl(8) variables:
+Tune the following sysctl(8) variables:
* kern.maxfiles - maximum allowed file descriptors (for entire system)
* kern.maxfilesperproc - maximum file descriptors one process is allowed
to use
- * kern.ipc.maxsockets - overall maximum numbers of sockets for entire
+ * kern.ipc.maxsockets - overall maximum numbers of sockets for entire
system
* kern.ipc.somaxconn - size of listen queue for incoming TCP connections
for entire system
@@ -31,8 +31,8 @@ Mac OS X
Since Mac OS X is BSD-based system, most of the above hold for OS X as well.
However, launchd(8) is known to modify kern.maxfiles and kern.maxfilesperproc
-when it launches tor service (see launchd.plist(5) manpage). Also,
-kern.ipc.maxsockets is determined dynamically by the system and thus is
+when it launches tor service (see launchd.plist(5) manpage). Also,
+kern.ipc.maxsockets is determined dynamically by the system and thus is
read-only on OS X.
OpenBSD
@@ -79,8 +79,7 @@ Disclaimer
Do note that this document is a draft and above information may be
technically incorrect and/or incomplete. If so, please open a ticket
-on https://trac.torproject.org or post to tor-relays mailing list.
+on https://gitlab.torproject.org or post to tor-relays mailing list.
Are you running a busy Tor relay? Let us know how you are solving
the out-of-sockets problem on your system.
-
diff --git a/doc/include.am b/doc/include.am
index 8651f845eb..7a8a64ed16 100644
--- a/doc/include.am
+++ b/doc/include.am
@@ -12,7 +12,7 @@
# part of the source distribution, so that people without asciidoc can
# just use the .1 and .html files.
-all_mans = doc/tor doc/tor-gencert doc/tor-resolve doc/torify doc/tor-print-ed-signing-cert
+all_mans = doc/man/tor doc/man/tor-gencert doc/man/tor-resolve doc/man/torify doc/man/tor-print-ed-signing-cert
if USE_ASCIIDOC
txt_in = $(all_mans:=.1.txt)
@@ -52,7 +52,6 @@ EXTRA_DIST+= doc/asciidoc-helper.sh \
doc/HACKING/README.1st.md \
doc/HACKING/CodingStandards.md \
doc/HACKING/CodingStandardsRust.md \
- doc/HACKING/CodeStructure.md \
doc/HACKING/Fuzzing.md \
doc/HACKING/GettingStarted.md \
doc/HACKING/GettingStartedRust.md \
@@ -60,8 +59,9 @@ EXTRA_DIST+= doc/asciidoc-helper.sh \
doc/HACKING/HowToReview.md \
doc/HACKING/Module.md \
doc/HACKING/ReleasingTor.md \
- doc/HACKING/Tracing.md \
doc/HACKING/WritingTests.md
+ doc/HACKING/tracing/Tracing.md \
+ doc/HACKING/tracing/EventsCircuit.md
docdir = @docdir@
@@ -77,17 +77,17 @@ $(html_in) :
$(man_in) :
$(AM_V_GEN)$(top_srcdir)/doc/asciidoc-helper.sh man @A2X@ $(top_srcdir)/$@
-doc/tor.1.in: doc/tor.1.txt
-doc/torify.1.in: doc/torify.1.txt
-doc/tor-gencert.1.in: doc/tor-gencert.1.txt
-doc/tor-resolve.1.in: doc/tor-resolve.1.txt
-doc/tor-print-ed-signing-cert.1.in: doc/tor-print-ed-signing-cert.1.txt
+doc/man/tor.1.in: doc/man/tor.1.txt
+doc/man/torify.1.in: doc/man/torify.1.txt
+doc/man/tor-gencert.1.in: doc/man/tor-gencert.1.txt
+doc/man/tor-resolve.1.in: doc/man/tor-resolve.1.txt
+doc/man/tor-print-ed-signing-cert.1.in: doc/man/tor-print-ed-signing-cert.1.txt
-doc/tor.html.in: doc/tor.1.txt
-doc/torify.html.in: doc/torify.1.txt
-doc/tor-gencert.html.in: doc/tor-gencert.1.txt
-doc/tor-resolve.html.in: doc/tor-resolve.1.txt
-doc/tor-print-ed-signing-cert.html.in: doc/tor-print-ed-signing-cert.1.txt
+doc/man/tor.html.in: doc/man/tor.1.txt
+doc/man/torify.html.in: doc/man/torify.1.txt
+doc/man/tor-gencert.html.in: doc/man/tor-gencert.1.txt
+doc/man/tor-resolve.html.in: doc/man/tor-resolve.1.txt
+doc/man/tor-print-ed-signing-cert.html.in: doc/man/tor-print-ed-signing-cert.1.txt
# use config.status to swap all machine-specific magic strings
# in the asciidoc with their replacements.
@@ -98,17 +98,17 @@ $(asciidoc_product) :
fi
$(AM_V_at)$(top_builddir)/config.status -q --file=$@;
-doc/tor.html: doc/tor.html.in
-doc/tor-gencert.html: doc/tor-gencert.html.in
-doc/tor-resolve.html: doc/tor-resolve.html.in
-doc/tor-print-ed-signing-cert.html: doc/tor-print-ed-signing-cert.html.in
-doc/torify.html: doc/torify.html.in
-
-doc/tor.1: doc/tor.1.in
-doc/tor-gencert.1: doc/tor-gencert.1.in
-doc/tor-resolve.1: doc/tor-resolve.1.in
-doc/tor-print-ed-signing-cert.1: doc/tor-print-ed-signing-cert.1.in
-doc/torify.1: doc/torify.1.in
+doc/man/tor.html: doc/man/tor.html.in
+doc/man/tor-gencert.html: doc/man/tor-gencert.html.in
+doc/man/tor-resolve.html: doc/man/tor-resolve.html.in
+doc/man/tor-print-ed-signing-cert.html: doc/man/tor-print-ed-signing-cert.html.in
+doc/man/torify.html: doc/man/torify.html.in
+
+doc/man/tor.1: doc/man/tor.1.in
+doc/man/tor-gencert.1: doc/man/tor-gencert.1.in
+doc/man/tor-resolve.1: doc/man/tor-resolve.1.in
+doc/man/tor-print-ed-signing-cert.1: doc/man/tor-print-ed-signing-cert.1.in
+doc/man/torify.1: doc/man/torify.1.in
CLEANFILES+= $(asciidoc_product)
DISTCLEANFILES+= $(html_in) $(man_in)
diff --git a/doc/tor-gencert.1.txt b/doc/man/tor-gencert.1.txt
index 26f68b29c0..9262c4a39a 100644
--- a/doc/tor-gencert.1.txt
+++ b/doc/man/tor-gencert.1.txt
@@ -6,7 +6,6 @@
:man manual: Tor Manual
tor-gencert(1)
==============
-Nick Mathewson
NAME
----
@@ -14,7 +13,7 @@ tor-gencert - Generate certs and keys for Tor directory authorities
SYNOPSIS
--------
-**tor-gencert** [-h|--help] [-v] [-r|--reuse] [--create-identity-key] [-i __id_file__] [-c
+**tor-gencert** [-h|--help] [-v] [-r|--reuse] [--create-identity-key] [-i __id_file__] [-c
__cert_file__] [-m __num__] [-a __address__:__port__]
DESCRIPTION
@@ -86,7 +85,3 @@ SEE ALSO
**tor**(1) +
See also the "dir-spec.txt" file, distributed with Tor.
-
-AUTHORS
--------
- Roger Dingledine <arma@mit.edu>, Nick Mathewson <nickm@alum.mit.edu>.
diff --git a/doc/tor-print-ed-signing-cert.1.txt b/doc/man/tor-print-ed-signing-cert.1.txt
index 71c8b67ec4..2ce10d7cbd 100644
--- a/doc/tor-print-ed-signing-cert.1.txt
+++ b/doc/man/tor-print-ed-signing-cert.1.txt
@@ -32,7 +32,3 @@ SEE ALSO
**tor**(1) +
https://spec.torproject.org/cert-spec
-
-AUTHORS
--------
-Roger Dingledine <arma@mit.edu>, Nick Mathewson <nickm@alum.mit.edu>.
diff --git a/doc/tor-resolve.1.txt b/doc/man/tor-resolve.1.txt
index 17a77e482f..c944d75650 100644
--- a/doc/tor-resolve.1.txt
+++ b/doc/man/tor-resolve.1.txt
@@ -48,7 +48,3 @@ SEE ALSO
**tor**(1), **torify**(1). +
For protocol details, see: https://spec.torproject.org/socks-extensions
-
-AUTHORS
--------
-Roger Dingledine <arma@mit.edu>, Nick Mathewson <nickm@alum.mit.edu>.
diff --git a/doc/tor.1.txt b/doc/man/tor.1.txt
index 3dc8c7a034..b57c6ec70a 100644
--- a/doc/tor.1.txt
+++ b/doc/man/tor.1.txt
@@ -97,11 +97,10 @@ The following options in this section are only recognized on the
[[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.
+[[opt-dump-config]] **`--dump-config`** **`short`**|**`full`**::
+ Write a 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.
+ are different from their default values
When `full` is selected, write every option.
[[opt-serviceinstall]] **`--service install`** [**`--options`** __command-line options__]::
@@ -151,7 +150,7 @@ The following options in this section are only recognized on the
+
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
+ master identity key. You will be prompted for the old passphrase
(if any), and the new passphrase (if any).
+
[NOTE]
@@ -175,16 +174,22 @@ The following options in this section are only recognized on the
If the file descriptor is not specified, the passphrase is read
from the terminal by default.
-[[opt-key-expiration]] **`--key-expiration`** [__purpose__]::
+[[opt-key-expiration]] **`--key-expiration`** [__purpose__] [**`--format`** **`iso8601`**|**`timestamp`**]::
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"
+ as to stdout. The optional **`--format`** argument lets you specify
+ the time format. Currently, **`iso8601`** and **`timestamp`** are
+ supported. If **`--format`** is not specified, the signing key
+ certificate's expiration time will be 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". If **`--format`** **`timestamp`**
+ is specified, the signing key certificate's expiration time will be in
+ Unix timestamp format. For example, the output sent to stdout will be of the form:
+ "signing-cert-expiry: 1500971415".
[[opt-dbg]] **--dbg-**...::
Tor may support other options beginning with the string "dbg". These
@@ -206,14 +211,22 @@ backslash character (\) before the end of the line. Comments can be used in
such multiline entries, but they must start at the beginning of a line.
Configuration options can be imported from files or folders using the %include
-option with the value being a path. If the path is a file, the options from the
-file will be parsed as if they were written where the %include option is. If
+option with the value being a path. This path can have wildcards. Wildcards are
+expanded first, then sorted using lexical order. Then, for each matching file or
+folder, the following rules are followed: if the path is a file, the options from
+the file will be parsed as if they were written where the %include option is. If
the path is a folder, all files on that folder will be parsed following lexical
-order. Files starting with a dot are ignored. Files on subfolders are ignored.
+order. Files starting with a dot are ignored. Files in subfolders are ignored.
The %include option can be used recursively.
New configuration files or directories cannot be added to already running Tor
instance if **Sandbox** is enabled.
+The supported wildcards are * meaning any number of characters including none
+and ? meaning exactly one character. These characters can be escaped by preceding
+them with a backslash, except on Windows. Files starting with a dot are not matched
+when expanding wildcards unless the starting dot is explicitly in the pattern, except
+on Windows.
+
By default, an option on the command line overrides an option found in the
configuration file, and an option in a configuration file overrides one in
the defaults file.
@@ -263,11 +276,6 @@ forward slash (/) in the configuration file and on the command line.
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
@@ -608,7 +616,7 @@ forward slash (/) in the configuration file and on the command line.
**DirCache** fetches and serves all documents except extrainfo
descriptors, **DownloadExtraInfo*** fetches extrainfo documents, and serves
them if **DirCache** is on, and **UseMicrodescriptors** changes the
- flavour of consensues and descriptors that is fetched and used for
+ flavor of consensuses and descriptors that is fetched and used for
building circuits. (Default: 0)
[[HardwareAccel]] **HardwareAccel** **0**|**1**::
@@ -675,7 +683,7 @@ forward slash (/) in the configuration file and on the command line.
Signal-safe logs are always sent to stderr or stdout. They are also sent to
a limited number of log files that are configured to log messages at error
severity from the bug or general domains. They are never sent as syslogs,
- android logs, control port log events, or to any API-based log
+ control port log events, or to any API-based log
destinations.
[[Log2]] **Log** __minSeverity__[-__maxSeverity__] **file** __FILENAME__::
@@ -736,6 +744,48 @@ forward slash (/) in the configuration file and on the command line.
total; this is intended to be used to debug problems without opening live
servers to resource exhaustion attacks. (Default: 10 MBytes)
+[[MetricsPort]] **MetricsPort** ['address'**:**]{empty}__port__ [__format__]::
+ WARNING: Before enabling this, it is important to understand that exposing
+ tor metrics publicly is dangerous to the Tor network users. Please take
+ extra precaution and care when opening this port. Set a very strict access
+ policy with MetricsPortPolicy and consider using your operating systems
+ firewall features for defense in depth.
+ +
+ We recommend, for the prometheus __format__, that the only address that
+ can access this port should be the Prometheus server itself. Remember that
+ the connection is unencrypted (HTTP) hence consider using a tool like
+ stunnel to secure the link from this port to the server.
+ +
+ If set, open this port to listen for an HTTP GET request to "/metrics".
+ Upon a request, the collected metrics in the the tor instance are
+ formatted for the given format and then sent back. If this is set,
+ MetricsPortPolicy must be defined else every request will be rejected.
+ +
+ Supported format is "prometheus" which is also the default if not set. The
+ Prometheus data model can be found here:
+ https://prometheus.io/docs/concepts/data_model/
+ +
+ The tor metrics are constantly collected and they solely consists of
+ counters. Thus, asking for those metrics is very lightweight on the tor
+ process. (Default: None)
+ +
+ As an example, here only 5.6.7.8 will be allowed to connect:
+
+ MetricsPort 1.2.3.4:9035
+ MetricsPortPolicy accept 5.6.7.8
+
+[[MetricsPortPolicy]] **MetricsPortPolicy** __policy__,__policy__,__...__::
+ Set an entrance policy for the **MetricsPort**, to limit who can access
+ it. The policies have the same form as exit policies below, except that
+ port specifiers are ignored. For multiple entries, this line can be used
+ multiple times. It is a reject all by default policy. (Default: None)
+ +
+ Please, keep in mind here that if the server collecting metrics on the
+ MetricsPort is behind a NAT, then everything behind it can access it. This
+ is similar for the case of allowing localhost, every users on the server
+ will be able to access it. Again, strongly consider using a tool like
+ stunnel to secure the link or to strengthen access control.
+
[[NoExec]] **NoExec** **0**|**1**::
If this option is set to 1, then Tor will never launch another
executable, regardless of the settings of ClientTransportPlugin
@@ -784,6 +834,17 @@ forward slash (/) in the configuration file and on the command line.
field, Tor will use it for separate rate limiting for each connection
from a non-relay. (Default: 0)
+[[OutboundBindAddressPT]] **OutboundBindAddressPT** __IP__::
+ Request that pluggable transports makes all outbound connections
+ originate from the IP address specified. Because outgoing connections
+ are handled by the pluggable transport itself, it is not possible for
+ Tor to enforce whether the pluggable transport honors this option. 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).
+
[[PidFile]] **PidFile** __FILE__::
On startup, write our PID to FILE. On clean shutdown, remove
FILE. Can not be changed while tor is running.
@@ -834,10 +895,11 @@ forward slash (/) in the configuration file and on the command line.
[[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. +
+ Otherwise the sandbox will be disabled. The option only works on
+ Linux-based operating systems, and only when Tor has been built with the
+ libseccomp library. Note that this option may be incompatible with some
+ versions of libc, and some kernel versions. 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:
@@ -1289,15 +1351,6 @@ The following options are useful only for clients (that is, if
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__ +
@@ -1744,8 +1797,9 @@ The following options are useful only for clients (that is, if
The default **VirtualAddrNetwork** address ranges on a
properly configured machine will route to the loopback or link-local
interface. The maximum number of bits for the network prefix is set to 104
- for IPv6 and 16 for IPv4. However, a wider network - smaller prefix length
- - is preferable since it reduces the chances for an attacker to guess the
+ for IPv6 and 16 for IPv4. However, a larger network
+ (that is, one with a smaller prefix length)
+ is preferable, since it reduces the chances for an attacker to guess the
used IP. For local use, no change to the default VirtualAddrNetwork setting
is needed.
@@ -1808,7 +1862,7 @@ The following options control when Tor enters and leaves dormant mode:
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
+ clicking on an application 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.)
@@ -1852,6 +1906,9 @@ different from other Tor clients:
option overrides this option; if you have configured bridges and
UseBridges is 1, the Bridges are used as your entry nodes. +
+
+ This option can appear multiple times: the values from multiple lines are
+ spliced together. +
+ +
The ExcludeNodes option overrides this option: any node listed in both
EntryNodes and ExcludeNodes is treated as excluded. See
<<ExcludeNodes,ExcludeNodes>> for more information on how to specify nodes.
@@ -1864,6 +1921,9 @@ different from other Tor clients:
(Example:
ExcludeNodes ABCD1234CDEF5678ABCD1234CDEF5678ABCD1234, \{cc}, 255.254.0.0/8) +
+
+ This option can appear multiple times: the values from multiple lines are
+ spliced together. +
+ +
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,
@@ -1889,13 +1949,19 @@ different from other Tor clients:
list too. See
<<ExcludeNodes,ExcludeNodes>> for more information on how to specify
nodes. See also the caveats on the <<ExitNodes,ExitNodes>> option below.
-
+ +
+ This option can appear multiple times: the values from multiple lines are
+ spliced together. +
+ +
[[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
<<ExcludeNodes,ExcludeNodes>> for more information on how to specify nodes. +
+
+ This option can appear multiple times: the values from multiple lines are
+ spliced together. +
+ +
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
@@ -1934,6 +2000,9 @@ different from other Tor clients:
(Example:
HSLayer2Nodes ABCD1234CDEF5678ABCD1234CDEF5678ABCD1234, \{cc}, 255.254.0.0/8) +
+
+ This option can appear multiple times: the values from multiple lines are
+ spliced together. +
+ +
When this is set, the resulting hidden service paths will
look like:
+
@@ -1990,6 +2059,9 @@ different from other Tor clients:
(Example:
HSLayer3Nodes ABCD1234CDEF5678ABCD1234CDEF5678ABCD1234, \{cc}, 255.254.0.0/8) +
+
+ This option can appear multiple times: the values from multiple lines are
+ spliced together. +
+ +
When this is set by itself, the resulting hidden service paths
will look like: +
C - G - M - L3 - Rend +
@@ -2036,12 +2108,15 @@ different from other Tor clients:
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. +
-+
+ to directory servers. Middle hops are all hops other than exit and entry.
+ +
+ This option can appear multiple times: the values from multiple lines are
+ spliced together. +
+ +
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.
+ without care will strongly influence your anonymity. Other tor features may
+ not work with MiddleNodes. 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
@@ -2139,12 +2214,22 @@ is non-zero):
binds to. To bind to a different address, use the ORPort and
OutboundBindAddress options.
+[[AddressDisableIPv6]] **AddressDisableIPv6** **0**|**1**::
+ By default, Tor will attempt to find the IPv6 of the relay if there is no
+ IPv4Only ORPort. If set, this option disables IPv6 auto discovery. This
+ disables IPv6 address resolution, IPv6 ORPorts, and IPv6 reachability
+ checks. Also, the relay won't publish an IPv6 ORPort in its
+ descriptor. (Default: 0)
+
[[AssumeReachable]] **AssumeReachable** **0**|**1**::
This option is used when bootstrapping a new Tor network. If set to 1,
don't do self-reachability testing; just upload your server descriptor
- immediately. If **AuthoritativeDirectory** is also set, this option
- instructs the dirserver to bypass remote reachability testing too and list
- all connected servers as running.
+ immediately. (Default: 0)
+
+[[AssumeReachableIPv6]] **AssumeReachableIPv6** **0**|**1**|**auto**::
+ Like **AssumeReachable**, but affects only the relay's own IPv6 ORPort.
+ If this value is set to "auto", then Tor will look at **AssumeReachable**
+ instead. (Default: auto)
[[BridgeRelay]] **BridgeRelay** **0**|**1**::
Sets the relay to act as a "bridge" with respect to relaying connections
@@ -3004,6 +3089,12 @@ on the public Tor network.
if there is some major bug in Ed25519 link authentication that causes us
to label all the relays as not Running. (Default: 1)
+[[AuthDirTestReachability]] **AuthDirTestReachability** **0**|**1**::
+ Authoritative directories only. If set to 1, then we periodically
+ check every relay we know about to see whether it is running.
+ If set to 0, we vote Running for every relay, and don't perform
+ these tests. (Default: 1)
+
[[BridgePassword]] **BridgePassword** __Password__::
If set, contains an HTTP authenticator that tells a bridge authority to
serve all requested bridge information. Used by the (only partially
@@ -3358,7 +3449,6 @@ The following options are used for running a testing Tor network.
DirAllowPrivateAddresses 1
EnforceDistinctSubnets 0
- AssumeReachable 1
AuthDirMaxServersPerAddr 0
ClientBootstrapConsensusAuthorityDownloadInitialDelay 0
ClientBootstrapConsensusFallbackDownloadInitialDelay 0
@@ -3735,9 +3825,11 @@ __DataDirectory__/**`approved-routers`**::
**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.
+ descriptors are accepted, but marked in the vote as not valid.
+ If it is **!badexit**, then the authority will vote for it to receive a
+ BadExit flag, indicating that it shouldn't be used for traffic leaving
+ the Tor network.
+ (Neither rejected nor invalid relays are included in the consensus.)
__DataDirectory__/**`v3-status-votes`**::
Only for v3 authoritative directory servers. This file contains status
@@ -3826,8 +3918,4 @@ https://spec.torproject.org. See also **torsocks**(1) and **torify**(1).
== BUGS
Because Tor is still under development, there may be plenty of bugs. Please
-report them at https://trac.torproject.org/.
-
-== AUTHORS
-
-Roger Dingledine [arma at mit.edu], Nick Mathewson [nickm at alum.mit.edu].
+report them at https://bugs.torproject.org/.
diff --git a/doc/torify.1.txt b/doc/man/torify.1.txt
index 716625f92d..46b13e18e5 100644
--- a/doc/torify.1.txt
+++ b/doc/man/torify.1.txt
@@ -34,7 +34,3 @@ different circuits.
SEE ALSO
--------
**tor**(1), **torsocks**(1)
-
-AUTHORS
--------
-Peter Palfrader and Jacob Appelbaum wrote this manual.
diff --git a/doc/state-contents.txt b/doc/state-contents.txt
index 44716efc0c..772e108377 100644
--- a/doc/state-contents.txt
+++ b/doc/state-contents.txt
@@ -14,6 +14,21 @@ Recognized fields are:
Time when this state file was written.
Given in ISO format (YYYY-MM-DD HH:MM:SS)
+
+ MinutesSinceUserActivity (integer)
+ Dormant (0, 1, or "auto")
+
+ These values are used to keep track of how long Tor has been idle,
+ for the purpose of becoming 'dormant' after a long period without
+ any user-initiated requests.
+
+ "MinutesSinceUserActivity" is the number of minutes since the last
+ time the user asked us to do something. It is set to zero if we're
+ dormant.
+
+ "Dormant" is 1 if Tor was dormant when it wrote its state file, 0 if
+ Tor was active, and "auto" if Tor was starting for the first time.
+
AccountingBytesReadInInterval (memory unit)
AccountingBytesWrittenInInterval (memory unit)
AccountingExpectedUsage (memory unit)
@@ -36,26 +51,6 @@ Recognized fields are:
BytesAtSoftLimit. If we hit the soft limit already, we did so at
SoftLimitHitAt.
- EntryGuard
- EntryGuardDownSince
- EntryGuardUnlistedSince
- EntryGuardAddedBy
-
- These lines form sections related to entry guards. Each section
- starts with a single EntryGuard line, and is then followed by
- information on the state of the Entry guard.
-
- The EntryGuard line contains a nickname, then an identity digest, of
- the guard.
-
- The EntryGuardDownSince and EntryGuardUnlistedSince lines are present
- if the entry guard is believed to be non-running or non-listed. If
- present, they contain a line in ISO format (YYYY-MM-DD HH:MM:SS).
-
- The EntryGuardAddedBy line is optional. It contains three
- space-separated fields: the identity of the entry guard, the version of
- Tor that added it, and the ISO time at which it was added.
-
TransportProxy
One or more of these may be present.
@@ -65,41 +60,183 @@ Recognized fields are:
this information to spawn pluggable transport listeners in the
same IP address and TCP port even after tor client restarts.
- BWHistoryReadEnds (ISO time)
- BWHistoryReadInterval (integer, number of seconds)
- BWHistoryReadValues (comma-separated list of integer)
- BWHistoryReadMaxima (comma-separated list of integer)
- BWHistoryWriteEnds
- BWHistoryWriteInterval
- BWHistoryWriteValues
- BWHistoryWriteMaxima
- BWHistoryDirReadEnds
- BWHistoryDirReadInterval
- BWHistoryDirReadValues
- BWHistoryDirReadMaxima
- BWHistoryDirWriteEnds
- BWHistoryDirWriteInterval
- BWHistoryDirWriteValues
- BWHistoryDirWriteMaxima
-
- These values record bandwidth history. The "Values" fields are a list, for
- some number of "Intervals", of the total amount read/written during that
- integer. The "Maxima" are the highest burst for each interval.
+ BWHistory___Ends (ISO time)
+ BWHistory___Interval (integer, number of seconds)
+ BWHistory___Values (comma-separated list of integer)
+ BWHistory___Maxima (comma-separated list of integer)
+
+ These values record bandwidth history. The "Values" fields are a list,
+ for some number of "Intervals", of the total amount read/written during
+ that integer. The "Maxima" are the highest burst for each interval.
Interval duration is set by the "Interval" field, in seconds. The
"Ends" field is the ending time of the last interval in each list.
- The *Read* and *Write* fields are the total amount read and
- written; the *DirRead* and *DirWrite* variants are for directory
- traffic only.
+ Recognized values for "___" are:
+ Read -- total bytes read
+ Write -- total bytes written
+ DirRead -- total bytes read for directory connections.
+ DirWrite -- total bytes written for directory connections.
+ IPv6Read -- total bytes read on IPv6 connections
+ IPv6Write -- total bytes written on IPv6 connections
LastRotatedOnionKey
The last time that we changed our onion key for a new one.
Given in ISO format (YYYY-MM-DD HH:MM:SS)
+ This field is used to ensure that onion key rotations happen with the
+ appropriate frequency.
+
TotalBuildTimes
CircuitBuildAbandonedCount
CircuitBuildTimeBin
- XXXX writeme.
+ These fields are used by the Circuit Build Timeout code, which
+ tries to learn what times are reasonable for circuit construction,
+ so that it can reject circuits that take too long to build.
+
+ CircuitBuildTimeBin is a count of circuits that were build
+ successfully in some timeframe. This entry can repeat; each of
+ these represents some bar on a histogram. The first integer is a
+ number of milliseconds; it tells the position of the center of the
+ histogram bin on the time axis. The second number is a count of
+ circuits in that bin.
+
+ CircuitBuildTimeAbandonedCount is a count of circuits that we
+ simply gave up on building because they were taking far too long.
+
+ TotalBuildTimes is the number of circuit build times that we
+ observed in order to build the above measurements fields. If it
+ reaches a cap, then older measurements get thrown away.
+
+ Guard [key=value] [key=value]...
+
+ Describes a single entry guard used by the client. Key=value
+ entries with unrecognized keys are persisted. Order is not
+ significant. For more information about terminology used here,
+ system, see guard-spec.txt in the tor specifications repository.
+
+ Recognized keys are:
+
+ in (string)
+
+ The name of a guard selection that this guard is in.
+
+ rsa_id (string)
+
+ RSA fingerprint of this guard, without spaces.
+
+ nickname (string)
+
+ Declared nickname of this guard.
+
+ sampled_on (Time in ISO YYYY-MM-DDTHH:MM:SS format)
+
+ When was this guard added to the Guard sample?
+
+ sampled_by (tor version)
+
+ Which version of Tor added this Guard to the sample?
+ (Used to help with debugging.)
+
+ sampled_idx (integer)
+
+ Index of this guard among sampled guards.
+
+ listed (boolean)
+
+ Did this guard appear in the most recent consensus?
+
+ unlisted_since (Time in ISO YYYY-MM-DDTHH:MM:SS format)
+
+ If this guard is not listed, when is the earliest
+ consensus in which we found it unlisted?
+
+ confirmed_on (Time in ISO YYYY-MM-DDTHH:MM:SS format)
+
+ When did this guard become confirmed?
+
+ confirmed_idx (integer)
+
+ Index of this guard among confirmed guards.
+
+ bridge_addr (address)
+
+ If this guard is a bridge, its current address.
+
+ pb_use_attempts
+ pb_use_successes
+ pb_circ_attempts
+ pb_successful_circuits_closed
+ pb_collapsed_circuits
+ pb_unusable_circuits
+ pb_timeouts
+
+ Used by the pathbias subsystem to keep a record of the
+ behavior of circuits built through this guard, in hopes of
+ detecting guards try to that interfere with traffic.
+
+ All of these fields are floating-point integers which
+ represent a count of circuits that have been trated in
+ various ways. These counts decay with time.
+
+ "use_attempts" is a count of the circuits that we've built
+ and tried to use for traffic.
+
+ "successful_circuits_closed" is a count of circuits that
+ have closed "naturally" without timeout or error.
+
+ "use_successes" is a count of circuits that we've sent
+ traffic on, and which closed "naturally" without timeout
+ or error.
+
+ "circ_attempts" is a count of circuits we've tried to
+ build through this guard.
+
+ "collapsed_circuits" is a count of circuits that failed
+ after having been built, but before sending traffic.
+
+ "unusable_circuits" is a count of circuits that we
+ built, but where streams or probes but which failed,
+ or which encountered questionable errors.
+
+ "timeouts" is a count of circuits that encountered a
+ timeout while we were building them.
+
+Obsolete fields include:
+
+ EntryGuard
+ EntryGuardDownSince
+ EntryGuardUnlistedSince
+ EntryGuardAddedBy
+
+ These lines formed sections related to entry guards. Each section
+ starts with a single EntryGuard line, and is then followed by
+ information on the state of the Entry guard.
+
+ The EntryGuard line contains a nickname, then an identity digest, of
+ the guard.
+
+ The EntryGuardDownSince and EntryGuardUnlistedSince lines are present
+ if the entry guard is believed to be non-running or non-listed. If
+ present, they contain a line in ISO format (YYYY-MM-DD HH:MM:SS).
+
+ The EntryGuardAddedBy line is optional. It contains three
+ space-separated fields: the identity of the entry guard, the version of
+ Tor that added it, and the ISO time at which it was added.
+
+ EntryGuardPathBias and EntryGuardPathUseBias are superseded by
+ the `pb_...` elements in the Guard flag, and served a similar purpose.
+
+ These entries have all been superseded by the Guard line type,
+ since Tor 0.3.0.1-alpha.
+
+ HidServRevCounter
+
+ It was once used to ensure that v3 onion service directory revision
+ numbers were strictly increasing; we now use an order-preserving
+ encryption scheme for that purpose.
+
+ This option could appear multiple times; each time it does, it
+ applies to a different hidden service.
diff --git a/doc/ticket40136 b/doc/ticket40136
new file mode 100644
index 0000000000..cd1c0682f6
--- /dev/null
+++ b/doc/ticket40136
@@ -0,0 +1,3 @@
+ o Documentation:
+ - Update doc/state-contents.txt to more accurately explain the
+ current contents of a Tor state file. Closes ticket 40136.
diff --git a/m4/pc_from_ucontext.m4 b/m4/pc_from_ucontext.m4
index 9b66bf752c..61d979622b 100644
--- a/m4/pc_from_ucontext.m4
+++ b/m4/pc_from_ucontext.m4
@@ -54,7 +54,7 @@ AC_DEFUN([AC_PC_FROM_UCONTEXT],
else
AC_CHECK_HEADERS(sys/ucontext.h) # ucontext on OS X 10.6 (at least)
fi
- AC_CHECK_HEADERS(cygwin/signal.h) # ucontext on cywgin
+ AC_CHECK_HEADERS(cygwin/signal.h) # ucontext on cygwin
AC_MSG_CHECKING([how to access the program counter from a struct ucontext])
pc_fields=" uc_mcontext.gregs[[REG_PC]]" # Solaris x86 (32 + 64 bit)
pc_fields="$pc_fields uc_mcontext.gregs[[REG_EIP]]" # Linux (i386)
diff --git a/m4/pkg.m4 b/m4/pkg.m4
index 12e9835fba..13e0550be4 100644
--- a/m4/pkg.m4
+++ b/m4/pkg.m4
@@ -53,7 +53,7 @@ fi[]dnl
# to PKG_CHECK_MODULES(), but does not set variables or print errors.
#
# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
-# only at the first occurence in configure.ac, so if the first place
+# only at the first occurrence in configure.ac, so if the first place
# it's called might be skipped (such as if it is within an "if", you
# have to call PKG_CHECK_EXISTS manually
# --------------------------------------------------------------
diff --git a/scripts/build/combine_libs b/scripts/build/combine_libs
new file mode 100755
index 0000000000..9c87f68248
--- /dev/null
+++ b/scripts/build/combine_libs
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+set -e
+
+TMPDIR="$(mktemp -d -t tor_lib_combining.XXXXXX)"
+ORIGDIR="$(pwd)"
+
+trap 'cd "$ORIGDIR" && rm -rf "$TMPDIR"' 0
+
+abspath() {
+ echo "$(cd "$(dirname "$1")">/dev/null && pwd)/$(basename "$1")"
+}
+
+TARGET=$(abspath "$1")
+
+#echo ORIGDIR="$ORIGDIR"
+#echo AR="$AR"
+#echo ARFLAGS="$AFLAGS"
+
+shift
+
+for input in "$@"; do
+ cd "$ORIGDIR"
+ abs=$(abspath "$input")
+ dir="$TMPDIR"/$(basename "$input" .a)
+ mkdir "$dir"
+ cd "$dir">/dev/null
+ "${AR:-ar}" x "$abs"
+done
+
+cd "$TMPDIR" >/dev/null
+#echo "${AR:-ar}" "${ARFLAGS:-cru}" library.tmp.a ./*/**
+"${AR:-ar}" "${ARFLAGS:-cru}" library.tmp.a ./*/**
+"${RANLIB:-ranlib}" library.tmp.a
+mv -f library.tmp.a "$TARGET"
diff --git a/scripts/ci/ci-driver.sh b/scripts/ci/ci-driver.sh
index 67a95a1f61..c07d99188b 100755
--- a/scripts/ci/ci-driver.sh
+++ b/scripts/ci/ci-driver.sh
@@ -461,7 +461,7 @@ fi
if [[ "${STEM}" = "yes" ]]; then
start_section "Stem"
if [[ "${TOR_VER_AT_LEAST_044}" = 'yes' ]]; then
- # XXXX This shold probably be part some test-stem make target.
+ # XXXX This should probably be part of some test-stem make target.
if runcmd timelimit -p -t 520 -s USR1 -T 30 -S ABRT \
python3 "${STEM_PATH}/run_tests.py" \
--tor src/app/tor \
diff --git a/scripts/codegen/fuzzing_include_am.py b/scripts/codegen/fuzzing_include_am.py
index ae50563074..b52b956f81 100755
--- a/scripts/codegen/fuzzing_include_am.py
+++ b/scripts/codegen/fuzzing_include_am.py
@@ -31,17 +31,18 @@ FUZZING_CFLAGS = \
FUZZING_LDFLAG = \
@TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) @TOR_LDFLAGS_libevent@
FUZZING_LIBS = \
- $(TOR_INTERNAL_TESTING_LIBS) \
+ src/test/libtor-testing.a \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \
@TOR_LIBEVENT_LIBS@ $(TOR_LIBS_CRYPTLIB) \
- @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@ \
+ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@ \
@TOR_SYSTEMD_LIBS@ \
@TOR_LZMA_LIBS@ \
- @TOR_ZSTD_LIBS@
+ @TOR_ZSTD_LIBS@ \
+ @TOR_TRACE_LIBS@
oss-fuzz-prereqs: \
- $(TOR_INTERNAL_TESTING_LIBS)
+ src/test/libtor-testing.a
noinst_HEADERS += \
src/test/fuzz/fuzzing.h
diff --git a/scripts/codegen/makedesc.py b/scripts/codegen/makedesc.py
index 48d1d31a02..5c59a52af1 100644
--- a/scripts/codegen/makedesc.py
+++ b/scripts/codegen/makedesc.py
@@ -70,19 +70,39 @@ i2d_RSAPublicKey.argtypes = [
i2d_RSAPublicKey.restype = ctypes.c_int
+HEADER = """\
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+"""
+
+FOOTER="""
+
+"""
+
def rsa_sign(msg, rsa):
- buf = ctypes.create_string_buffer(1024)
+ buf = ctypes.create_string_buffer(2048)
n = RSA_private_encrypt(len(msg), msg, buf, rsa, 1)
if n <= 0:
raise Exception()
return buf.raw[:n]
-def b64(x):
- x = base64.b64encode(x)
+def b64(x1):
+ x = binascii.b2a_base64(x1)
res = []
for i in xrange(0, len(x), 64):
- res.append(x[i:i+64]+"\n")
- return "".join(res)
+ res.append((x[i:i+64]).decode("ascii"))
+ return "\n".join(res)
def bio_extract(bio):
buf = ctypes.c_char_p()
@@ -100,18 +120,19 @@ def make_rsa_key(e=65537):
n = crypt.i2d_RSAPublicKey(rsa, ctypes.byref(pBuf))
s = buf.raw[:n]
digest = hashlib.sha1(s).digest()
+ pem = pem.decode("ascii")
return (rsa,pem,digest)
def makeEdSigningKeyCert(sk_master, pk_master, pk_signing, date,
includeSigning=False, certType=1):
assert len(pk_signing) == len(pk_master) == 32
- expiration = struct.pack("!L", date//3600)
+ expiration = struct.pack(b"!L", date//3600)
if includeSigning:
- extensions = "\x01\x00\x20\x04\x00%s"%(pk_master)
+ extensions = b"\x01\x00\x20\x04\x00%s"%(pk_master)
else:
- extensions = "\x00"
- signed = "\x01%s%s\x01%s%s" % (
- chr(certType), expiration, pk_signing, extensions)
+ extensions = b"\x00"
+ signed = b"\x01%s%s\x01%s%s" % (
+ bytes([certType]), expiration, pk_signing, extensions)
signature = ed25519_exts_ref.signatureWithESK(signed, sk_master, pk_master)
assert len(signature) == 64
return signed+signature
@@ -127,7 +148,7 @@ MAGIC2 = "<<<<<!#!#!#XYZZY#!#!#!>>>>>"
class OnDemandKeys(object):
def __init__(self, certDate=None):
if certDate is None:
- certDate = time.time() + 86400
+ certDate = int(time.time()) + 86400
self.certDate = certDate
self.rsa_id = None
self.rsa_onion_key = None
@@ -151,7 +172,7 @@ class OnDemandKeys(object):
@property
def RSA_FINGERPRINT_NOSPACE(self):
- return binascii.b2a_hex(self.RSA_ID_DIGEST).upper()
+ return binascii.b2a_hex(self.RSA_ID_DIGEST).upper().decode("ascii")
@property
def RSA_ONION_KEY(self):
@@ -162,7 +183,7 @@ class OnDemandKeys(object):
@property
def RSA_FINGERPRINT(self):
- hexdigest = self.RSA_FINGERPRINT_NOSPACEK
+ hexdigest = self.RSA_FINGERPRINT_NOSPACE
return " ".join(hexdigest[i:i+4] for i in range(0,len(hexdigest),4))
@property
@@ -178,7 +199,7 @@ class OnDemandKeys(object):
if self.ntor_sk is None:
self.ntor_sk = slownacl_curve25519.Private()
self.ntor_pk = self.ntor_sk.get_public()
- return base64.b64encode(self.ntor_pk.serialize())
+ return base64.b64encode(self.ntor_pk.serialize()).decode("ascii")
@property
def ED_CERT(self):
@@ -192,6 +213,11 @@ class OnDemandKeys(object):
return objwrap('ED25519 CERT', b64(self.ed_cert))
@property
+ def ED_IDENTITY(self):
+ self.ED_CERT
+ return binascii.b2a_base64(self.ed_id_pk).strip().decode("ascii")
+
+ @property
def NTOR_CROSSCERT(self):
if self.ntor_crosscert is None:
self.ED_CERT
@@ -199,7 +225,7 @@ class OnDemandKeys(object):
ed_privkey = self.ntor_sk.serialize() + os.urandom(32)
ed_pub0 = ed25519_exts_ref.publickeyFromESK(ed_privkey)
- sign = (ord(ed_pub0[31]) & 255) >> 7
+ sign = ((ed_pub0[31]) & 255) >> 7
self.ntor_crosscert = makeEdSigningKeyCert(self.ntor_sk.serialize() + os.urandom(32), ed_pub0, self.ed_id_pk, self.certDate, certType=10)
self.ntor_crosscert_sign = sign
@@ -234,18 +260,19 @@ class OnDemandKeys(object):
self.ED_CERT
signed_part = body[:idx+len("\nrouter-sig-ed25519 ")]
signed_part = "Tor router descriptor signature v1" + signed_part
- digest = hashlib.sha256(signed_part).digest()
+ digest = hashlib.sha256(signed_part.encode("utf-8")).digest()
ed_sig = ed25519_exts_ref.signatureWithESK(digest,
self.ed_signing_sk, self.ed_signing_pk)
- body = body.replace(MAGIC2, base64.b64encode(ed_sig).replace("=",""))
+ body = body.replace(MAGIC2, base64.b64encode(ed_sig).decode("ascii").replace("=",""))
+ self.RSA_IDENTITY
idx = body.rindex("\nrouter-signature")
end_of_sig = body.index("\n", idx+1)
signed_part = body[:end_of_sig+1]
- digest = hashlib.sha1(signed_part).digest()
+ digest = hashlib.sha1(signed_part.encode("utf-8")).digest()
assert len(digest) == 20
rsasig = rsa_sign(digest, self.rsa_id)
@@ -318,29 +345,42 @@ def emit_ri(name, body):
body = info.sign_desc(body)
print_c_string("EX_RI_%s"%name.upper(), body)
-def emit_ei(name, body):
+def emit_ei(name, body, fields):
info = OnDemandKeys()
body = body.format(d=info)
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(
+ print('ATTR_UNUSED static const char EX_EI_{NAME}_FP[] = "{d.RSA_FINGERPRINT_NOSPACE}";'.format(
d=info, NAME=name.upper()))
+ print("ATTR_UNUSED")
print_c_string("EX_EI_%s_KEY"%name.upper(), info.RSA_IDENTITY)
def analyze(s):
- fields = {}
- while s.startswith(":::"):
- first,s=s.split("\n", 1)
- m = re.match(r'^:::(\w+)=(.*)',first)
- if not m:
- raise ValueError(first)
- k,v = m.groups()
- fields[k] = v
- return fields, s
-
-def process_file(s):
- fields, s = analyze(s)
+ while s:
+ fields = {}
+ s_pre = s
+ while s.startswith(":::"):
+ first,s=s.split("\n", 1)
+ m = re.match(r'^:::(\w+)=(.*)',first)
+ if not m:
+ raise ValueError(first)
+ k,v = m.groups()
+ fields[k] = v
+ if "name" not in fields:
+ print(repr(s_pre))
+
+ idx = s.find(":::")
+ if idx != -1:
+ body = s[:idx].rstrip()
+ s = s[idx:]
+ else:
+ body = s.rstrip()
+ s = ""
+
+ yield (fields, body)
+
+def emit_entry(fields, s):
try:
name = fields['name']
tp = fields['type']
@@ -348,12 +388,21 @@ def process_file(s):
raise ValueError("missing required field")
if tp == 'ei':
- emit_ei(name, s)
+ emit_ei(name, s, fields)
elif tp == 'ri':
emit_ri(name, s)
else:
raise ValueError("unrecognized type")
+def process_file(s):
+ print("""\
+/* These entries are automatically generated by makedesc.py to make sure
+ * that their keys and signatures are right except when otherwise
+ * specified. */
+""")
+ for (fields, s) in analyze(s):
+ emit_entry(fields, s)
+
if __name__ == '__main__':
import sys
for fn in sys.argv[1:]:
diff --git a/scripts/git/git-install-tools.sh b/scripts/git/git-install-tools.sh
index ef8623a018..d74f8475af 100755
--- a/scripts/git/git-install-tools.sh
+++ b/scripts/git/git-install-tools.sh
@@ -3,7 +3,7 @@
SCRIPT_NAME=$(basename "$0")
SCRIPTS_DIR=$(dirname "$0")
-TOOL_NAMES=(push-all pull-all merge-forward list-tor-branches)
+TOOL_NAMES=(push-all pull-all merge-forward list-tor-branches resquash)
function usage()
{
@@ -146,7 +146,7 @@ if [[ $INSTALL_HOOKS = 1 ]]; then
note "Installing hooks"
for fn in "$SCRIPTS_DIR"/*.git-hook; do
name=$(basename "$fn")
- $RUN install --backup "$fn" "${HOOKS_DIR}/${name%.git-hook}"
+ $RUN install -b "$fn" "${HOOKS_DIR}/${name%.git-hook}"
done
fi
@@ -163,7 +163,7 @@ if [[ $INSTALL_TOOLS = 1 ]]; then
note "Copying scripts"
for tool in "${TOOL_NAMES[@]}"; do
- $RUN install --backup "${SCRIPTS_DIR}/git-${tool}.sh" "${TOR_DEVTOOLS_DIR}/"
+ $RUN install -b "${SCRIPTS_DIR}/git-${tool}.sh" "${TOR_DEVTOOLS_DIR}/"
done
fi
diff --git a/scripts/git/git-list-tor-branches.sh b/scripts/git/git-list-tor-branches.sh
index d6b30f064f..5a527ffc05 100755
--- a/scripts/git/git-list-tor-branches.sh
+++ b/scripts/git/git-list-tor-branches.sh
@@ -139,15 +139,12 @@ finish() {
branch maint-0.3.5
branch release-0.3.5
-branch maint-0.4.1
-branch release-0.4.1
-
-branch maint-0.4.2
-branch release-0.4.2
-
branch maint-0.4.3
branch release-0.4.3
+branch maint-0.4.4
+branch release-0.4.4
+
branch master
finish
diff --git a/scripts/git/git-pull-all.sh b/scripts/git/git-pull-all.sh
index 7f82eda296..52a5c6140c 100755
--- a/scripts/git/git-pull-all.sh
+++ b/scripts/git/git-pull-all.sh
@@ -181,6 +181,19 @@ function fetch_tor_github
fi
}
+# Fetch tor-gitlab pull requests. No arguments.
+function fetch_tor_gitlab
+{
+ local cmd="git fetch tor-gitlab"
+ printf " %s Fetching tor-gitlab..." "$MARKER"
+ 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 #
###############
@@ -189,6 +202,9 @@ function fetch_tor_github
goto_repo "$ORIGIN_PATH"
fetch_tor_github
+# Then tor-gitlab
+fetch_tor_gitlab
+
# Then, fetch the origin.
fetch_origin
diff --git a/scripts/git/git-resquash.sh b/scripts/git/git-resquash.sh
new file mode 100755
index 0000000000..e0f26ecdc4
--- /dev/null
+++ b/scripts/git/git-resquash.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# Provides a convenient alias for "git rebase -i --autosquash --keep-root"
+# on gits that have it, and a replacement on gits that don't.
+
+set -e
+
+PARENT="$1"
+
+if test "x$PARENT" = "x"; then
+ echo "You must specify the parent branch."
+ exit 1
+fi
+
+# Can we use git rebase --keep-base? Detect the git version to find out.
+GITVER=$(git version)
+if test "$(echo "$GITVER"|cut -d ' ' -f 1-2)" = "git version"; then
+ # --keep-base was added in git 2.24. Detect if we have that version.
+ GITVER=$(echo "$GITVER" | cut -d ' ' -f 3)
+ major=$(echo "$GITVER" | cut -d . -f 1)
+ minor=$(echo "$GITVER" | cut -d . -f 2)
+ if test "$major" -lt 2; then
+ USE_KEEP_BASE=0
+ elif test "$major" -eq 2 && test "$minor" -lt 24; then
+ USE_KEEP_BASE=0
+ else
+ USE_KEEP_BASE=1
+ fi
+else
+ # This isn't a git that reports its version in a way recognize; assume that
+ # --keep-base will work
+ USE_KEEP_BASE=1
+fi
+
+if test "x$USE_KEEP_BASE" = "x1" ; then
+ exec git rebase -i --autosquash --keep-base "${PARENT}"
+else
+ REV=$(git log --reverse --format='%H' "${PARENT}..HEAD" | head -1)
+
+ if test "x${REV}" = "x"; then
+ echo "No changes here since ${PARENT}"
+ exit 1
+ fi
+
+ exec git rebase -i --autosquash "${REV}^"
+fi
diff --git a/scripts/git/git-setup-dirs.sh b/scripts/git/git-setup-dirs.sh
index 1f61eb8b83..5a9ae41cbd 100755
--- a/scripts/git/git-setup-dirs.sh
+++ b/scripts/git/git-setup-dirs.sh
@@ -40,6 +40,10 @@ function usage()
echo " (current: $GITHUB_PULL)"
echo " TOR_GITHUB_PUSH: the tor-github remote push URL"
echo " (current: $GITHUB_PUSH)"
+ echo " TOR_GITLAB_PULL: the tor-gitlab remote pull URL"
+ echo " (current: $GITLAB_PULL)"
+ echo " TOR_GITLAB_PUSH: the tor-gitlab remote push URL"
+ echo " (current: $GITLAB_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"
@@ -83,6 +87,10 @@ fi
GITHUB_PULL=${TOR_GITHUB_PULL:-"https://github.com/torproject/tor.git"}
GITHUB_PUSH=${TOR_GITHUB_PUSH:-"No_Pushing_To_GitHub"}
+# GitLab repositories
+GITLAB_PULL=${TOR_GITLAB_PULL:-"https://gitlab.torproject.org/tpo/core/tor.git"}
+GITLAB_PUSH=${TOR_GITLAB_PUSH:-"No_Pushing_To_GitLab"}
+
##########################
# Git branches to manage #
##########################
@@ -343,6 +351,20 @@ function set_tor_github_pr_fetch_config
"refs/pull.*pr"
}
+# Set up the tor-github PR config, so tor-gitlab/mr/NNNN points to GitHub
+# MR NNNN. In some repositories, "/head" is optional.
+function set_tor_gitlab_mr_fetch_config
+{
+ # standard branches
+ replace_fetch_config tor-gitlab \
+ "+refs/heads/*:refs/remotes/tor-gitlab/*" \
+ "refs/heads"
+ # MRs
+ replace_fetch_config tor-gitlab \
+ "+refs/merge-requests/*/head:refs/remotes/tor-gitlab/mr/*" \
+ "refs/merge-requests.*mr"
+}
+
# Add a new worktree for branch at path.
# If the directory already exists: fail if $USE_EXISTING is 0, otherwise skip.
function add_worktree
@@ -471,6 +493,15 @@ set_tor_github_pr_fetch_config
# Now fetch them all
fetch_remote "tor-github"
+# GitLab remote
+printf "%s Setting up remote %s\\n" "$MARKER" "${BYEL}tor-gitlab${CNRM}"
+add_remote "tor-gitlab" "$GITLAB_PULL"
+set_remote_push "tor-gitlab" "$GITLAB_PUSH"
+# Add custom fetch for MRs
+set_tor_gitlab_mr_fetch_config
+# Now fetch them all
+fetch_remote "tor-gitlab"
+
# Extra remote
if [ "$TOR_EXTRA_REMOTE_NAME" ]; then
printf "%s Setting up remote %s\\n" "$MARKER" \
diff --git a/scripts/git/pre-commit.git-hook b/scripts/git/pre-commit.git-hook
index f630a242bd..75e5133a73 100755
--- a/scripts/git/pre-commit.git-hook
+++ b/scripts/git/pre-commit.git-hook
@@ -3,9 +3,14 @@
# To install this script, copy it to .git/hooks/pre-commit in local copy of
# tor git repo and make sure it has permission to execute.
#
-# This is pre-commit git hook script that prevents commiting your changeset if
+# This is pre-commit git hook script that prevents committing your changeset if
# it fails our code formatting, changelog entry formatting, module include
-# rules, or best practices tracker.
+# rules, etc...
+
+# Run only if this environment variable is set.
+if [ -z "$TOR_EXTRA_PRE_COMMIT_CHECKS" ]; then
+ exit 0
+fi
workdir=$(git rev-parse --show-toplevel)
@@ -49,13 +54,6 @@ 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
@@ -74,19 +72,11 @@ printf "Modified tor-owned source files:\\n%s\\n" "$CHECK_FILES"
perl scripts/maint/checkSpace.pl -C \
$CHECK_FILES
+# This makes sure that we are only including things we're allowed to include.
if test -e scripts/maint/practracker/includes.py; then
python scripts/maint/practracker/includes.py
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
-if [ -e "${PT_DIR}/practracker.py" ]; then
- if [ -e "${PT_DIR}/.enable_practracker_in_hooks" ]; then
- python3 "${PT_DIR}/practracker.py" "$workdir"
- fi
-fi
-
if [ -e scripts/coccinelle/check_cocci_parse.sh ]; then
# Run a verbose cocci parse check on the changed files
diff --git a/scripts/git/pre-push.git-hook b/scripts/git/pre-push.git-hook
index efa45b9860..f0a3a250ec 100755
--- a/scripts/git/pre-push.git-hook
+++ b/scripts/git/pre-push.git-hook
@@ -83,6 +83,7 @@ do
src/tools/*.[ch] \
)"
+ export TOR_EXTRA_PRE_COMMIT_CHECKS=1
# We want word splitting here, because file names are space
# separated
# shellcheck disable=SC2086
diff --git a/scripts/maint/annotate_ifdef_directives.py b/scripts/maint/annotate_ifdef_directives.py
index 9ca090d595..eeca0bbb17 100755
--- a/scripts/maint/annotate_ifdef_directives.py
+++ b/scripts/maint/annotate_ifdef_directives.py
@@ -70,7 +70,7 @@ LINE_OBVIOUSNESS_LIMIT = 4
# Maximum line width. This includes a terminating newline character.
#
# (This is the maximum before encoding, so that if the the operating system
-# uses multiple characers to encode newline, that's still okay.)
+# uses multiple characters to encode newline, that's still okay.)
LINE_WIDTH=80
class Problem(Exception):
diff --git a/scripts/maint/checkOptionDocs.pl.in b/scripts/maint/checkOptionDocs.pl.in
index 6533c762c5..bb8008c2e8 100644
--- a/scripts/maint/checkOptionDocs.pl.in
+++ b/scripts/maint/checkOptionDocs.pl.in
@@ -39,7 +39,7 @@ loadTorrc("@abs_top_srcdir@/src/config/torrc.sample.in", \%torrcSampleOptions);
# Try to figure out what's in the man page.
my $considerNextLine = 0;
-open(F, "@abs_top_srcdir@/doc/tor.1.txt") or die;
+open(F, "@abs_top_srcdir@/doc/man/tor.1.txt") or die;
while (<F>) {
if (m!^(?:\[\[([A-za-z0-9_]+)\]\] *)?\*\*([A-Za-z0-9_]+)\*\*!) {
$manPageOptions{$2} = 1;
diff --git a/scripts/maint/clang-format.sh b/scripts/maint/clang-format.sh
deleted file mode 100755
index 59832117b4..0000000000
--- a/scripts/maint/clang-format.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/sh
-# Copyright 2020, The Tor Project, Inc.
-# See LICENSE for licensing information.
-
-#
-# DO NOT COMMIT OR MERGE CODE THAT IS RUN THROUGH THIS TOOL YET.
-#
-# WE ARE STILL DISCUSSING OUR DESIRED STYLE AND ITERATING ON IT.
-# (12 Feb 2020)
-#
-
-# This script runs "clang-format" and "codetool" in sequence over each of
-# our source files, and replaces the original file only if it has changed.
-#
-# We can't just use clang-format -i, since we also want to use codetool to
-# reformat a few things back to how we want them, and we want avoid changing
-# the mtime on files that didn't actually change.
-
-set -e
-
-cd "$(dirname "$0")/../../src/"
-
-# Shellcheck complains that a for loop over find's output is unreliable,
-# since there might be special characters in the output. But we happen
-# to know that none of our C files have special characters or spaces in
-# their names, so this is safe.
-#
-# shellcheck disable=SC2044
-for fname in $(find lib core feature app test tools -name '[^.]*.[ch]'); do
- tmpfname="${fname}.clang_fmt.tmp"
- rm -f "${tmpfname}"
- clang-format --style=file "${fname}" > "${tmpfname}"
- ../scripts/maint/codetool.py "${tmpfname}"
- if cmp "${fname}" "${tmpfname}" >/dev/null 2>&1; then
- echo "No change in ${fname}"
- rm -f "${tmpfname}"
- else
- echo "Change in ${fname}"
- mv "${tmpfname}" "${fname}"
- fi
-done
diff --git a/scripts/maint/code-format.sh b/scripts/maint/code-format.sh
new file mode 100755
index 0000000000..d8f597d70d
--- /dev/null
+++ b/scripts/maint/code-format.sh
@@ -0,0 +1,232 @@
+#!/usr/bin/env bash
+# Copyright 2020, The Tor Project, Inc.
+# See LICENSE for licensing information.
+
+#
+# DO NOT COMMIT OR MERGE CODE THAT IS RUN THROUGH THIS TOOL YET.
+#
+# WE ARE STILL DISCUSSING OUR DESIRED STYLE AND ITERATING ON IT.
+# (12 Feb 2020)
+#
+
+# This script runs "clang-format" and "codetool" in sequence over each of its
+# arguments. It either replaces the original, or says whether anything has
+# changed, depending on its arguments.
+#
+# We can't just use clang-format directly, since we also want to use codetool
+# to reformat a few things back to how we want them, and we want avoid changing
+# the mtime on files that didn't actually change.
+#
+# Use "-i" to edit the file in-place.
+# Use "-c" to exit with a nonzero exit status if any file needs to change.
+# Use "-d" to emit diffs.
+#
+# The "-a" option tells us to run over every Tor source file.
+# The "-v" option tells us to be verbose.
+
+set -e
+
+ALL=0
+GITDIFF=0
+GITIDX=0
+DIFFMODE=0
+CHECKMODE=0
+CHANGEMODE=0
+
+SCRIPT_NAME=$(basename "$0")
+SCRIPT_DIR=$(dirname "$0")
+SRC_DIR="${SCRIPT_DIR}/../../src"
+
+function usage() {
+ echo "$SCRIPT_NAME [-h] [-c|-d|-i] [-v] [-a|-G|files...]"
+ echo
+ echo " flags:"
+ echo " -h: show this help text"
+ echo " -c: check whether files are correctly formatted"
+ echo " -d: print a diff for the changes that would be applied"
+ echo " -i: change files in-place"
+ echo " -a: run over all the C files in Tor"
+ echo " -v: verbose mode"
+ echo " -g: look at the files that have changed in git."
+ echo " -G: look at the files that are staged for the git commit."
+ echo
+ echo "EXAMPLES"
+ echo
+ echo " $SCRIPT_NAME -a -i"
+ echo " rewrite every file in place, whether it has changed or not."
+ echo " $SCRIPT_NAME -a -d"
+ echo " as above, but only display the changes."
+ echo " $SCRIPT_NAME -g -i"
+ echo " update every file that you have changed in the git working tree."
+ echo " $SCRIPT_NAME -G -c"
+ echo " exit with an error if any staged changes are not well-formatted."
+}
+
+FILEARGS_OK=1
+
+while getopts "acdgGhiv" opt; do
+ case "$opt" in
+ h) usage
+ exit 0
+ ;;
+ a) ALL=1
+ FILEARGS_OK=0
+ ;;
+ g) GITDIFF=1
+ FILEARGS_OK=0
+ ;;
+ G) GITIDX=1
+ FILEARGS_OK=0
+ ;;
+ c) CHECKMODE=1
+ ;;
+ d) DIFFMODE=1
+ ;;
+ i) CHANGEMODE=1
+ ;;
+ v) VERBOSE=1
+ ;;
+ *) echo
+ usage
+ exit 1
+ ;;
+ esac
+done
+# get rid of the flags; keep the filenames.
+shift $((OPTIND - 1))
+
+# Define a verbose function.
+if [[ $VERBOSE = 1 ]]; then
+ function note()
+ {
+ echo "$@"
+ }
+else
+ function note()
+ {
+ true
+ }
+fi
+
+# We have to be in at least one mode, or we can't do anything
+if [[ $CHECKMODE = 0 && $DIFFMODE = 0 && $CHANGEMODE = 0 ]]; then
+ echo "Nothing to do. You need to specify -c, -d, or -i."
+ echo "Try $SCRIPT_NAME -h for more information."
+ exit 0
+fi
+
+# We don't want to "give an error if anything would change" if we're
+# actually trying to change things.
+if [[ $CHECKMODE = 1 && $CHANGEMODE = 1 ]]; then
+ echo "It doesn't make sense to use -c and -i together."
+ exit 0
+fi
+# It doesn't make sense to look at "all files" and "git files"
+if [[ $((ALL + GITIDX + GITDIFF)) -gt 1 ]]; then
+ echo "It doesn't make sense to use more than one of -a, -g, or -G together."
+ exit 0
+fi
+
+if [[ $FILEARGS_OK = 1 ]]; then
+ # The filenames are on the command-line.
+ INPUTS=("${@}")
+else
+ if [[ "$#" != 0 ]]; then
+ echo "Can't use -a, -g, or -G with additional command-line arguments."
+ exit 1
+ fi
+fi
+
+if [[ $ALL = 1 ]]; then
+ # We're in "all" mode -- use find(1) to find the filenames.
+ mapfile -d '' INPUTS < <(find "${SRC_DIR}"/{lib,core,feature,app,test,tools} -name '[^.]*.[ch]' -print0)
+elif [[ $GITIDX = 1 ]]; then
+ # We're in "git index" mode -- use git diff --cached to find the filenames
+ # that are changing in the index, then strip out the ones that
+ # aren't C.
+ mapfile INPUTS < <(git diff --name-only --cached --diff-filter=AMCR | grep '\.[ch]$')
+elif [[ $GITDIFF = 1 ]]; then
+ # We are in 'git diff' mode -- we want everything that changed, including
+ # the index and the working tree.
+ #
+ # TODO: There might be a better way to do this.
+ mapfile INPUTS < <(git diff --name-only --cached --diff-filter=AMCR | grep '\.[ch]$'; git diff --name-only --diff-filter=AMCR | grep '\.[ch]$' )
+fi
+
+if [[ $GITIDX = 1 ]]; then
+ # If we're running in git mode, we need to stash all the changes that
+ # we don't want to look at. This is necessary even though we're only
+ # looking at the changed files, since we might have the file only
+ # partially staged.
+ note "Stashing unstaged changes"
+ git stash -q --keep-index
+ function restoregit() {
+ note "Restoring git state"
+ git stash pop -q
+ }
+else
+ function restoregit() {
+ true
+ }
+fi
+
+ANY_CHANGED=0
+
+tmpfname=""
+
+#
+# Set up a trap handler to make sure that on exit, we remove our
+# tmpfile and un-stash the git environment (if appropriate)
+#
+trap 'if [ -n "${tmpfname}" ]; then rm -f "${tmpfname}"; fi; restoregit' 0
+
+for fname in "${INPUTS[@]}"; do
+ note "Inspecting $fname..."
+ tmpfname="${fname}.$$.clang_fmt.tmp"
+ rm -f "${tmpfname}"
+ clang-format --style=file "${fname}" > "${tmpfname}"
+ "${SCRIPT_DIR}/codetool.py" "${tmpfname}"
+
+ changed=not_set
+
+ if [[ $DIFFMODE = 1 ]]; then
+ # If we're running diff for its output, we can also use it
+ # to compare the files.
+ if diff -u "${fname}" "${tmpfname}"; then
+ changed=0
+ else
+ changed=1
+ fi
+ else
+ # We aren't running diff, so we have to compare the files with cmp.
+ if cmp "${fname}" "${tmpfname}" >/dev/null 2>&1; then
+ changed=0
+ else
+ changed=1
+ fi
+ fi
+
+ if [[ $changed = 1 ]]; then
+ note "Found a change in $fname"
+ ANY_CHANGED=1
+
+ if [[ $CHANGEMODE = 1 ]]; then
+ mv "${tmpfname}" "${fname}"
+ fi
+ fi
+
+ rm -f "${tmpfname}"
+done
+
+exitcode=0
+
+if [[ $CHECKMODE = 1 ]]; then
+ if [[ $ANY_CHANGED = 1 ]]; then
+ note "Found at least one misformatted file; check failed"
+ exitcode=1
+ else
+ note "No changes found."
+ fi
+fi
+
+exit $exitcode
diff --git a/scripts/maint/codetool.py b/scripts/maint/codetool.py
index 725712c0cc..c6daf759f5 100755
--- a/scripts/maint/codetool.py
+++ b/scripts/maint/codetool.py
@@ -11,7 +11,7 @@
#
"""
- This program uses a set of plugable filters to inspect and transform
+ This program uses a set of pluggable filters to inspect and transform
our C code.
"""
diff --git a/scripts/maint/practracker/.enable_practracker_in_hooks b/scripts/maint/practracker/.enable_practracker_in_hooks
new file mode 100644
index 0000000000..a9e707f5da
--- /dev/null
+++ b/scripts/maint/practracker/.enable_practracker_in_hooks
@@ -0,0 +1 @@
+This file is present to tell our git hooks to run practracker on this branch.
diff --git a/scripts/maint/practracker/exceptions.txt b/scripts/maint/practracker/exceptions.txt
index 711ef67d36..cd2e613977 100644
--- a/scripts/maint/practracker/exceptions.txt
+++ b/scripts/maint/practracker/exceptions.txt
@@ -34,10 +34,10 @@
# Remember: It is better to fix the problem than to add a new exception!
problem file-size /src/app/config/config.c 7525
-problem include-count /src/app/config/config.c 80
+problem include-count /src/app/config/config.c 81
problem function-size /src/app/config/config.c:options_act() 381
problem function-size /src/app/config/config.c:options_validate_cb() 794
-problem function-size /src/app/config/config.c:options_init_from_torrc() 192
+problem function-size /src/app/config/config.c:options_init_from_torrc() 139
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
@@ -46,11 +46,11 @@ 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:port_parse_config() 435
problem function-size /src/app/config/config.c:parse_ports() 132
-problem function-size /src/app/config/resolve_addr.c:resolve_my_address() 191
-problem file-size /src/app/config/or_options_st.h 1050
-problem include-count /src/app/main/main.c 68
+problem function-size /src/app/config/resolve_addr.c:resolve_my_address_v4() 197
+problem file-size /src/app/config/or_options_st.h 1072
+problem include-count /src/app/main/main.c 71
problem function-size /src/app/main/main.c:dumpstats() 102
-problem function-size /src/app/main/main.c:tor_init() 101
+problem function-size /src/app/main/main.c:tor_init() 109
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
@@ -96,7 +96,7 @@ problem function-size /src/core/or/channeltls.c:channel_tls_process_authenticate
problem dependency-violation /src/core/or/channeltls.c 11
problem include-count /src/core/or/circuitbuild.c 53
problem function-size /src/core/or/circuitbuild.c:get_unique_circ_id_by_chan() 128
-problem function-size /src/core/or/circuitbuild.c:choose_good_exit_server_general() 206
+problem function-size /src/core/or/circuitbuild.c:choose_good_exit_server_general() 196
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
@@ -108,16 +108,16 @@ 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 3101
+problem file-size /src/core/or/circuitpadding.c 3183
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
+problem file-size /src/core/or/circuitpadding.h 832
problem function-size /src/core/or/circuitpadding_machines.c:circpad_machine_relay_hide_intro_circuits() 103
problem function-size /src/core/or/circuitpadding_machines.c:circpad_machine_client_hide_rend_circuits() 112
problem dependency-violation /src/core/or/circuitpadding_machines.c 1
problem function-size /src/core/or/circuitstats.c:circuit_build_times_parse_state() 123
problem dependency-violation /src/core/or/circuitstats.c 11
-problem file-size /src/core/or/circuituse.c 3195
+problem file-size /src/core/or/circuituse.c 3250
problem function-size /src/core/or/circuituse.c:circuit_is_acceptable() 128
problem function-size /src/core/or/circuituse.c:circuit_expire_building() 389
problem function-size /src/core/or/circuituse.c:circuit_log_ancient_one_hop_circuits() 126
@@ -145,8 +145,9 @@ problem function-size /src/core/or/connection_or.c:connection_or_group_set_badne
problem function-size /src/core/or/connection_or.c:connection_or_client_learned_peer_id() 142
problem dependency-violation /src/core/or/connection_or.c 21
problem dependency-violation /src/core/or/dos.c 6
+problem dependency-violation /src/core/or/extendinfo.c 6
problem dependency-violation /src/core/or/onion.c 2
-problem file-size /src/core/or/or.h 1105
+problem file-size /src/core/or/or.h 1150
problem include-count /src/core/or/or.h 48
problem dependency-violation /src/core/or/or.h 1
problem dependency-violation /src/core/or/or_periodic.c 1
@@ -188,7 +189,7 @@ problem function-size /src/feature/client/entrynodes.c:entry_guard_parse_from_st
problem file-size /src/feature/client/entrynodes.h 700
problem function-size /src/feature/client/transports.c:handle_proxy_line() 108
problem function-size /src/feature/client/transports.c:parse_method_line_helper() 110
-problem function-size /src/feature/client/transports.c:create_managed_proxy_environment() 111
+problem function-size /src/feature/client/transports.c:create_managed_proxy_environment() 140
problem function-size /src/feature/control/control.c:connection_control_process_inbuf() 113
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
@@ -198,9 +199,9 @@ problem function-size /src/feature/control/control_events.c:control_event_stream
problem include-count /src/feature/control/control_getinfo.c 56
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() 297
-problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_events() 234
+problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_events() 237
problem function-size /src/feature/dirauth/bwauth.c:dirserv_read_measured_bandwidths() 121
-problem file-size /src/feature/dirauth/dirvote.c 4734
+problem file-size /src/feature/dirauth/dirvote.c 4900
problem include-count /src/feature/dirauth/dirvote.c 55
problem function-size /src/feature/dirauth/dirvote.c:format_networkstatus_vote() 230
problem function-size /src/feature/dirauth/dirvote.c:networkstatus_compute_bw_weights_v10() 233
@@ -255,11 +256,11 @@ problem function-size /src/feature/nodelist/microdesc.c:microdesc_cache_rebuild(
problem include-count /src/feature/nodelist/networkstatus.c 65
problem function-size /src/feature/nodelist/networkstatus.c:networkstatus_check_consensus_signature() 175
problem function-size /src/feature/nodelist/networkstatus.c:networkstatus_set_current_consensus() 289
-problem function-size /src/feature/nodelist/node_select.c:router_pick_directory_server_impl() 122
+problem function-size /src/feature/nodelist/node_select.c:router_pick_directory_server_impl() 126
problem function-size /src/feature/nodelist/node_select.c:compute_weighted_bandwidths() 204
-problem function-size /src/feature/nodelist/node_select.c:router_pick_trusteddirserver_impl() 112
+problem function-size /src/feature/nodelist/node_select.c:router_pick_trusteddirserver_impl() 116
problem function-size /src/feature/nodelist/nodelist.c:compute_frac_paths_available() 190
-problem file-size /src/feature/nodelist/routerlist.c 3247
+problem file-size /src/feature/nodelist/routerlist.c 3350
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
@@ -323,3 +324,5 @@ 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 /src/core/or/trace_probes_circuit.c 1
+problem dependency-violation /src/core/or/trace_probes_circuit.h 1
diff --git a/scripts/maint/rename_c_identifier.py b/scripts/maint/rename_c_identifier.py
index 77802e10f3..8b286c1a28 100755
--- a/scripts/maint/rename_c_identifier.py
+++ b/scripts/maint/rename_c_identifier.py
@@ -153,7 +153,7 @@ This is an automated commit, generated by this command:
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.
+The committer should be sure to fix them up in a subsequent commit.
"""
return msg
@@ -239,7 +239,7 @@ def main(argv):
print("I require an even number of identifiers.", file=sys.stderr)
return 1
- if any_uncommitted_changes():
+ if args.commit and any_uncommitted_changes():
print("Uncommitted changes found. Not running.", file=sys.stderr)
return 1
diff --git a/src/app/app.md b/src/app/app.md
index 138e75b127..298bde75f5 100644
--- a/src/app/app.md
+++ b/src/app/app.md
@@ -4,3 +4,8 @@
The "app" directory has Tor's main entry point and configuration logic,
and is responsible for initializing and managing the other modules in
Tor.
+
+The modules in "app" are:
+
+ - \refdir{app/config} -- configuration and state for Tor
+ - \refdir{app/main} -- Top-level functions to invoke the rest or Tor.
diff --git a/src/app/config/app_config.md b/src/app/config/app_config.md
index b359ce77f6..96a55494ff 100644
--- a/src/app/config/app_config.md
+++ b/src/app/config/app_config.md
@@ -2,5 +2,4 @@
@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).
-
+[ticket 29211](https://bugs.torproject.org/tpo/core/tor/29211)
diff --git a/src/app/config/config.c b/src/app/config/config.c
index a0c188adc4..fa74907b3d 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -27,7 +27,7 @@
* <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.
- * <li>The manual in doc/tor.1.txt, to document what the new option
+ * <li>The manual in doc/man/tor.1.txt, to document what the new option
* is, and how it works.
* </ul>
*
@@ -91,6 +91,7 @@
#include "feature/dirclient/dirclient_modes.h"
#include "feature/hibernate/hibernate.h"
#include "feature/hs/hs_config.h"
+#include "feature/metrics/metrics.h"
#include "feature/nodelist/dirlist.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nickname.h"
@@ -140,6 +141,7 @@
#include "lib/meminfo/meminfo.h"
#include "lib/osinfo/uname.h"
+#include "lib/osinfo/libc.h"
#include "lib/process/daemon.h"
#include "lib/process/pidfile.h"
#include "lib/process/restrict.h"
@@ -313,7 +315,8 @@ static const config_var_t option_vars_[] = {
V(AccountingMax, MEMUNIT, "0 bytes"),
VAR("AccountingRule", STRING, AccountingRule_option, "max"),
V(AccountingStart, STRING, NULL),
- V(Address, STRING, NULL),
+ V(Address, LINELIST, NULL),
+ V(AddressDisableIPv6, BOOL, "0"),
OBSOLETE("AllowDotExit"),
OBSOLETE("AllowInvalidNodes"),
V(AllowNonRFC953Hostnames, BOOL, "0"),
@@ -323,6 +326,7 @@ static const config_var_t option_vars_[] = {
V(AlternateDirAuthority, LINELIST, NULL),
OBSOLETE("AlternateHSAuthority"),
V(AssumeReachable, BOOL, "0"),
+ V(AssumeReachableIPv6, AUTOBOOL, "auto"),
OBSOLETE("AuthDirBadDir"),
OBSOLETE("AuthDirBadDirCCs"),
V(AuthDirBadExit, LINELIST, NULL),
@@ -545,7 +549,7 @@ static const config_var_t option_vars_[] = {
V(LogTimeGranularity, MSEC_INTERVAL, "1 second"),
V(TruncateLogFile, BOOL, "0"),
V_IMMUTABLE(SyslogIdentityTag, STRING, NULL),
- V_IMMUTABLE(AndroidIdentityTag,STRING, NULL),
+ OBSOLETE("AndroidIdentityTag"),
V(LongLivedPorts, CSV,
"21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"),
VAR("MapAddress", LINELIST, AddressMap, NULL),
@@ -557,6 +561,8 @@ static const config_var_t option_vars_[] = {
OBSOLETE("MaxOnionsPending"),
V(MaxOnionQueueDelay, MSEC_INTERVAL, "1750 msec"),
V(MaxUnparseableDescSizeToLog, MEMUNIT, "10 MB"),
+ VPORT(MetricsPort),
+ V(MetricsPortPolicy, LINELIST, NULL),
VAR("MyFamily", LINELIST, MyFamily_lines, NULL),
V(NewCircuitPeriod, INTERVAL, "30 seconds"),
OBSOLETE("NamingAuthoritativeDirectory"),
@@ -577,6 +583,7 @@ static const config_var_t option_vars_[] = {
V(OutboundBindAddress, LINELIST, NULL),
V(OutboundBindAddressOR, LINELIST, NULL),
V(OutboundBindAddressExit, LINELIST, NULL),
+ V(OutboundBindAddressPT, LINELIST, NULL),
OBSOLETE("PathBiasDisableRate"),
V(PathBiasCircThreshold, INT, "-1"),
@@ -606,7 +613,7 @@ static const config_var_t option_vars_[] = {
V(TestingAuthKeySlop, INTERVAL, "3 hours"),
V(TestingSigningKeySlop, INTERVAL, "1 day"),
- V(OptimisticData, AUTOBOOL, "auto"),
+ OBSOLETE("OptimisticData"),
OBSOLETE("PortForwarding"),
OBSOLETE("PortForwardingHelper"),
OBSOLETE("PreferTunneledDirConns"),
@@ -1511,7 +1518,7 @@ compute_group_readable_flag(const char *datadir,
* the datadirectory */
return datadir_gr;
} else {
- /* The directores are different, so we default to "not group-readable" */
+ /* The directories are different, so we default to "not group-readable" */
return 0;
}
}
@@ -1735,8 +1742,8 @@ options_rollback_listener_transaction(listener_transaction_t *xn)
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);
+ log_notice(LD_NET, "Closing partially-constructed %s",
+ connection_describe(conn));
connection_close_immediate(conn);
connection_mark_for_close(conn);
});
@@ -2101,6 +2108,16 @@ options_act,(const or_options_t *old_options))
"in a non-anonymous mode. It will provide NO ANONYMITY.");
}
+ /* 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 "
+ "bind addresses: %s", msg);
+ tor_free(msg);
+ return -1;
+ // LCOV_EXCL_STOP
+ }
+
if (options->Bridges) {
mark_bridge_list();
for (cl = options->Bridges; cl; cl = cl->next) {
@@ -2262,16 +2279,6 @@ 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 "
- "bind addresses: %s", msg);
- tor_free(msg);
- return -1;
- // LCOV_EXCL_STOP
- }
-
config_maybe_load_geoip_files_(options, old_options);
if (geoip_is_loaded(AF_INET) && options->GeoIPExcludeUnknown) {
@@ -2465,6 +2472,8 @@ static const struct {
{ .name="--key-expiration",
.takes_argument=ARGUMENT_OPTIONAL,
.command=CMD_KEY_EXPIRATION },
+ { .name="--format",
+ .takes_argument=ARGUMENT_NECESSARY },
{ .name="--newpass" },
{ .name="--no-passphrase" },
{ .name="--passphrase-fd",
@@ -2722,6 +2731,140 @@ list_enabled_modules(void)
// test variants in test_parseconf.sh to no useful purpose.
}
+/** Prints compile-time and runtime library versions. */
+static void
+print_library_versions(void)
+{
+ printf("Tor version %s. \n", get_version());
+ printf("Library versions\tCompiled\t\tRuntime\n");
+ printf("Libevent\t\t%-15s\t\t%s\n",
+ tor_libevent_get_header_version_str(),
+ tor_libevent_get_version_str());
+#ifdef ENABLE_OPENSSL
+ printf("OpenSSL \t\t%-15s\t\t%s\n",
+ crypto_openssl_get_header_version_str(),
+ crypto_openssl_get_version_str());
+#endif
+#ifdef ENABLE_NSS
+ printf("NSS \t\t%-15s\t\t%s\n",
+ crypto_nss_get_header_version_str(),
+ crypto_nss_get_version_str());
+#endif
+ if (tor_compress_supports_method(ZLIB_METHOD)) {
+ printf("Zlib \t\t%-15s\t\t%s\n",
+ tor_compress_version_str(ZLIB_METHOD),
+ tor_compress_header_version_str(ZLIB_METHOD));
+ }
+ if (tor_compress_supports_method(LZMA_METHOD)) {
+ printf("Liblzma \t\t%-15s\t\t%s\n",
+ tor_compress_version_str(LZMA_METHOD),
+ tor_compress_header_version_str(LZMA_METHOD));
+ }
+ if (tor_compress_supports_method(ZSTD_METHOD)) {
+ printf("Libzstd \t\t%-15s\t\t%s\n",
+ tor_compress_version_str(ZSTD_METHOD),
+ tor_compress_header_version_str(ZSTD_METHOD));
+ }
+ if (tor_libc_get_name()) {
+ printf("%-7s \t\t%-15s\t\t%s\n",
+ tor_libc_get_name(),
+ tor_libc_get_header_version_str(),
+ tor_libc_get_version_str());
+ }
+ //TODO: Hex versions?
+}
+
+/** Handles the --no-passphrase command line option. */
+static int
+handle_cmdline_no_passphrase(tor_cmdline_mode_t command)
+{
+ if (command == CMD_KEYGEN) {
+ get_options_mutable()->keygen_force_passphrase = FORCE_PASSPHRASE_OFF;
+ return 0;
+ } else {
+ log_err(LD_CONFIG, "--no-passphrase specified without --keygen!");
+ return -1;
+ }
+}
+
+/** Handles the --format command line option. */
+static int
+handle_cmdline_format(tor_cmdline_mode_t command, const char *value)
+{
+ if (command == CMD_KEY_EXPIRATION) {
+ // keep the same order as enum key_expiration_format
+ const char *formats[] = { "iso8601", "timestamp" };
+ int format = -1;
+ for (unsigned i = 0; i < ARRAY_LENGTH(formats); i++) {
+ if (!strcmp(value, formats[i])) {
+ format = i;
+ break;
+ }
+ }
+
+ if (format < 0) {
+ log_err(LD_CONFIG, "Invalid --format value %s", escaped(value));
+ return -1;
+ } else {
+ get_options_mutable()->key_expiration_format = format;
+ }
+ return 0;
+ } else {
+ log_err(LD_CONFIG, "--format specified without --key-expiration!");
+ return -1;
+ }
+}
+
+/** Handles the --newpass command line option. */
+static int
+handle_cmdline_newpass(tor_cmdline_mode_t command)
+{
+ if (command == CMD_KEYGEN) {
+ get_options_mutable()->change_key_passphrase = 1;
+ return 0;
+ } else {
+ log_err(LD_CONFIG, "--newpass specified without --keygen!");
+ return -1;
+ }
+}
+
+/** Handles the --passphrase-fd command line option. */
+static int
+handle_cmdline_passphrase_fd(tor_cmdline_mode_t command, const char *value)
+{
+ if (get_options()->keygen_force_passphrase == FORCE_PASSPHRASE_OFF) {
+ log_err(LD_CONFIG, "--no-passphrase specified with --passphrase-fd!");
+ return -1;
+ } else if (command != CMD_KEYGEN) {
+ log_err(LD_CONFIG, "--passphrase-fd specified without --keygen!");
+ return -1;
+ } else {
+ int ok = 1;
+ long fd = tor_parse_long(value, 10, 0, INT_MAX, &ok, NULL);
+ if (fd < 0 || ok == 0) {
+ log_err(LD_CONFIG, "Invalid --passphrase-fd value %s", escaped(value));
+ return -1;
+ }
+ get_options_mutable()->keygen_passphrase_fd = (int)fd;
+ get_options_mutable()->use_keygen_passphrase_fd = 1;
+ get_options_mutable()->keygen_force_passphrase = FORCE_PASSPHRASE_ON;
+ return 0;
+ }
+}
+
+/** Handles the --master-key command line option. */
+static int
+handle_cmdline_master_key(tor_cmdline_mode_t command, const char *value)
+{
+ if (command != CMD_KEYGEN) {
+ log_err(LD_CONFIG, "--master-key without --keygen!");
+ return -1;
+ } else {
+ get_options_mutable()->master_key_fname = tor_strdup(value);
+ return 0;
+ }
+}
+
/* Return true if <b>options</b> is using the default authorities, and false
* if any authority-related option has been overridden. */
int
@@ -2771,10 +2914,6 @@ options_dump(const or_options_t *options, int how_to_dump)
use_defaults = global_default_options;
minimal = 1;
break;
- case OPTIONS_DUMP_DEFAULTS:
- use_defaults = NULL;
- minimal = 1;
- break;
case OPTIONS_DUMP_ALL:
use_defaults = NULL;
minimal = 0;
@@ -3229,6 +3368,10 @@ options_validate_cb(const void *old_options_, void *options_, char **msg)
REJECT("TokenBucketRefillInterval must be between 1 and 1000 inclusive.");
}
+ if (options->AssumeReachable && options->AssumeReachableIPv6 == 0) {
+ REJECT("Cannot set AssumeReachable 1 and AssumeReachableIPv6 0.");
+ }
+
if (options->ExcludeExitNodes || options->ExcludeNodes) {
options->ExcludeExitNodesUnion_ = routerset_new();
routerset_union(options->ExcludeExitNodesUnion_,options->ExcludeExitNodes);
@@ -3453,7 +3596,7 @@ options_validate_cb(const void *old_options_, void *options_, char **msg)
"configured. This is bad because it's very easy to locate your "
"entry guard which can then lead to the deanonymization of your "
"hidden service -- for more details, see "
- "https://trac.torproject.org/projects/tor/ticket/14917. "
+ "https://bugs.torproject.org/tpo/core/tor/14917. "
"For this reason, the use of one EntryNodes with an hidden "
"service is prohibited until a better solution is found.");
return -1;
@@ -3470,7 +3613,7 @@ options_validate_cb(const void *old_options_, void *options_, char **msg)
"be harmful to the service anonymity. Because of this, we "
"recommend you either don't do that or make sure you know what "
"you are doing. For more details, please look at "
- "https://trac.torproject.org/projects/tor/ticket/21155.");
+ "https://bugs.torproject.org/tpo/core/tor/21155.");
}
/* Single Onion Services: non-anonymous hidden services */
@@ -4045,7 +4188,7 @@ options_check_transition_cb(const void *old_,
if (! CFG_EQ_INT(old, new_val, opt)) \
BAD_CHANGE_TO(opt," with Sandbox active")
- SB_NOCHANGE_STR(Address);
+ SB_NOCHANGE_LINELIST(Address);
SB_NOCHANGE_STR(ServerDNSResolvConfFile);
SB_NOCHANGE_STR(DirPortFrontPage);
SB_NOCHANGE_STR(CookieAuthFile);
@@ -4351,37 +4494,7 @@ options_init_from_torrc(int argc, char **argv)
}
if (config_line_find(cmdline_only_options, "--library-versions")) {
- printf("Tor version %s. \n", get_version());
- printf("Library versions\tCompiled\t\tRuntime\n");
- printf("Libevent\t\t%-15s\t\t%s\n",
- tor_libevent_get_header_version_str(),
- tor_libevent_get_version_str());
-#ifdef ENABLE_OPENSSL
- printf("OpenSSL \t\t%-15s\t\t%s\n",
- crypto_openssl_get_header_version_str(),
- crypto_openssl_get_version_str());
-#endif
-#ifdef ENABLE_NSS
- printf("NSS \t\t%-15s\t\t%s\n",
- crypto_nss_get_header_version_str(),
- crypto_nss_get_version_str());
-#endif
- if (tor_compress_supports_method(ZLIB_METHOD)) {
- printf("Zlib \t\t%-15s\t\t%s\n",
- tor_compress_version_str(ZLIB_METHOD),
- tor_compress_header_version_str(ZLIB_METHOD));
- }
- if (tor_compress_supports_method(LZMA_METHOD)) {
- printf("Liblzma \t\t%-15s\t\t%s\n",
- tor_compress_version_str(LZMA_METHOD),
- tor_compress_header_version_str(LZMA_METHOD));
- }
- if (tor_compress_supports_method(ZSTD_METHOD)) {
- printf("Libzstd \t\t%-15s\t\t%s\n",
- tor_compress_version_str(ZSTD_METHOD),
- tor_compress_header_version_str(ZSTD_METHOD));
- }
- //TODO: Hex versions?
+ print_library_versions();
return 1;
}
@@ -4395,10 +4508,7 @@ options_init_from_torrc(int argc, char **argv)
cf = tor_strdup("");
} else {
cf_defaults = load_torrc_from_disk(cmdline_only_options, 1);
-
- const config_line_t *f_line = config_line_find(cmdline_only_options,
- "-f");
-
+ const config_line_t *f_line = config_line_find(cmdline_only_options, "-f");
const int read_torrc_from_stdin =
(f_line != NULL && strcmp(f_line->value, "-") == 0);
@@ -4419,74 +4529,54 @@ options_init_from_torrc(int argc, char **argv)
retval = options_init_from_string(cf_defaults, cf, command, command_arg,
&errmsg);
-
if (retval < 0)
goto err;
if (config_line_find(cmdline_only_options, "--no-passphrase")) {
- if (command == CMD_KEYGEN) {
- get_options_mutable()->keygen_force_passphrase = FORCE_PASSPHRASE_OFF;
- } else {
- log_err(LD_CONFIG, "--no-passphrase specified without --keygen!");
+ if (handle_cmdline_no_passphrase(command) < 0) {
retval = -1;
goto err;
}
}
+ const config_line_t *format_line = config_line_find(cmdline_only_options,
+ "--format");
+ if (format_line) {
+ if (handle_cmdline_format(command, format_line->value) < 0) {
+ retval = -1;
+ goto err;
+ }
+ } else {
+ get_options_mutable()->key_expiration_format =
+ KEY_EXPIRATION_FORMAT_ISO8601;
+ }
+
if (config_line_find(cmdline_only_options, "--newpass")) {
- if (command == CMD_KEYGEN) {
- get_options_mutable()->change_key_passphrase = 1;
- } else {
- log_err(LD_CONFIG, "--newpass specified without --keygen!");
+ if (handle_cmdline_newpass(command) < 0) {
retval = -1;
goto err;
}
}
- {
- const config_line_t *fd_line = config_line_find(cmdline_only_options,
- "--passphrase-fd");
- if (fd_line) {
- if (get_options()->keygen_force_passphrase == FORCE_PASSPHRASE_OFF) {
- log_err(LD_CONFIG, "--no-passphrase specified with --passphrase-fd!");
- retval = -1;
- goto err;
- } else if (command != CMD_KEYGEN) {
- log_err(LD_CONFIG, "--passphrase-fd specified without --keygen!");
- retval = -1;
- goto err;
- } else {
- const char *v = fd_line->value;
- int ok = 1;
- long fd = tor_parse_long(v, 10, 0, INT_MAX, &ok, NULL);
- if (fd < 0 || ok == 0) {
- log_err(LD_CONFIG, "Invalid --passphrase-fd value %s", escaped(v));
- retval = -1;
- goto err;
- }
- get_options_mutable()->keygen_passphrase_fd = (int)fd;
- get_options_mutable()->use_keygen_passphrase_fd = 1;
- get_options_mutable()->keygen_force_passphrase = FORCE_PASSPHRASE_ON;
- }
+ const config_line_t *fd_line = config_line_find(cmdline_only_options,
+ "--passphrase-fd");
+ if (fd_line) {
+ if (handle_cmdline_passphrase_fd(command, fd_line->value) < 0) {
+ retval = -1;
+ goto err;
}
}
- {
- const config_line_t *key_line = config_line_find(cmdline_only_options,
- "--master-key");
- if (key_line) {
- if (command != CMD_KEYGEN) {
- log_err(LD_CONFIG, "--master-key without --keygen!");
- retval = -1;
- goto err;
- } else {
- get_options_mutable()->master_key_fname = tor_strdup(key_line->value);
- }
+ const config_line_t *key_line = config_line_find(cmdline_only_options,
+ "--master-key");
+ if (key_line) {
+ if (handle_cmdline_master_key(command, key_line->value) < 0) {
+ retval = -1;
+ goto err;
}
}
err:
-
tor_free(cf);
tor_free(cf_defaults);
if (errmsg) {
@@ -4848,15 +4938,19 @@ options_init_logs(const or_options_t *old_options, const or_options_t *options,
goto cleanup;
}
+ /* We added this workaround in 0.4.5.x; we can remove it in 0.4.6 or
+ * later */
if (!strcasecmp(smartlist_get(elts, 0), "android")) {
-#ifdef HAVE_ANDROID_LOG_H
+#ifdef HAVE_SYSLOG_H
+ log_warn(LD_CONFIG, "The android logging API is no longer supported;"
+ " adding a syslog instead. The 'android' logging "
+ " type will no longer work in the future.");
if (!validate_only) {
- add_android_log(severity, options->AndroidIdentityTag);
+ add_syslog_log(severity, options->SyslogIdentityTag);
}
#else
- log_warn(LD_CONFIG, "Android logging is not supported"
- " on this system. Sorry.");
-#endif /* defined(HAVE_ANDROID_LOG_H) */
+ log_warn(LD_CONFIG, "The android logging API is no longer supported.");
+#endif
goto cleanup;
}
}
@@ -5778,9 +5872,9 @@ warn_client_dns_cache(const char *option, int disabling)
return;
warn_deprecated_option(option,
- "Client-side DNS cacheing enables a wide variety of route-"
+ "Client-side DNS caching enables a wide variety of route-"
"capture attacks. If a single bad exit node lies to you about "
- "an IP address, cacheing that address would make you visit "
+ "an IP address, caching that address would make you visit "
"an address of the attacker's choice every time you connected "
"to your destination.");
}
@@ -5839,6 +5933,14 @@ port_parse_config(smartlist_t *out,
int got_zero_port=0, got_nonzero_port=0;
char *unix_socket_path = NULL;
port_cfg_t *cfg = NULL;
+ bool addr_is_explicit = false;
+ tor_addr_t default_addr = TOR_ADDR_NULL;
+
+ /* Parse default address. This can fail for Unix socket so the default_addr
+ * will simply be made UNSPEC. */
+ if (defaultaddr) {
+ tor_addr_parse(&default_addr, defaultaddr);
+ }
/* If there's no FooPort, then maybe make a default one. */
if (! ports) {
@@ -5915,8 +6017,7 @@ port_parse_config(smartlist_t *out,
port = 1;
} else if (!strcasecmp(addrport, "auto")) {
port = CFG_AUTO_PORT;
- int af = tor_addr_parse(&addr, defaultaddr);
- tor_assert(af >= 0);
+ tor_addr_copy(&addr, &default_addr);
} else if (!strcasecmpend(addrport, ":auto")) {
char *addrtmp = tor_strndup(addrport, strlen(addrport)-5);
port = CFG_AUTO_PORT;
@@ -5932,14 +6033,15 @@ port_parse_config(smartlist_t *out,
"9050" might be a valid address. */
port = (int) tor_parse_long(addrport, 10, 0, 65535, &ok, NULL);
if (ok) {
- int af = tor_addr_parse(&addr, defaultaddr);
- tor_assert(af >= 0);
+ tor_addr_copy(&addr, &default_addr);
+ addr_is_explicit = false;
} else if (tor_addr_port_lookup(addrport, &addr, &ptmp) == 0) {
if (ptmp == 0) {
log_warn(LD_CONFIG, "%sPort line has address but no port", portname);
goto err;
}
port = ptmp;
+ addr_is_explicit = true;
} else {
log_warn(LD_CONFIG, "Couldn't parse address %s for %sPort",
escaped(addrport), portname);
@@ -5950,6 +6052,7 @@ port_parse_config(smartlist_t *out,
/* Default port_cfg_t object initialization */
cfg = port_cfg_new(unix_socket_path ? strlen(unix_socket_path) : 0);
+ cfg->explicit_addr = addr_is_explicit;
if (unix_socket_path && default_to_group_writable)
cfg->is_group_writable = 1;
@@ -5992,15 +6095,25 @@ port_parse_config(smartlist_t *out,
}
if (cfg->server_cfg.bind_ipv4_only &&
tor_addr_family(&addr) != AF_INET) {
- log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv4",
- portname);
- goto err;
+ if (cfg->explicit_addr) {
+ log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv4",
+ portname);
+ goto err;
+ }
+ /* This ORPort is IPv4Only but the default address is IPv6, ignore it
+ * since this will be configured with an IPv4 default address. */
+ goto ignore;
}
if (cfg->server_cfg.bind_ipv6_only &&
tor_addr_family(&addr) != AF_INET6) {
- log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv6",
- portname);
- goto err;
+ if (cfg->explicit_addr) {
+ log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv6",
+ portname);
+ goto err;
+ }
+ /* This ORPort is IPv6Only but the default address is IPv4, ignore it
+ * since this will be configured with an IPv6 default address. */
+ goto ignore;
}
} else {
/* This is a client port; parse isolation options */
@@ -6213,9 +6326,10 @@ port_parse_config(smartlist_t *out,
smartlist_add(out, cfg);
/* out owns cfg now, don't re-use or free it */
cfg = NULL;
- } else {
- tor_free(cfg);
}
+
+ ignore:
+ tor_free(cfg);
SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
smartlist_clear(elts);
tor_free(addrport);
@@ -6343,6 +6457,10 @@ parse_ports(or_options_t *options, int validate_only,
*msg = tor_strdup("Invalid HTTPTunnelPort configuration");
goto err;
}
+ if (metrics_parse_ports(options, ports, msg) < 0) {
+ goto err;
+ }
+
{
unsigned control_port_flags = CL_PORT_NO_STREAM_OPTIONS |
CL_PORT_WARN_NONLOCAL;
@@ -6512,48 +6630,57 @@ get_first_listener_addrport_string(int listener_type)
return NULL;
}
-/** Return the first advertised port of type <b>listener_type</b> in
- * <b>address_family</b>. Returns 0 when no port is found, and when passed
- * AF_UNSPEC. */
-int
-get_first_advertised_port_by_type_af(int listener_type, int address_family)
+/** Find and return the first configured advertised `port_cfg_t` of type @a
+ * listener_type in @a address_family. */
+static const port_cfg_t *
+portconf_get_first_advertised(int listener_type, int address_family)
{
+ const port_cfg_t *first_port = NULL;
+ const port_cfg_t *first_port_explicit_addr = NULL;
+
if (address_family == AF_UNSPEC)
- return 0;
+ return NULL;
const smartlist_t *conf_ports = get_configured_ports();
SMARTLIST_FOREACH_BEGIN(conf_ports, const port_cfg_t *, cfg) {
- if (cfg->type == listener_type &&
- !cfg->server_cfg.no_advertise) {
+ if (cfg->type == listener_type && !cfg->server_cfg.no_advertise) {
if ((address_family == AF_INET && port_binds_ipv4(cfg)) ||
(address_family == AF_INET6 && port_binds_ipv6(cfg))) {
- return cfg->port;
+ if (cfg->explicit_addr && !first_port_explicit_addr) {
+ first_port_explicit_addr = cfg;
+ } else if (!first_port) {
+ first_port = cfg;
+ }
}
}
} SMARTLIST_FOREACH_END(cfg);
- return 0;
+
+ /* Prefer the port with the explicit address if any. */
+ return (first_port_explicit_addr) ? first_port_explicit_addr : first_port;
+}
+
+/** Return the first advertised port of type <b>listener_type</b> in
+ * <b>address_family</b>. Returns 0 when no port is found, and when passed
+ * AF_UNSPEC. */
+int
+portconf_get_first_advertised_port(int listener_type, int address_family)
+{
+ const port_cfg_t *cfg;
+ cfg = portconf_get_first_advertised(listener_type, address_family);
+
+ return cfg ? cfg->port : 0;
}
/** Return the first advertised address of type <b>listener_type</b> in
* <b>address_family</b>. Returns NULL if there is no advertised address,
* and when passed AF_UNSPEC. */
const tor_addr_t *
-get_first_advertised_addr_by_type_af(int listener_type, int address_family)
+portconf_get_first_advertised_addr(int listener_type, int address_family)
{
- if (address_family == AF_UNSPEC)
- return NULL;
- if (!configured_ports)
- return NULL;
- SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) {
- if (cfg->type == listener_type &&
- !cfg->server_cfg.no_advertise) {
- if ((address_family == AF_INET && port_binds_ipv4(cfg)) ||
- (address_family == AF_INET6 && port_binds_ipv6(cfg))) {
- return &cfg->addr;
- }
- }
- } SMARTLIST_FOREACH_END(cfg);
- return NULL;
+ const port_cfg_t *cfg;
+ cfg = portconf_get_first_advertised(listener_type, address_family);
+
+ return cfg ? &cfg->addr : NULL;
}
/** Return 1 if a port exists of type <b>listener_type</b> on <b>addr</b> and
@@ -6883,7 +7010,7 @@ options_get_dir_fname2_suffix,(const or_options_t *options,
return fname;
}
-/** Check wether the data directory has a private subdirectory
+/** Check whether the data directory has a private subdirectory
* <b>subdir</b>. If not, try to create it. Return 0 on success,
* -1 otherwise. */
int
@@ -7066,7 +7193,8 @@ parse_outbound_address_lines(const config_line_t *lines, outbound_addr_t type,
"configured: %s",
family==AF_INET?" IPv4":(family==AF_INET6?" IPv6":""),
type==OUTBOUND_ADDR_OR?" OR":
- (type==OUTBOUND_ADDR_EXIT?" exit":""), lines->value);
+ (type==OUTBOUND_ADDR_EXIT?" exit":
+ (type==OUTBOUND_ADDR_PT?" PT":"")), lines->value);
return -1;
}
lines = lines->next;
@@ -7089,7 +7217,7 @@ parse_outbound_addresses(or_options_t *options, int validate_only, char **msg)
}
if (parse_outbound_address_lines(options->OutboundBindAddress,
- OUTBOUND_ADDR_EXIT_AND_OR, options,
+ OUTBOUND_ADDR_ANY, options,
validate_only, msg) < 0) {
goto err;
}
@@ -7106,6 +7234,12 @@ parse_outbound_addresses(or_options_t *options, int validate_only, char **msg)
goto err;
}
+ if (parse_outbound_address_lines(options->OutboundBindAddressPT,
+ OUTBOUND_ADDR_PT, options, validate_only,
+ msg) < 0) {
+ goto err;
+ }
+
return 0;
err:
return -1;
diff --git a/src/app/config/config.h b/src/app/config/config.h
index 1ba10d1d37..e95ef4a728 100644
--- a/src/app/config/config.h
+++ b/src/app/config/config.h
@@ -58,8 +58,7 @@ setopt_err_t options_trial_assign(struct config_line_t *list, unsigned flags,
void options_init(or_options_t *options);
#define OPTIONS_DUMP_MINIMAL 1
-#define OPTIONS_DUMP_DEFAULTS 2
-#define OPTIONS_DUMP_ALL 3
+#define OPTIONS_DUMP_ALL 2
char *options_dump(const or_options_t *options, int how_to_dump);
int options_init_from_torrc(int argc, char **argv);
setopt_err_t options_init_from_string(const char *cf_defaults, const char *cf,
@@ -160,13 +159,11 @@ 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() \
- (get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER, AF_INET))
-#define get_primary_dir_port() \
- (get_first_advertised_port_by_type_af(CONN_TYPE_DIR_LISTENER, AF_INET))
-const tor_addr_t *get_first_advertised_addr_by_type_af(int listener_type,
+int portconf_get_first_advertised_port(int listener_type,
+ int address_family);
+#define portconf_get_primary_dir_port() \
+ (portconf_get_first_advertised_port(CONN_TYPE_DIR_LISTENER, AF_INET))
+const tor_addr_t *portconf_get_first_advertised_addr(int listener_type,
int address_family);
int port_exists_by_type_addr_port(int listener_type, const tor_addr_t *addr,
int port, int check_wildcard);
diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h
index bf58205f89..4364f145ed 100644
--- a/src/app/config/or_options_st.h
+++ b/src/app/config/or_options_st.h
@@ -24,10 +24,29 @@ struct config_suite_t;
struct routerset_t;
/** Enumeration of outbound address configuration types:
- * Exit-only, OR-only, or both */
-typedef enum {OUTBOUND_ADDR_EXIT, OUTBOUND_ADDR_OR,
- OUTBOUND_ADDR_EXIT_AND_OR,
- OUTBOUND_ADDR_MAX} outbound_addr_t;
+ * Exit-only, OR-only, PT-only, or any of them */
+typedef enum {
+ /** Outbound IP address for Exit connections. Controlled by the
+ * `OutboundBindAddressExit` configuration entry in torrc. */
+ OUTBOUND_ADDR_EXIT,
+
+ /** Outbound IP address for OR connections. Controlled by the
+ * `OutboundBindAddressOR` configuration entry in torrc. */
+ OUTBOUND_ADDR_OR,
+
+ /** Outbound IP address for PT connections. Controlled by the
+ * `OutboundBindAddressPT` configuration entry in torrc. */
+ OUTBOUND_ADDR_PT,
+
+ /** Outbound IP address for any outgoing connections. Controlled by the
+ * OutboundBindAddress configuration entry in torrc. This value is used as
+ * fallback if the more specific OUTBOUND_ADDR_EXIT, OUTBOUND_ADDR_OR, and
+ * OUTBOUND_ADDR_PT are unset. */
+ OUTBOUND_ADDR_ANY,
+
+ /** Max value for this enum. Must be the last element in this enum. */
+ OUTBOUND_ADDR_MAX
+} outbound_addr_t;
/** Which protocol to use for TCPProxy. */
typedef enum {
@@ -35,6 +54,12 @@ typedef enum {
TCP_PROXY_PROTOCOL_HAPROXY
} tcp_proxy_protocol_t;
+/** Enumeration of available time formats for output of --key-expiration */
+typedef enum {
+ KEY_EXPIRATION_FORMAT_ISO8601 = 0,
+ KEY_EXPIRATION_FORMAT_TIMESTAMP
+} key_expiration_format_t;
+
/** Configuration options for a Tor process. */
struct or_options_t {
uint32_t magic_;
@@ -52,7 +77,6 @@ struct or_options_t {
int TruncateLogFile; /**< Boolean: Should we truncate the log file
before we start writing? */
char *SyslogIdentityTag; /**< Identity tag to add for syslog logging. */
- char *AndroidIdentityTag; /**< Identity tag to add for Android logging. */
char *DebugLogFile; /**< Where to send verbose log messages. */
char *DataDirectory_option; /**< Where to store long-term data, as
@@ -71,7 +95,14 @@ struct or_options_t {
int CacheDirectoryGroupReadable; /**< Boolean: Is the CacheDirectory g+r? */
char *Nickname; /**< OR only: nickname of this onion router. */
- char *Address; /**< OR only: configured address for this onion router. */
+ /** OR only: configured address for this onion router. Up to two times this
+ * options is accepted as in IPv4 and IPv6. */
+ struct config_line_t *Address;
+
+ /** Boolean: If set, disable IPv6 address resolution, IPv6 ORPorts, IPv6
+ * reachability checks, and publishing an IPv6 ORPort in its descriptor. */
+ int AddressDisableIPv6;
+
char *PidFile; /**< Where to store PID of Tor process. */
struct routerset_t *ExitNodes; /**< Structure containing nicknames, digests,
@@ -118,6 +149,8 @@ struct or_options_t {
struct config_line_t *OutboundBindAddressOR;
/** Local address to bind outbound exit sockets */
struct config_line_t *OutboundBindAddressExit;
+ /** Local address to bind outbound PT sockets */
+ struct config_line_t *OutboundBindAddressPT;
/** Addresses derived from the various OutboundBindAddress lines.
* [][0] is IPv4, [][1] is IPv6
*/
@@ -131,6 +164,8 @@ struct or_options_t {
struct config_line_t *ORPort_lines;
/** Ports to listen on for extended OR connections. */
struct config_line_t *ExtORPort_lines;
+ /** Ports to listen on for Metrics connections. */
+ struct config_line_t *MetricsPort_lines;
/** Ports to listen on for SOCKS connections. */
struct config_line_t *SocksPort_lines;
/** Ports to listen on for transparent pf/netfilter connections. */
@@ -190,9 +225,17 @@ struct or_options_t {
unsigned int DNSPort_set : 1;
unsigned int ExtORPort_set : 1;
unsigned int HTTPTunnelPort_set : 1;
+ unsigned int MetricsPort_set : 1;
/**@}*/
- int AssumeReachable; /**< Whether to publish our descriptor regardless. */
+ /** Whether to publish our descriptor regardless of all our self-tests
+ */
+ int AssumeReachable;
+ /** Whether to publish our descriptor regardless of IPv6 self-tests.
+ *
+ * This is an autobool; when set to AUTO, it uses AssumeReachable.
+ **/
+ int AssumeReachableIPv6;
int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */
int V3AuthoritativeDir; /**< Boolean: is this an authoritative directory
* for version 3 directories? */
@@ -648,7 +691,7 @@ struct or_options_t {
int ClientUseIPv4;
/** If true, clients may connect over IPv6. If false, they will avoid
* connecting over IPv4. We enforce this for OR and Dir connections.
- * Use fascist_firewall_use_ipv6() instead of accessing this value
+ * Use reachable_addr_use_ipv6() instead of accessing this value
* directly. */
int ClientUseIPv6;
/** If true, prefer an IPv6 OR port over an IPv4 one for entry node
@@ -658,7 +701,7 @@ struct or_options_t {
int ClientPreferIPv6ORPort;
/** If true, prefer an IPv6 directory port over an IPv4 one for direct
* directory connections. If auto, bridge clients prefer IPv6, and other
- * clients prefer IPv4. Use fascist_firewall_prefer_ipv6_dirport() instead of
+ * clients prefer IPv4. Use reachable_addr_prefer_ipv6_dirport() instead of
* accessing this value directly. */
int ClientPreferIPv6DirPort;
@@ -828,10 +871,6 @@ struct or_options_t {
* once. */
int MaxClientCircuitsPending;
- /** If 1, we always send optimistic data when it's supported. If 0, we
- * never use it. If -1, we do what the consensus says. */
- int OptimisticData;
-
/** If 1, we accept and launch no external network connections, except on
* control ports. */
int DisableNetwork;
@@ -930,6 +969,8 @@ struct or_options_t {
* ed25519 identity key except from tor --keygen */
int OfflineMasterKey;
+ key_expiration_format_t key_expiration_format;
+
enum {
FORCE_PASSPHRASE_AUTO=0,
FORCE_PASSPHRASE_ON,
@@ -1000,7 +1041,7 @@ struct or_options_t {
/** Maximum allowed burst of circuits. Reaching that value, the address is
* detected as malicious and a defense might be used. */
int DoSCircuitCreationBurst;
- /** When an address is marked as malicous, what defense should be used
+ /** When an address is marked as malicious, what defense should be used
* against it. See the dos_cc_defense_type_t enum. */
int DoSCircuitCreationDefenseType;
/** For how much time (in seconds) the defense is applicable for a malicious
@@ -1038,6 +1079,9 @@ struct or_options_t {
**/
int DormantCanceledByStartup;
+ /** List of policy allowed to query the Metrics port. */
+ struct config_line_t *MetricsPortPolicy;
+
/**
* Configuration objects for individual modules.
*
diff --git a/src/app/config/or_state_st.h b/src/app/config/or_state_st.h
index 8c4e9d5e61..807f546169 100644
--- a/src/app/config/or_state_st.h
+++ b/src/app/config/or_state_st.h
@@ -21,7 +21,7 @@ struct config_suite_t;
struct or_state_t {
uint32_t magic_;
/** The time at which we next plan to write the state to the disk. Equal to
- * TIME_MAX if there are no savable changes, 0 if there are changes that
+ * TIME_MAX if there are no saveable changes, 0 if there are changes that
* should be saved right away. */
time_t next_write;
@@ -38,17 +38,11 @@ struct or_state_t {
uint64_t AccountingBytesAtSoftLimit;
uint64_t AccountingExpectedUsage;
- /** A list of Entry Guard-related configuration lines. (pre-prop271) */
- struct config_line_t *EntryGuards;
-
- /** A list of guard-related configuration lines. (post-prop271) */
+ /** A list of guard-related configuration lines. */
struct config_line_t *Guard;
struct config_line_t *TransportProxies;
- /** Cached revision counters for active hidden services on this host */
- struct config_line_t *HidServRevCounter;
-
/** These fields hold information on the history of bandwidth usage for
* servers. The "Ends" fields hold the time when we last updated the
* bandwidth usage. The "Interval" fields hold the granularity, in seconds,
@@ -65,6 +59,14 @@ struct or_state_t {
int BWHistoryWriteInterval;
struct smartlist_t *BWHistoryWriteValues;
struct smartlist_t *BWHistoryWriteMaxima;
+ time_t BWHistoryIPv6ReadEnds;
+ int BWHistoryIPv6ReadInterval;
+ struct smartlist_t *BWHistoryIPv6ReadValues;
+ struct smartlist_t *BWHistoryIPv6ReadMaxima;
+ time_t BWHistoryIPv6WriteEnds;
+ int BWHistoryIPv6WriteInterval;
+ struct smartlist_t *BWHistoryIPv6WriteValues;
+ struct smartlist_t *BWHistoryIPv6WriteMaxima;
time_t BWHistoryDirReadEnds;
int BWHistoryDirReadInterval;
struct smartlist_t *BWHistoryDirReadValues;
diff --git a/src/app/config/resolve_addr.c b/src/app/config/resolve_addr.c
index 9d1a8e0260..86db6ba680 100644
--- a/src/app/config/resolve_addr.c
+++ b/src/app/config/resolve_addr.c
@@ -14,301 +14,842 @@
#include "core/mainloop/mainloop.h"
#include "feature/control/control_events.h"
+#include "feature/dirauth/authmode.h"
+#include "lib/encoding/confline.h"
#include "lib/net/gethostname.h"
#include "lib/net/resolve.h"
-/** Last value actually set by resolve_my_address. */
-static uint32_t last_resolved_addr = 0;
+/** Maximum "Address" statement allowed in our configuration. */
+#define MAX_CONFIG_ADDRESS 2
+
+/** Ease our life. Arrays containing state per address family. These are to
+ * add semantic to the code so we know what is accessed. */
+#define IDX_NULL 0 /* Index to zeroed address object. */
+#define IDX_IPV4 1 /* Index to AF_INET. */
+#define IDX_IPV6 2 /* Index to AF_INET6. */
+#define IDX_SIZE 3 /* How many indexes do we have. */
+
+/** Function in our address function table return one of these code. */
+typedef enum {
+ /* The address has been found. */
+ FN_RET_OK = 0,
+ /* The failure requirements were not met and thus it is recommended that the
+ * caller stops the search. */
+ FN_RET_BAIL = 1,
+ /* The address was not found or failure is transient so the caller should go
+ * to the next method. */
+ FN_RET_NEXT = 2,
+} fn_address_ret_t;
+
+/** Last resolved addresses. */
+static tor_addr_t last_resolved_addrs[] =
+ { TOR_ADDR_NULL, TOR_ADDR_NULL, TOR_ADDR_NULL };
+CTASSERT(ARRAY_LENGTH(last_resolved_addrs) == IDX_SIZE);
+
+/** Last suggested addresses.
+ *
+ * These addresses come from a NETINFO cell from a trusted relay (currently
+ * only authorities). We only use those in last resort. */
+static tor_addr_t last_suggested_addrs[] =
+ { TOR_ADDR_NULL, TOR_ADDR_NULL, TOR_ADDR_NULL };
+CTASSERT(ARRAY_LENGTH(last_suggested_addrs) == IDX_SIZE);
+
+/** True iff the address was found to be configured that is from the
+ * configuration file either using Address or ORPort. */
+static bool last_addrs_configured[] = { false, false, false };
+CTASSERT(ARRAY_LENGTH(last_addrs_configured) == IDX_SIZE);
+
+static inline int
+af_to_idx(const int family)
+{
+ switch (family) {
+ case AF_INET:
+ return IDX_IPV4;
+ case AF_INET6:
+ return IDX_IPV6;
+ default:
+ /* It wouldn't be safe to just die here with an assert but we can heavily
+ * scream with a bug. Return the index of the NULL address. */
+ tor_assert_nonfatal_unreached();
+ return IDX_NULL;
+ }
+}
-/** Accessor for last_resolved_addr from outside this file. */
-uint32_t
-get_last_resolved_addr(void)
+/** Return string representation of the given method. */
+const char *
+resolved_addr_method_to_str(const resolved_addr_method_t method)
{
- return last_resolved_addr;
+ switch (method) {
+ case RESOLVED_ADDR_NONE:
+ return "NONE";
+ case RESOLVED_ADDR_CONFIGURED:
+ return "CONFIGURED";
+ case RESOLVED_ADDR_CONFIGURED_ORPORT:
+ return "CONFIGURED_ORPORT";
+ case RESOLVED_ADDR_GETHOSTNAME:
+ return "GETHOSTNAME";
+ case RESOLVED_ADDR_INTERFACE:
+ return "INTERFACE";
+ case RESOLVED_ADDR_RESOLVED:
+ return "RESOLVED";
+ default:
+ tor_assert_nonfatal_unreached();
+ return "???";
+ }
}
-/** Reset last_resolved_addr from outside this file. */
+/** Return true if the last address of family was configured or not. An
+ * address is considered configured if it was found in the Address or ORPort
+ * statement.
+ *
+ * This applies to the address returned by the function
+ * resolved_addr_get_last() which is the cache of discovered addresses. */
+bool
+resolved_addr_is_configured(int family)
+{
+ return last_addrs_configured[af_to_idx(family)];
+}
+
+/** Copy the last suggested address of family into addr_out.
+ *
+ * If no last suggested address exists, the addr_out is a null address (use
+ * tor_addr_is_null() to confirm). */
void
-reset_last_resolved_addr(void)
+resolved_addr_get_suggested(int family, tor_addr_t *addr_out)
{
- last_resolved_addr = 0;
+ tor_addr_copy(addr_out, &last_suggested_addrs[af_to_idx(family)]);
}
-/**
- * Attempt getting our non-local (as judged by tor_addr_is_internal()
- * function) IP address using following techniques, listed in
- * order from best (most desirable, try first) to worst (least
- * desirable, try if everything else fails).
- *
- * First, attempt using <b>options-\>Address</b> to get our
- * non-local IP address.
- *
- * If <b>options-\>Address</b> represents a non-local IP address,
- * consider it ours.
- *
- * If <b>options-\>Address</b> is a DNS name that resolves to
- * a non-local IP address, consider this IP address ours.
- *
- * If <b>options-\>Address</b> is NULL, fall back to getting local
- * hostname and using it in above-described ways to try and
- * get our IP address.
- *
- * In case local hostname cannot be resolved to a non-local IP
- * address, try getting an IP address of network interface
- * in hopes it will be non-local one.
- *
- * Fail if one or more of the following is true:
- * - DNS name in <b>options-\>Address</b> cannot be resolved.
- * - <b>options-\>Address</b> is a local host address.
- * - Attempt at getting local hostname fails.
- * - Attempt at getting network interface address fails.
- *
- * Return 0 if all is well, or -1 if we can't find a suitable
- * public IP address.
- *
- * If we are returning 0:
- * - Put our public IP address (in host order) into *<b>addr_out</b>.
- * - If <b>method_out</b> is non-NULL, set *<b>method_out</b> to a static
- * string describing how we arrived at our answer.
- * - "CONFIGURED" - parsed from IP address string in
- * <b>options-\>Address</b>
- * - "RESOLVED" - resolved from DNS name in <b>options-\>Address</b>
- * - "GETHOSTNAME" - resolved from a local hostname.
- * - "INTERFACE" - retrieved from a network interface.
- * - If <b>hostname_out</b> is non-NULL, and we resolved a hostname to
- * get our address, set *<b>hostname_out</b> to a newly allocated string
- * holding that hostname. (If we didn't get our address by resolving a
- * hostname, set *<b>hostname_out</b> to NULL.)
- *
- * XXXX ipv6
+/** Set the last suggested address into our cache. This is called when we get
+ * a new NETINFO cell from a trusted source. */
+void
+resolved_addr_set_suggested(const tor_addr_t *addr)
+{
+ if (BUG(tor_addr_family(addr) != AF_INET &&
+ tor_addr_family(addr) != AF_INET6)) {
+ return;
+ }
+
+ /* In case we don't have a configured address, log that we will be using the
+ * one discovered from the dirauth. */
+ const int idx = af_to_idx(tor_addr_family(addr));
+ if (tor_addr_is_null(&last_resolved_addrs[idx]) &&
+ !tor_addr_eq(&last_suggested_addrs[idx], addr)) {
+ log_notice(LD_CONFIG, "External address seen and suggested by a "
+ "directory authority: %s", fmt_addr(addr));
+ }
+ tor_addr_copy(&last_suggested_addrs[idx], addr);
+}
+
+/** Copy the last resolved address of family into addr_out.
+ *
+ * If not last resolved address existed, the addr_out is a null address (use
+ * tor_addr_is_null()). */
+void
+resolved_addr_get_last(int family, tor_addr_t *addr_out)
+{
+ tor_addr_copy(addr_out, &last_resolved_addrs[af_to_idx(family)]);
+}
+
+/** Reset the last resolved address of family.
+ *
+ * This makes it null address. */
+void
+resolved_addr_reset_last(int family)
+{
+ tor_addr_make_null(&last_resolved_addrs[af_to_idx(family)], family);
+}
+
+/** Errors returned by address_can_be_used() in order for the caller to know
+ * why the address is denied or not. */
+#define ERR_DEFAULT_DIRAUTH -1 /* Using default authorities. */
+#define ERR_ADDRESS_IS_INTERNAL -2 /* IP is internal. */
+
+/** @brief Return true iff the given IP address can be used as a valid
+ * external resolved address.
+ *
+ * Two tests are done in this function:
+ * 1) If the address if NOT internal, it can be used.
+ * 2) If the address is internal and we have custom directory authorities
+ * configured then it can they be used. Important for testing networks.
+ *
+ * @param addr The IP address to validate.
+ * @param options Global configuration options.
+ * @param warn_severity Log level that should be used on error.
+ * @param explicit_ip Was the IP address explicitly given.
+ *
+ * @return Return 0 if it can be used. Return error code ERR_* found at the
+ * top of the file.
*/
-int
-resolve_my_address(int warn_severity, const or_options_t *options,
- uint32_t *addr_out,
- const char **method_out, char **hostname_out)
+static int
+address_can_be_used(const tor_addr_t *addr, const or_options_t *options,
+ int warn_severity, const bool explicit_ip)
{
- struct in_addr in;
- uint32_t addr; /* host order */
- char hostname[256];
- const char *method_used;
- const char *hostname_used;
- int explicit_ip=1;
- int explicit_hostname=1;
- int from_interface=0;
- char *addr_string = NULL;
- const char *address = options->Address;
- int notice_severity = warn_severity <= LOG_NOTICE ?
- LOG_NOTICE : warn_severity;
-
- tor_addr_t myaddr;
- tor_assert(addr_out);
+ tor_assert(addr);
- /*
- * Step one: Fill in 'hostname' to be our best guess.
- */
+ /* Public address, this is fine. */
+ if (!tor_addr_is_internal(addr, 0)) {
+ goto allow;
+ }
- if (address && *address) {
- strlcpy(hostname, address, sizeof(hostname));
- log_debug(LD_CONFIG, "Trying configured Address '%s' as local hostname",
- hostname);
- } else { /* then we need to guess our address */
- explicit_ip = 0; /* it's implicit */
- explicit_hostname = 0; /* it's implicit */
-
- if (tor_gethostname(hostname, sizeof(hostname)) < 0) {
- log_fn(warn_severity, LD_NET,"Error obtaining local hostname");
- return -1;
- }
- log_debug(LD_CONFIG, "Guessed local host name as '%s'", hostname);
+ /* We allow internal addresses to be used if the PublishServerDescriptor is
+ * unset and AssumeReachable (or for IPv6) is set.
+ *
+ * This is to cover the case where a relay/bridge might be run behind a
+ * firewall on a local network to users can reach the network through it
+ * using Tor Browser for instance. */
+ if (options->PublishServerDescriptor_ == NO_DIRINFO &&
+ (options->AssumeReachable ||
+ (tor_addr_family(addr) == AF_INET6 && options->AssumeReachableIPv6))) {
+ goto allow;
}
- /*
- * Step two: Now that we know 'hostname', parse it or resolve it. If
- * it doesn't parse or resolve, look at the interface address. Set 'addr'
- * to be our (host-order) 32-bit answer.
- */
+ /* We have a private IP address. This is also allowed if we set custom
+ * directory authorities. */
+ if (using_default_dir_authorities(options)) {
+ log_fn(warn_severity, LD_CONFIG,
+ "Address '%s' is a private IP address. Tor relays that use "
+ "the default DirAuthorities must have public IP addresses.",
+ fmt_addr(addr));
+ return ERR_DEFAULT_DIRAUTH;
+ }
- if (tor_inet_aton(hostname, &in) == 0) {
- /* then we have to resolve it */
- log_debug(LD_CONFIG, "Local hostname '%s' is DNS address. "
- "Trying to resolve to IP address.", hostname);
- explicit_ip = 0;
- if (tor_lookup_hostname(hostname, &addr)) { /* failed to resolve */
- uint32_t interface_ip; /* host order */
-
- if (explicit_hostname) {
- log_fn(warn_severity, LD_CONFIG,
- "Could not resolve local Address '%s'. Failing.", hostname);
- return -1;
- }
- log_fn(notice_severity, LD_CONFIG,
- "Could not resolve guessed local hostname '%s'. "
- "Trying something else.", hostname);
- if (get_interface_address(warn_severity, &interface_ip)) {
- log_fn(warn_severity, LD_CONFIG,
- "Could not get local interface IP address. Failing.");
- return -1;
- }
- from_interface = 1;
- addr = interface_ip;
- log_fn(notice_severity, LD_CONFIG, "Learned IP address '%s' for "
- "local interface. Using that.", fmt_addr32(addr));
- strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
- } else { /* resolved hostname into addr */
- tor_addr_from_ipv4h(&myaddr, addr);
-
- if (!explicit_hostname &&
- tor_addr_is_internal(&myaddr, 0)) {
- tor_addr_t interface_ip;
-
- log_fn(notice_severity, LD_CONFIG, "Guessed local hostname '%s' "
- "resolves to a private IP address (%s). Trying something "
- "else.", hostname, fmt_addr32(addr));
-
- if (get_interface_address6(warn_severity, AF_INET, &interface_ip)<0) {
- log_fn(warn_severity, LD_CONFIG,
- "Could not get local interface IP address. Too bad.");
- } else if (tor_addr_is_internal(&interface_ip, 0)) {
- log_fn(notice_severity, LD_CONFIG,
- "Interface IP address '%s' is a private address too. "
- "Ignoring.", fmt_addr(&interface_ip));
- } else {
- from_interface = 1;
- addr = tor_addr_to_ipv4h(&interface_ip);
- log_fn(notice_severity, LD_CONFIG,
- "Learned IP address '%s' for local interface."
- " Using that.", fmt_addr32(addr));
- strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
- }
- }
- }
- } else {
- log_debug(LD_CONFIG, "Local hostname '%s' is already IP address, "
- "skipping DNS resolution", hostname);
- addr = ntohl(in.s_addr); /* set addr so that addr_string is not
- * illformed */
+ if (!explicit_ip) {
+ /* Even with custom directory authorities, only an explicit internal
+ * address is accepted. */
+ log_fn(warn_severity, LD_CONFIG,
+ "Address %s was resolved and thus not explicitly "
+ "set. Even if DirAuthorities are custom, this is "
+ "not allowed.", fmt_addr(addr));
+ return ERR_ADDRESS_IS_INTERNAL;
}
- /*
- * Step three: Check whether 'addr' is an internal IP address, and error
- * out if it is and we don't want that.
- */
+ allow:
+ return 0;
+}
+
+/** @brief Get IP address from the given config line and for a specific address
+ * family.
+ *
+ * This can fail is more than two Address statement are found for the same
+ * address family. It also fails if no statement is found.
+ *
+ * @param options Global configuration options.
+ * @param warn_severity Log level that should be used on error.
+ * @param family IP address family. Only AF_INET and AF_INET6 are supported.
+ * @param method_out OUT: Method denoting how the address was found.
+ * This is described in the control-spec.txt as
+ * actions for "STATUS_SERVER".
+ * @param hostname_out OUT: String containing the hostname gotten from the
+ * Address value if any.
+ * @param addr_out OUT: Tor address of the address found in the cline or
+ * resolved from the cline.
+ *
+ * @return Return 0 on success that is an address has been found or resolved
+ * successfully. Return error code ERR_* found at the top of the file.
+ */
+static fn_address_ret_t
+get_address_from_config(const or_options_t *options, int warn_severity,
+ int family, resolved_addr_method_t *method_out,
+ char **hostname_out, tor_addr_t *addr_out)
+{
+ int ret;
+ bool explicit_ip = false, resolve_failure = false;
+ int num_valid_addr = 0;
+
+ tor_assert(options);
+ tor_assert(addr_out);
+ tor_assert(method_out);
+ tor_assert(hostname_out);
- tor_addr_from_ipv4h(&myaddr,addr);
+ /* Set them to NULL for safety reasons. */
+ *hostname_out = NULL;
+ *method_out = RESOLVED_ADDR_NONE;
- addr_string = tor_dup_ip(addr);
- if (addr_string && tor_addr_is_internal(&myaddr, 0)) {
- /* make sure we're ok with publishing an internal IP */
- if (using_default_dir_authorities(options)) {
- /* if they are using the default authorities, disallow internal IPs
- * always. For IPv6 ORPorts, this check is done in
- * router_get_advertised_ipv6_or_ap(). See #33681. */
+ log_debug(LD_CONFIG, "Attempting to get address from configuration");
+
+ if (!options->Address) {
+ log_info(LD_CONFIG, "No Address option found in configuration.");
+ /* No Address statement, inform caller to try next method. */
+ return FN_RET_NEXT;
+ }
+
+ for (const config_line_t *cfg = options->Address; cfg != NULL;
+ cfg = cfg->next) {
+ int af;
+ tor_addr_t addr;
+
+ af = tor_addr_parse(&addr, cfg->value);
+ if (af == family) {
+ tor_addr_copy(addr_out, &addr);
+ *method_out = RESOLVED_ADDR_CONFIGURED;
+ explicit_ip = true;
+ num_valid_addr++;
+ continue;
+ } else if (af != -1) {
+ /* Parsable address but just not the one from the family we want. Skip
+ * it so we don't attempt a resolve. */
+ continue;
+ }
+
+ /* Not an IP address. Considering this value a hostname and attempting to
+ * do a DNS lookup. */
+ if (!tor_addr_lookup(cfg->value, family, &addr)) {
+ tor_addr_copy(addr_out, &addr);
+ *method_out = RESOLVED_ADDR_RESOLVED;
+ if (*hostname_out) {
+ tor_free(*hostname_out);
+ }
+ *hostname_out = tor_strdup(cfg->value);
+ explicit_ip = false;
+ num_valid_addr++;
+ continue;
+ } else {
+ /* Hostname that can't be resolved, this is a fatal error. */
+ resolve_failure = true;
log_fn(warn_severity, LD_CONFIG,
- "Address '%s' resolves to private IP address '%s'. "
- "Tor servers that use the default DirAuthorities must have "
- "public IP addresses.", hostname, addr_string);
- tor_free(addr_string);
- return -1;
+ "Could not resolve local Address '%s'. Failing.", cfg->value);
+ continue;
}
- if (!explicit_ip) {
- /* even if they've set their own authorities, require an explicit IP if
- * they're using an internal address. */
- log_fn(warn_severity, LD_CONFIG, "Address '%s' resolves to private "
- "IP address '%s'. Please set the Address config option to be "
- "the IP address you want to use.", hostname, addr_string);
- tor_free(addr_string);
- return -1;
+ }
+
+ if (!num_valid_addr) {
+ if (resolve_failure) {
+ /* We found no address but we got a resolution failure. This means we
+ * can know if the hostname given was v4 or v6 so we can't continue. */
+ return FN_RET_BAIL;
}
+ log_info(LD_CONFIG,
+ "No Address option found for family %s in configuration.",
+ fmt_af_family(family));
+ /* No Address statement for family so move on to try next method. */
+ return FN_RET_NEXT;
}
- /*
- * Step four: We have a winner! 'addr' is our answer for sure, and
- * 'addr_string' is its string form. Fill out the various fields to
- * say how we decided it.
- */
+ if (num_valid_addr >= MAX_CONFIG_ADDRESS) {
+ /* Too many Address for same family. This is a fatal error. */
+ log_fn(warn_severity, LD_CONFIG,
+ "Found %d Address statement of address family %s. "
+ "Only one is allowed.", num_valid_addr, fmt_af_family(family));
+ tor_free(*hostname_out);
+ return FN_RET_BAIL;
+ }
- log_debug(LD_CONFIG, "Resolved Address to '%s'.", addr_string);
-
- if (explicit_ip) {
- method_used = "CONFIGURED";
- hostname_used = NULL;
- } else if (explicit_hostname) {
- method_used = "RESOLVED";
- hostname_used = hostname;
- } else if (from_interface) {
- method_used = "INTERFACE";
- hostname_used = NULL;
- } else {
- method_used = "GETHOSTNAME";
- hostname_used = hostname;
+ /* Great, we found an address. */
+ ret = address_can_be_used(addr_out, options, warn_severity, explicit_ip);
+ if (ret != 0) {
+ /* One of the requirement of this interface is if an internal Address is
+ * used, custom authorities must be defined else it is a fatal error.
+ * Furthermore, if the Address was resolved to an internal interface, we
+ * stop immediately. */
+ tor_free(*hostname_out);
+ return FN_RET_BAIL;
}
- *addr_out = addr;
- if (method_out)
- *method_out = method_used;
- if (hostname_out)
- *hostname_out = hostname_used ? tor_strdup(hostname_used) : NULL;
+ /* Address can be used. We are done. */
+ log_info(LD_CONFIG, "Address found in configuration: %s",
+ fmt_addr(addr_out));
+ return FN_RET_OK;
+}
- /*
- * Step five: Check if the answer has changed since last time (or if
- * there was no last time), and if so call various functions to keep
- * us up-to-date.
- */
+/** @brief Get IP address from the local hostname by calling gethostbyname()
+ * and doing a DNS resolution on the hostname.
+ *
+ * @param options Global configuration options.
+ * @param warn_severity Log level that should be used on error.
+ * @param family IP address family. Only AF_INET and AF_INET6 are supported.
+ * @param method_out OUT: Method denoting how the address was found.
+ * This is described in the control-spec.txt as
+ * actions for "STATUS_SERVER".
+ * @param hostname_out OUT: String containing the local hostname.
+ * @param addr_out OUT: Tor address resolved from the local hostname.
+ *
+ * @return Return 0 on success that is an address has been found and resolved
+ * successfully. Return error code ERR_* found at the top of the file.
+ */
+static fn_address_ret_t
+get_address_from_hostname(const or_options_t *options, int warn_severity,
+ int family, resolved_addr_method_t *method_out,
+ char **hostname_out, tor_addr_t *addr_out)
+{
+ int ret;
+ char hostname[256];
+
+ tor_assert(addr_out);
+ tor_assert(method_out);
+
+ /* Set them to NULL for safety reasons. */
+ *hostname_out = NULL;
+ *method_out = RESOLVED_ADDR_NONE;
+
+ log_debug(LD_CONFIG, "Attempting to get address from local hostname");
+
+ if (tor_gethostname(hostname, sizeof(hostname)) < 0) {
+ log_fn(warn_severity, LD_NET, "Error obtaining local hostname");
+ /* Unable to obtain the local hostname is a fatal error. */
+ return FN_RET_BAIL;
+ }
+ if (tor_addr_lookup(hostname, family, addr_out)) {
+ log_fn(warn_severity, LD_NET,
+ "Could not resolve local hostname '%s'. Failing.", hostname);
+ /* Unable to resolve, inform caller to try next method. */
+ return FN_RET_NEXT;
+ }
+
+ ret = address_can_be_used(addr_out, options, warn_severity, false);
+ if (ret == ERR_DEFAULT_DIRAUTH) {
+ /* Non custom authorities, inform caller to try next method. */
+ return FN_RET_NEXT;
+ } else if (ret == ERR_ADDRESS_IS_INTERNAL) {
+ /* Internal address is a fatal error. */
+ return FN_RET_BAIL;
+ }
+
+ /* addr_out contains the address of the local hostname. */
+ *method_out = RESOLVED_ADDR_GETHOSTNAME;
+ *hostname_out = tor_strdup(hostname);
+
+ /* Found it! */
+ log_info(LD_CONFIG, "Address found from local hostname: %s",
+ fmt_addr(addr_out));
+ return FN_RET_OK;
+}
+
+/** @brief Get IP address from a network interface.
+ *
+ * @param options Global configuration options.
+ * @param warn_severity Log level that should be used on error.
+ * @param family IP address family. Only AF_INET and AF_INET6 are supported.
+ * @param method_out OUT: Always RESOLVED_ADDR_INTERFACE on success which
+ * is detailed in the control-spec.txt as actions
+ * for "STATUS_SERVER".
+ * @param hostname_out OUT: String containing the local hostname. For this
+ * function, it is always set to NULL.
+ * @param addr_out OUT: Tor address found attached to the interface.
+ *
+ * @return Return 0 on success that is an address has been found. Return
+ * error code ERR_* found at the top of the file.
+ */
+static fn_address_ret_t
+get_address_from_interface(const or_options_t *options, int warn_severity,
+ int family, resolved_addr_method_t *method_out,
+ char **hostname_out, tor_addr_t *addr_out)
+{
+ int ret;
+
+ tor_assert(method_out);
+ tor_assert(hostname_out);
+ tor_assert(addr_out);
+
+ /* Set them to NULL for safety reasons. */
+ *method_out = RESOLVED_ADDR_NONE;
+ *hostname_out = NULL;
+
+ log_debug(LD_CONFIG, "Attempting to get address from network interface");
+
+ if (get_interface_address6(warn_severity, family, addr_out) < 0) {
+ log_fn(warn_severity, LD_CONFIG,
+ "Could not get local interface IP address.");
+ /* Unable to get IP from interface. Inform caller to try next method. */
+ return FN_RET_NEXT;
+ }
- if (last_resolved_addr && last_resolved_addr != *addr_out) {
+ ret = address_can_be_used(addr_out, options, warn_severity, false);
+ if (ret < 0) {
+ /* Unable to use address. Inform caller to try next method. */
+ return FN_RET_NEXT;
+ }
+
+ *method_out = RESOLVED_ADDR_INTERFACE;
+
+ /* Found it! */
+ log_info(LD_CONFIG, "Address found from interface: %s", fmt_addr(addr_out));
+ return FN_RET_OK;
+}
+
+/** @brief Get IP address from the ORPort (if any).
+ *
+ * @param options Global configuration options.
+ * @param warn_severity Log level that should be used on error.
+ * @param family IP address family. Only AF_INET and AF_INET6 are supported.
+ * @param method_out OUT: Always RESOLVED_ADDR_CONFIGURED_ORPORT on success
+ * which is detailed in the control-spec.txt as actions
+ * for "STATUS_SERVER".
+ * @param hostname_out OUT: String containing the ORPort hostname if any.
+ * @param addr_out OUT: Tor address found if any.
+ *
+ * @return Return 0 on success that is an address has been found. Return
+ * error code ERR_* found at the top of the file.
+ */
+static fn_address_ret_t
+get_address_from_orport(const or_options_t *options, int warn_severity,
+ int family, resolved_addr_method_t *method_out,
+ char **hostname_out, tor_addr_t *addr_out)
+{
+ int ret;
+ const tor_addr_t *addr;
+
+ tor_assert(method_out);
+ tor_assert(hostname_out);
+ tor_assert(addr_out);
+
+ /* Set them to NULL for safety reasons. */
+ *method_out = RESOLVED_ADDR_NONE;
+ *hostname_out = NULL;
+
+ log_debug(LD_CONFIG, "Attempting to get address from ORPort");
+
+ if (!options->ORPort_set) {
+ log_info(LD_CONFIG, "No ORPort found in configuration.");
+ /* No ORPort statement, inform caller to try next method. */
+ return FN_RET_NEXT;
+ }
+
+ /* Get ORPort for requested family. */
+ addr = get_orport_addr(family);
+ if (!addr) {
+ /* No address configured for the ORPort. Ignore. */
+ return FN_RET_NEXT;
+ }
+
+ /* We found the ORPort address. Just make sure it can be used. */
+ ret = address_can_be_used(addr, options, warn_severity, true);
+ if (ret < 0) {
+ /* Unable to use address. Inform caller to try next method. */
+ return FN_RET_NEXT;
+ }
+
+ /* Found it! */
+ *method_out = RESOLVED_ADDR_CONFIGURED_ORPORT;
+ tor_addr_copy(addr_out, addr);
+
+ log_fn(warn_severity, LD_CONFIG, "Address found from ORPort: %s",
+ fmt_addr(addr_out));
+ return FN_RET_OK;
+}
+
+/** @brief Set the last resolved address cache using the given address.
+ *
+ * A log notice is emitted if the given address has changed from before. Not
+ * emitted on first resolve.
+ *
+ * Control port event "STATUS_SERVER" is emitted with the new information if
+ * it has changed.
+ *
+ * Finally, tor is notified that the IP address has changed.
+ *
+ * @param addr IP address to update the cache with.
+ * @param method_used By which method did we resolved it (for logging and
+ * control port).
+ * @param hostname_used Which hostname was used. If none were used, it is
+ * NULL. (for logging and control port).
+ */
+void
+resolved_addr_set_last(const tor_addr_t *addr,
+ const resolved_addr_method_t method_used,
+ const char *hostname_used)
+{
+ /** Have we done a first resolve. This is used to control logging. */
+ static bool have_resolved_once[] = { false, false, false };
+ CTASSERT(ARRAY_LENGTH(have_resolved_once) == IDX_SIZE);
+
+ bool *done_one_resolve;
+ bool have_hostname = false;
+ tor_addr_t *last_resolved;
+
+ tor_assert(addr);
+
+ /* Do we have an hostname. */
+ have_hostname = (hostname_used != NULL);
+
+ int idx = af_to_idx(tor_addr_family(addr));
+ if (idx == IDX_NULL) {
+ /* Not suppose to happen and if it does, af_to_idx() screams loudly. */
+ return;
+ }
+
+ /* Get values from cache. */
+ done_one_resolve = &have_resolved_once[idx];
+ last_resolved = &last_resolved_addrs[idx];
+
+ /* Same address last resolved. Ignore. */
+ if (tor_addr_eq(last_resolved, addr)) {
+ return;
+ }
+
+ /* Don't log notice if this is the first resolve we do. */
+ if (*done_one_resolve) {
/* Leave this as a notice, regardless of the requested severity,
* at least until dynamic IP address support becomes bulletproof. */
log_notice(LD_NET,
"Your IP address seems to have changed to %s "
"(METHOD=%s%s%s). Updating.",
- addr_string, method_used,
- hostname_used ? " HOSTNAME=" : "",
- hostname_used ? hostname_used : "");
+ fmt_addr(addr),
+ resolved_addr_method_to_str(method_used),
+ have_hostname ? " HOSTNAME=" : "",
+ have_hostname ? hostname_used : "");
ip_address_changed(0);
}
- if (last_resolved_addr != *addr_out) {
- control_event_server_status(LOG_NOTICE,
- "EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s%s%s",
- addr_string, method_used,
- hostname_used ? " HOSTNAME=" : "",
- hostname_used ? hostname_used : "");
+ /* Notify control port. */
+ control_event_server_status(LOG_NOTICE,
+ "EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s%s%s",
+ fmt_addr(addr),
+ resolved_addr_method_to_str(method_used),
+ have_hostname ? " HOSTNAME=" : "",
+ have_hostname ? hostname_used : "");
+ /* Copy address to cache. */
+ tor_addr_copy(last_resolved, addr);
+ *done_one_resolve = true;
+
+ /* Flag true if the address was configured. Else, indicate it was not. */
+ last_addrs_configured[idx] = false;
+ if (method_used == RESOLVED_ADDR_CONFIGURED ||
+ method_used == RESOLVED_ADDR_CONFIGURED_ORPORT) {
+ last_addrs_configured[idx] = true;
+ }
+}
+
+/** Ease our lives. Typedef to the address discovery function signature. */
+typedef fn_address_ret_t
+ (*fn_address_t)(
+ const or_options_t *options, int warn_severity, int family,
+ resolved_addr_method_t *method_out, char **hostname_out,
+ tor_addr_t *addr_out);
+
+/** Address discovery function table. The order matters as in the first one is
+ * executed first and so on. */
+static const fn_address_t fn_address_table[] =
+{
+ /* These functions are in order for our find address algorithm. */
+ get_address_from_config,
+ get_address_from_orport,
+ get_address_from_interface,
+ get_address_from_hostname,
+};
+/** Length of address table as in how many functions. */
+static const size_t fn_address_table_len =
+ ARRAY_LENGTH(fn_address_table);
+
+/* Address discover function table for authorities (bridge or directory).
+ *
+ * They only discover their address from either the configuration file or the
+ * ORPort. They do not query the interface nor do any DNS resolution for
+ * security reasons. */
+static const fn_address_t fn_address_table_auth[] =
+{
+ /* These functions are in order for our find address algorithm. */
+ get_address_from_config,
+ get_address_from_orport,
+};
+/** Length of address table as in how many functions. */
+static const size_t fn_address_table_auth_len =
+ ARRAY_LENGTH(fn_address_table_auth);
+
+/** @brief Attempt to find our IP address that can be used as our external
+ * reachable address.
+ *
+ * The following describe the algorithm to find an address. Each have
+ * specific conditions so read carefully.
+ *
+ * On success, true is returned and depending on how the address was found,
+ * the out parameters can have different values.
+ *
+ * On error, false is returned and out parameters are set to NULL.
+ *
+ * 1. Look at the configuration Address option.
+
+ * If Address is a public address, True is returned and addr_out is set
+ * with it, the method_out is set to RESOLVED_ADDR_CONFIGURED and
+ * hostname_out is set to NULL.
+ *
+ * If Address is an internal address but NO custom authorities are used,
+ * an error is returned.
+ *
+ * If Address is a hostname, that is it can't be converted to an address,
+ * it is resolved. On success, addr_out is set with the address,
+ * method_out is set to RESOLVED_ADDR_RESOLVED and hostname_out is set
+ * to the resolved hostname. On failure to resolve, an error is returned.
+ *
+ * If no given Address, fallback to the network interface (see section 2).
+ *
+ * 2. Look at the network interface.
+ *
+ * Attempt to find the first public usable address from the list of
+ * network interfaces returned by the OS.
+ *
+ * On failure, we attempt to look at the local hostname (3).
+ *
+ * On success, addr_out is set with it, method_out is set to
+ * RESOLVED_ADDR_INTERFACE and hostname_out is set to NULL.
+ *
+ * 3. Look at the local hostname.
+ *
+ * If the local hostname resolves to a non internal address, addr_out is
+ * set with it, method_out is set to RESOLVED_ADDR_GETHOSTNAME and
+ * hostname_out is set to the resolved hostname.
+ *
+ * If a local hostname can NOT be found, an error is returned.
+ *
+ * If the local hostname resolves to an internal address, an error is
+ * returned.
+ *
+ * If the local hostname can NOT be resolved, an error is returned.
+ *
+ * @param options Global configuration options.
+ * @param family IP address family. Only AF_INET and AF_INET6 are supported.
+ * @param warn_severity Logging level.
+ * @param addr_out OUT: Set with the IP address found if any.
+ * @param method_out OUT: (optional) Method denoting how the address wa
+ * found. This is described in the control-spec.txt as
+ * actions for "STATUS_SERVER".
+ * @param hostname_out OUT: String containing the hostname if any was used.
+ * Only be set for RESOLVED and GETHOSTNAME methods.
+ * Else it is set to NULL.
+ *
+ * @return True if the address was found for the given family. False if not or
+ * on errors.
+ */
+bool
+find_my_address(const or_options_t *options, int family, int warn_severity,
+ tor_addr_t *addr_out, resolved_addr_method_t *method_out,
+ char **hostname_out)
+{
+ resolved_addr_method_t method_used = RESOLVED_ADDR_NONE;
+ char *hostname_used = NULL;
+ tor_addr_t my_addr;
+ const fn_address_t *table = fn_address_table;
+ size_t table_len = fn_address_table_len;
+
+ tor_assert(options);
+ tor_assert(addr_out);
+
+ /* Set them to NULL for safety reasons. */
+ tor_addr_make_unspec(addr_out);
+ if (method_out) *method_out = RESOLVED_ADDR_NONE;
+ if (hostname_out) *hostname_out = NULL;
+
+ /* If an IPv6 is requested, check if IPv6 address discovery is disabled and
+ * if so we always return a failure. It is done here so we don't populate
+ * the resolve cache or do any DNS resolution. */
+ if (family == AF_INET6 && options->AddressDisableIPv6) {
+ return false;
+ }
+
+ /* For authorities (bridge and directory), we use a different table. */
+ if (authdir_mode(options)) {
+ table = fn_address_table_auth;
+ table_len = fn_address_table_auth_len;
}
- last_resolved_addr = *addr_out;
/*
- * And finally, clean up and return success.
+ * Step 1: Discover address by calling methods from the function table.
*/
- tor_free(addr_string);
- return 0;
+ /* Go over the function table. They are in order. */
+ for (size_t idx = 0; idx < table_len; idx++) {
+ fn_address_ret_t ret = table[idx](options, warn_severity, family,
+ &method_used, &hostname_used, &my_addr);
+ if (ret == FN_RET_BAIL) {
+ return false;
+ } else if (ret == FN_RET_OK) {
+ goto found;
+ }
+ tor_assert(ret == FN_RET_NEXT);
+ }
+
+ /* We've exhausted our attempts. Failure. */
+ log_fn(warn_severity, LD_CONFIG, "Unable to find our IP address.");
+ return false;
+
+ found:
+ /*
+ * Step 2: Update last resolved address cache and inform the control port.
+ */
+ resolved_addr_set_last(&my_addr, method_used, hostname_used);
+
+ if (method_out) {
+ *method_out = method_used;
+ }
+ if (hostname_out) {
+ *hostname_out = hostname_used;
+ } else {
+ tor_free(hostname_used);
+ }
+
+ tor_addr_copy(addr_out, &my_addr);
+ return true;
}
-/** Return true iff <b>addr</b> is judged to be on the same network as us, or
- * on a private network.
+/** @brief: Return true iff the given addr is judged to be local to our
+ * resolved address.
+ *
+ * This function is used to tell whether another address is 'remote' enough
+ * that we can trust it when it tells us that we are reachable, or that we
+ * have a certain address.
+ *
+ * The criterion to learn if the address is local are the following:
+ *
+ * 1. Internal address.
+ * 2. If EnforceDistinctSubnets is set then it is never local.
+ * 3. Network mask is compared. IPv4: /24 and IPv6 /48. This is different
+ * from the path selection that looks at /16 and /32 because we only
+ * want to learn here if the address is considered to come from the
+ * Internet basically.
+ *
+ * @param addr The address to test if local and also test against our resovled
+ * address.
+ *
+ * @return True iff address is considered local or else False.
*/
-MOCK_IMPL(int,
-is_local_addr, (const tor_addr_t *addr))
+MOCK_IMPL(bool,
+is_local_to_resolve_addr, (const tor_addr_t *addr))
{
- if (tor_addr_is_internal(addr, 0))
- return 1;
- /* Check whether ip is on the same /24 as we are. */
- if (get_options()->EnforceDistinctSubnets == 0)
- return 0;
- if (tor_addr_family(addr) == AF_INET) {
- uint32_t ip = tor_addr_to_ipv4h(addr);
+ const int family = tor_addr_family(addr);
+ const tor_addr_t *last_resolved_addr =
+ &last_resolved_addrs[af_to_idx(family)];
+
+ /* Internal address is always local. */
+ if (tor_addr_is_internal(addr, 0)) {
+ return true;
+ }
+ /* Address is not local if we don't enforce subnet distinction. */
+ if (get_options()->EnforceDistinctSubnets == 0) {
+ return false;
+ }
+
+ switch (family) {
+ case AF_INET:
/* It's possible that this next check will hit before the first time
- * resolve_my_address actually succeeds. (For clients, it is likely that
- * resolve_my_address will never be called at all). In those cases,
- * last_resolved_addr will be 0, and so checking to see whether ip is on
- * the same /24 as last_resolved_addr will be the same as checking whether
- * it was on net 0, which is already done by tor_addr_is_internal.
- */
- if ((last_resolved_addr & (uint32_t)0xffffff00ul)
- == (ip & (uint32_t)0xffffff00ul))
- return 1;
+ * find_my_address actually succeeds. For clients, it is likely that
+ * find_my_address will never be called at all. In those cases,
+ * last_resolved_addr_v4 will be 0, and so checking to see whether ip is
+ * on the same /24 as last_resolved_addrs[AF_INET] will be the same as
+ * checking whether it was on net 0, which is already done by
+ * tor_addr_is_internal. */
+ return tor_addr_compare_masked(addr, last_resolved_addr, 24,
+ CMP_SEMANTIC) == 0;
+ case AF_INET6:
+ /* Look at /48 because it is typically the smallest network in the global
+ * IPv6 routing tables, and it was previously the recommended per-customer
+ * network block. (See [RFC 6177: IPv6 End Site Address Assignment].) */
+ return tor_addr_compare_masked(addr, last_resolved_addr, 48,
+ CMP_SEMANTIC) == 0;
+ break;
+ default:
+ /* Unknown address type so not local. */
+ return false;
}
- return 0;
}
+
+#ifdef TOR_UNIT_TESTS
+
+void
+resolve_addr_reset_suggested(int family)
+{
+ tor_addr_make_unspec(&last_suggested_addrs[af_to_idx(family)]);
+}
+
+#endif /* TOR_UNIT_TESTS */
diff --git a/src/app/config/resolve_addr.h b/src/app/config/resolve_addr.h
index 3747546402..919d5d42cc 100644
--- a/src/app/config/resolve_addr.h
+++ b/src/app/config/resolve_addr.h
@@ -9,19 +9,58 @@
#ifndef TOR_CONFIG_RESOLVE_ADDR_H
#define TOR_CONFIG_RESOLVE_ADDR_H
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+
#include "app/config/or_options_st.h"
-int resolve_my_address(int warn_severity, const or_options_t *options,
- uint32_t *addr_out,
- const char **method_out, char **hostname_out);
+/** Method used to resolved an address. In other words, how was the address
+ * discovered by tor. */
+typedef enum {
+ /* Default value. Indicate that no method found the address. */
+ RESOLVED_ADDR_NONE = 0,
+ /* Found from the "Address" configuration option. */
+ RESOLVED_ADDR_CONFIGURED = 1,
+ /* Found from the "ORPort" configuration option. */
+ RESOLVED_ADDR_CONFIGURED_ORPORT = 2,
+ /* Found by resolving the local hostname. */
+ RESOLVED_ADDR_GETHOSTNAME = 3,
+ /* Found by querying the local interface(s). */
+ RESOLVED_ADDR_INTERFACE = 4,
+ /* Found by resolving the hostname from the Address configuration option. */
+ RESOLVED_ADDR_RESOLVED = 5,
+} resolved_addr_method_t;
+
+const char *resolved_addr_method_to_str(const resolved_addr_method_t method);
+
+#define get_orport_addr(family) \
+ (portconf_get_first_advertised_addr(CONN_TYPE_OR_LISTENER, family))
+
+bool find_my_address(const or_options_t *options, int family,
+ int warn_severity, tor_addr_t *addr_out,
+ resolved_addr_method_t *method_out, char **hostname_out);
+
+void resolved_addr_get_last(int family, tor_addr_t *addr_out);
+void resolved_addr_reset_last(int family);
+void resolved_addr_set_last(const tor_addr_t *addr,
+ const resolved_addr_method_t method_used,
+ const char *hostname_used);
-uint32_t get_last_resolved_addr(void);
-void reset_last_resolved_addr(void);
+void resolved_addr_get_suggested(int family, tor_addr_t *addr_out);
+void resolved_addr_set_suggested(const tor_addr_t *addr);
-MOCK_DECL(int, is_local_addr, (const tor_addr_t *addr));
+bool resolved_addr_is_configured(int family);
+
+MOCK_DECL(bool, is_local_to_resolve_addr, (const tor_addr_t *addr));
#ifdef RESOLVE_ADDR_PRIVATE
+#ifdef TOR_UNIT_TESTS
+
+void resolve_addr_reset_suggested(int family);
+
+#endif /* TOR_UNIT_TESTS */
+
#endif /* RESOLVE_ADDR_PRIVATE */
#endif /* TOR_CONFIG_RESOLVE_ADDR_H */
diff --git a/src/app/config/statefile.c b/src/app/config/statefile.c
index dcc55f1898..22b15fcf24 100644
--- a/src/app/config/statefile.c
+++ b/src/app/config/statefile.c
@@ -40,7 +40,7 @@
#include "feature/control/control_events.h"
#include "feature/client/entrynodes.h"
#include "feature/hibernate/hibernate.h"
-#include "feature/stats/rephist.h"
+#include "feature/stats/bwhist.h"
#include "feature/relay/router.h"
#include "feature/relay/routermode.h"
#include "lib/sandbox/sandbox.h"
@@ -58,16 +58,38 @@
/** A list of state-file "abbreviations," for compatibility. */
static config_abbrev_t state_abbrevs_[] = {
- { "AccountingBytesReadInterval", "AccountingBytesReadInInterval", 0, 0 },
- { "HelperNode", "EntryGuard", 0, 0 },
- { "HelperNodeDownSince", "EntryGuardDownSince", 0, 0 },
- { "HelperNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 },
- { "EntryNode", "EntryGuard", 0, 0 },
- { "EntryNodeDownSince", "EntryGuardDownSince", 0, 0 },
- { "EntryNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 },
{ NULL, NULL, 0, 0},
};
+/** A list of obsolete keys that we do not and should not preserve.
+ *
+ * We could just let these live in ExtraLines indefinitely, but they're
+ * never going to be used again, and every version that used them
+ * has been obsolete for a long time.
+ * */
+static const char *obsolete_state_keys[] = {
+ /* These were renamed in 0.1.1.11-alpha */
+ "AccountingBytesReadInterval",
+ "HelperNode",
+ "HelperNodeDownSince",
+ "HelperNodeUnlistedSince",
+ "EntryNode",
+ "HelperNodeDownSince",
+ "EntryNodeUnlistedSince",
+ /* These were replaced by "Guard" in 0.3.0.1-alpha. */
+ "EntryGuard",
+ "EntryGuardDownSince",
+ "EntryGuardUnlistedSince",
+ "EntryGuardAddedBy",
+ "EntryGuardPathBias",
+ "EntryGuardPathUseBias",
+ /* This was replaced by OPE-based revision numbers in 0.3.5.1-alpha,
+ * and was never actually used in a released version. */
+ "HidServRevCounter",
+
+ NULL,
+};
+
/** dummy instance of or_state_t, used for type-checking its
* members with CONF_CHECK_VAR_TYPE. */
DUMMY_TYPECHECK_INSTANCE(or_state_t);
@@ -91,19 +113,9 @@ static const config_var_t state_vars_[] = {
V(AccountingSoftLimitHitAt, ISOTIME, NULL),
V(AccountingBytesAtSoftLimit, MEMUNIT, NULL),
- VAR("EntryGuard", LINELIST_S, EntryGuards, NULL),
- VAR("EntryGuardDownSince", LINELIST_S, EntryGuards, NULL),
- VAR("EntryGuardUnlistedSince", LINELIST_S, EntryGuards, NULL),
- VAR("EntryGuardAddedBy", LINELIST_S, EntryGuards, NULL),
- VAR("EntryGuardPathBias", LINELIST_S, EntryGuards, NULL),
- VAR("EntryGuardPathUseBias", LINELIST_S, EntryGuards, NULL),
- V(EntryGuards, LINELIST_V, NULL),
-
VAR("TransportProxy", LINELIST_S, TransportProxies, NULL),
V(TransportProxies, LINELIST_V, NULL),
- V(HidServRevCounter, LINELIST, NULL),
-
V(BWHistoryReadEnds, ISOTIME, NULL),
V(BWHistoryReadInterval, POSINT, "900"),
V(BWHistoryReadValues, CSV, ""),
@@ -112,6 +124,14 @@ static const config_var_t state_vars_[] = {
V(BWHistoryWriteInterval, POSINT, "900"),
V(BWHistoryWriteValues, CSV, ""),
V(BWHistoryWriteMaxima, CSV, ""),
+ V(BWHistoryIPv6ReadEnds, ISOTIME, NULL),
+ V(BWHistoryIPv6ReadInterval, POSINT, "900"),
+ V(BWHistoryIPv6ReadValues, CSV, ""),
+ V(BWHistoryIPv6ReadMaxima, CSV, ""),
+ V(BWHistoryIPv6WriteEnds, ISOTIME, NULL),
+ V(BWHistoryIPv6WriteInterval, POSINT, "900"),
+ V(BWHistoryIPv6WriteValues, CSV, ""),
+ V(BWHistoryIPv6WriteMaxima, CSV, ""),
V(BWHistoryDirReadEnds, ISOTIME, NULL),
V(BWHistoryDirReadInterval, POSINT, "900"),
V(BWHistoryDirReadValues, CSV, ""),
@@ -324,7 +344,7 @@ or_state_set(or_state_t *new_state)
tor_free(err);
ret = -1;
}
- if (rep_hist_load_state(global_state, &err)<0) {
+ if (bwhist_load_state(global_state, &err)<0) {
log_warn(LD_GENERAL,"Unparseable bandwidth history state: %s",err);
tor_free(err);
ret = -1;
@@ -467,6 +487,7 @@ or_state_load(void)
} else {
log_info(LD_GENERAL, "Initialized state");
}
+ or_state_remove_obsolete_lines(&new_state->ExtraLines);
if (or_state_set(new_state) == -1) {
or_state_save_broken(fname);
}
@@ -486,6 +507,36 @@ or_state_load(void)
return r;
}
+/** Remove from `extra_lines` every element whose key appears in
+ * `obsolete_state_keys`. */
+STATIC void
+or_state_remove_obsolete_lines(config_line_t **extra_lines)
+{
+ /* make a strmap for the obsolete state names, so we can have O(1)
+ lookup. */
+ strmap_t *bad_keys = strmap_new();
+ for (unsigned i = 0; obsolete_state_keys[i] != NULL; ++i) {
+ strmap_set_lc(bad_keys, obsolete_state_keys[i], (void*)"rmv");
+ }
+
+ config_line_t **line = extra_lines;
+ while (*line) {
+ if (strmap_get_lc(bad_keys, (*line)->key) != NULL) {
+ /* This key is obsolete; remove it. */
+ config_line_t *victim = *line;
+ *line = (*line)->next;
+
+ victim->next = NULL; // prevent double-free.
+ config_free_lines(victim);
+ } else {
+ /* This is just an unrecognized key; keep it. */
+ line = &(*line)->next;
+ }
+ }
+
+ strmap_free(bad_keys, NULL);
+}
+
/** Did the last time we tried to write the state file fail? If so, we
* should consider disabling such features as preemptive circuit generation
* to compute circuit-build-time. */
@@ -523,7 +574,7 @@ or_state_save(time_t now)
* 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);
+ bwhist_update_state(global_state);
circuit_build_times_update_state(get_circuit_build_times(), global_state);
if (accounting_is_enabled(get_options()))
diff --git a/src/app/config/statefile.h b/src/app/config/statefile.h
index 98d9d2dda1..89b10560f3 100644
--- a/src/app/config/statefile.h
+++ b/src/app/config/statefile.h
@@ -33,6 +33,7 @@ STATIC void or_state_free_(or_state_t *state);
STATIC or_state_t *or_state_new(void);
struct config_mgr_t;
STATIC const struct config_mgr_t *get_state_mgr(void);
+STATIC void or_state_remove_obsolete_lines(struct config_line_t **extra_lines);
#endif /* defined(STATEFILE_PRIVATE) */
#endif /* !defined(TOR_STATEFILE_H) */
diff --git a/src/app/config/testnet.inc b/src/app/config/testnet.inc
index 907c35f97c..00b307782b 100644
--- a/src/app/config/testnet.inc
+++ b/src/app/config/testnet.inc
@@ -1,8 +1,7 @@
// When modifying, don't forget to update the defaults
-// for 'TestingTorNetwork' in 'doc/tor.1.txt'
+// for 'TestingTorNetwork' in 'doc/man/tor.1.txt'
{ "DirAllowPrivateAddresses", "1" },
{ "EnforceDistinctSubnets", "0" },
-{ "AssumeReachable", "1" },
{ "AuthDirMaxServersPerAddr", "0" },
{ "ClientBootstrapConsensusAuthorityDownloadInitialDelay", "0" },
{ "ClientBootstrapConsensusFallbackDownloadInitialDelay", "0" },
diff --git a/src/app/include.am b/src/app/include.am
index 97d53ec0fd..8bb315fff1 100644
--- a/src/app/include.am
+++ b/src/app/include.am
@@ -14,22 +14,24 @@ src_app_tor_SOURCES = src/app/main/tor_main.c
# This seems to matter nowhere but on windows, but I assure you that it
# matters a lot there, and is quite hard to debug if you forget to do it.
-src_app_tor_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) @TOR_LDFLAGS_libevent@
-src_app_tor_LDADD = $(TOR_INTERNAL_LIBS) \
+src_app_tor_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) \
+ @TOR_LDFLAGS_libevent@ @TOR_STATIC_LDFLAGS@
+src_app_tor_LDADD = libtor.a \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ $(TOR_LIBS_CRYPTLIB) \
- @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
+ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
@CURVE25519_LIBS@ @TOR_SYSTEMD_LIBS@ \
- @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
+ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ @TOR_TRACE_LIBS@
if COVERAGE_ENABLED
src_app_tor_cov_SOURCES = $(src_app_tor_SOURCES)
src_app_tor_cov_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
src_app_tor_cov_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
-src_app_tor_cov_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) @TOR_LDFLAGS_libevent@
-src_app_tor_cov_LDADD = $(TOR_INTERNAL_TESTING_LIBS) \
+src_app_tor_cov_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) \
+ @TOR_LDFLAGS_libevent@ @TOR_STATIC_LDFALGS@
+src_app_tor_cov_LDADD = src/test/libtor-testing.a \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ $(TOR_LIBS_CRYPTLIB) \
- @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ \
+ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ \
@CURVE25519_LIBS@ @TOR_SYSTEMD_LIBS@ \
- @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
+ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ @TOR_TRACE_LIBS@
endif
diff --git a/src/app/main/include.am b/src/app/main/include.am
index ea392a8581..576c750377 100644
--- a/src/app/main/include.am
+++ b/src/app/main/include.am
@@ -2,6 +2,7 @@
# ADD_C_FILE: INSERT SOURCES HERE.
LIBTOR_APP_A_SOURCES += \
src/app/main/main.c \
+ src/app/main/risky_options.c \
src/app/main/shutdown.c \
src/app/main/subsystem_list.c \
src/app/main/subsysmgr.c
@@ -10,6 +11,7 @@ LIBTOR_APP_A_SOURCES += \
noinst_HEADERS += \
src/app/main/main.h \
src/app/main/ntmain.h \
+ src/app/main/risky_options.h \
src/app/main/shutdown.h \
src/app/main/subsysmgr.h
diff --git a/src/app/main/main.c b/src/app/main/main.c
index fd166638db..56478a0f71 100644
--- a/src/app/main/main.c
+++ b/src/app/main/main.c
@@ -16,6 +16,7 @@
#include "app/config/quiet_level.h"
#include "app/main/main.h"
#include "app/main/ntmain.h"
+#include "app/main/risky_options.h"
#include "app/main/shutdown.h"
#include "app/main/subsysmgr.h"
#include "core/mainloop/connection.h"
@@ -53,18 +54,21 @@
#include "feature/rend/rendcache.h"
#include "feature/rend/rendservice.h"
#include "feature/stats/predict_ports.h"
+#include "feature/stats/bwhist.h"
#include "feature/stats/rephist.h"
#include "lib/compress/compress.h"
#include "lib/buf/buffers.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_s2k.h"
#include "lib/net/resolve.h"
+#include "lib/trace/trace.h"
#include "lib/process/waitpid.h"
#include "lib/pubsub/pubsub_build.h"
#include "lib/meminfo/meminfo.h"
#include "lib/osinfo/uname.h"
+#include "lib/osinfo/libc.h"
#include "lib/sandbox/sandbox.h"
#include "lib/fs/lockfile.h"
#include "lib/tls/tortls.h"
@@ -295,7 +299,7 @@ process_signal(int sig)
}
#ifdef _WIN32
-/** Activate SIGINT on reciving a control signal in console */
+/** Activate SIGINT on receiving a control signal in console. */
static BOOL WINAPI
process_win32_console_ctrl(DWORD ctrl_type)
{
@@ -335,16 +339,12 @@ dumpstats(int severity)
SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
int i = conn_sl_idx;
tor_log(severity, LD_GENERAL,
- "Conn %d (socket %d) type %d (%s), state %d (%s), created %d secs ago",
- i, (int)conn->s, conn->type, conn_type_to_string(conn->type),
- conn->state, conn_state_to_string(conn->type, conn->state),
+ "Conn %d (socket %d) is a %s, created %d secs ago",
+ i, (int)conn->s,
+ connection_describe(conn),
(int)(now - conn->timestamp_created));
if (!connection_is_listener(conn)) {
tor_log(severity,LD_GENERAL,
- "Conn %d is to %s:%d.", i,
- safe_str_client(conn->address),
- conn->port);
- tor_log(severity,LD_GENERAL,
"Conn %d: %d bytes waiting on inbuf (len %d, last read %d secs ago)",
i,
(int)connection_get_inbuf_len(conn),
@@ -539,6 +539,7 @@ tor_init(int argc, char *argv[])
{
char progname[256];
quiet_level_t quiet = QUIET_NONE;
+ bool running_tor = false;
time_of_process_start = time(NULL);
tor_init_connection_lists();
@@ -548,6 +549,7 @@ tor_init(int argc, char *argv[])
/* Initialize the history structures. */
rep_hist_init();
+ bwhist_init();
/* Initialize the service cache. */
rend_cache_init();
addressmap_init(); /* Init the client dns cache. Do it always, since it's
@@ -561,8 +563,10 @@ tor_init(int argc, char *argv[])
whether we log anything at all to stdout. */
parsed_cmdline_t *cmdline;
cmdline = config_parse_commandline(argc, argv, 1);
- if (cmdline)
+ if (cmdline) {
quiet = cmdline->quiet_level;
+ running_tor = (cmdline->command == CMD_RUN_TOR);
+ }
parsed_cmdline_free(cmdline);
}
@@ -574,7 +578,8 @@ tor_init(int argc, char *argv[])
const char *version = get_version();
log_notice(LD_GENERAL, "Tor %s running on %s with Libevent %s, "
- "%s %s, Zlib %s, Liblzma %s, and Libzstd %s.", version,
+ "%s %s, Zlib %s, Liblzma %s, Libzstd %s and %s %s as libc.",
+ version,
get_uname(),
tor_libevent_get_version_str(),
crypto_get_library_name(),
@@ -584,7 +589,10 @@ tor_init(int argc, char *argv[])
tor_compress_supports_method(LZMA_METHOD) ?
tor_compress_version_str(LZMA_METHOD) : "N/A",
tor_compress_supports_method(ZSTD_METHOD) ?
- tor_compress_version_str(ZSTD_METHOD) : "N/A");
+ tor_compress_version_str(ZSTD_METHOD) : "N/A",
+ tor_libc_get_name() ?
+ tor_libc_get_name() : "Unknown",
+ tor_libc_get_version_str());
log_notice(LD_GENERAL, "Tor can't help you if you use it wrong! "
"Learn how to be safe at "
@@ -594,6 +602,12 @@ tor_init(int argc, char *argv[])
log_notice(LD_GENERAL, "This version is not a stable Tor release. "
"Expect more bugs than usual.");
+ if (strlen(risky_option_list) && running_tor) {
+ log_warn(LD_GENERAL, "This build of Tor has been compiled with one "
+ "or more options that might make it less reliable or secure! "
+ "They are:%s", risky_option_list);
+ }
+
tor_compress_log_init_warnings();
}
@@ -601,6 +615,9 @@ tor_init(int argc, char *argv[])
rust_log_welcome_string();
#endif /* defined(HAVE_RUST) */
+ /* Warn _if_ the tracing subsystem is built in. */
+ tracing_log_warning();
+
int init_rv = options_init_from_torrc(argc,argv);
if (init_rv < 0) {
log_err(LD_CONFIG,"Reading config failed--see warnings above.");
@@ -774,12 +791,14 @@ do_dump_config(void)
if (!strcmp(arg, "short")) {
how = OPTIONS_DUMP_MINIMAL;
} else if (!strcmp(arg, "non-builtin")) {
- how = OPTIONS_DUMP_DEFAULTS;
+ // Deprecated since 0.4.5.1-alpha.
+ fprintf(stderr, "'non-builtin' is deprecated; use 'short' instead.\n");
+ how = OPTIONS_DUMP_MINIMAL;
} else if (!strcmp(arg, "full")) {
how = OPTIONS_DUMP_ALL;
} else {
fprintf(stderr, "No valid argument to --dump-config found!\n");
- fprintf(stderr, "Please select 'short', 'non-builtin', or 'full'.\n");
+ fprintf(stderr, "Please select 'short' or 'full'.\n");
return -1;
}
@@ -794,8 +813,7 @@ do_dump_config(void)
static void
init_addrinfo(void)
{
- if (! server_mode(get_options()) ||
- (get_options()->Address && strlen(get_options()->Address) > 0)) {
+ if (! server_mode(get_options()) || get_options()->Address) {
/* We don't need to seed our own hostname, because we won't be calling
* resolve_my_address on it.
*/
@@ -1064,12 +1082,14 @@ sandbox_init_filter(void)
OPEN_DATADIR("approved-routers");
OPEN_DATADIR_SUFFIX("fingerprint", ".tmp");
+ OPEN_DATADIR_SUFFIX("fingerprint-ed25519", ".tmp");
OPEN_DATADIR_SUFFIX("hashed-fingerprint", ".tmp");
OPEN_DATADIR_SUFFIX("router-stability", ".tmp");
OPEN("/etc/resolv.conf");
RENAME_SUFFIX("fingerprint", ".tmp");
+ RENAME_SUFFIX("fingerprint-ed25519", ".tmp");
RENAME_KEYDIR_SUFFIX("secret_onion_key_ntor", ".tmp");
RENAME_KEYDIR_SUFFIX("secret_id_key", ".tmp");
diff --git a/src/app/main/risky_options.c b/src/app/main/risky_options.c
new file mode 100644
index 0000000000..747dda766b
--- /dev/null
+++ b/src/app/main/risky_options.c
@@ -0,0 +1,35 @@
+/* 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 risky_options.c
+ * \brief List compile-time options that might make Tor less reliable.
+ **/
+
+#include "orconfig.h"
+#include "app/main/risky_options.h"
+
+/** A space-separated list of the compile-time options might make Tor less
+ * reliable or secure. These options mainly exist for testing or debugging.
+ */
+const char risky_option_list[] =
+ ""
+#ifdef DISABLE_ASSERTS_IN_TEST
+ " --disable-asserts-in-test"
+#endif
+#ifdef TOR_UNIT_TESTS
+ " TOR_UNIT_TESTS"
+#endif
+#ifdef ENABLE_RESTART_DEBUGGING
+ " --enable-restart-debugging"
+#endif
+#ifdef ALL_BUGS_ARE_FATAL
+ " --enable-all-bugs-are-fatal"
+#endif
+#ifdef DISABLE_MEMORY_SENTINELS
+ " --disable-memory-sentinels"
+#endif
+ ;
diff --git a/src/app/main/risky_options.h b/src/app/main/risky_options.h
new file mode 100644
index 0000000000..4548ae3efb
--- /dev/null
+++ b/src/app/main/risky_options.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 risky_options.h
+ * \brief Header for risky_options.c
+ **/
+
+#ifndef TOR_RISKY_OPTIONS_H
+#define TOR_RISKY_OPTIONS_H
+
+extern const char risky_option_list[];
+
+#endif
diff --git a/src/app/main/shutdown.c b/src/app/main/shutdown.c
index aac15246b9..4a556333db 100644
--- a/src/app/main/shutdown.c
+++ b/src/app/main/shutdown.c
@@ -47,6 +47,7 @@
#include "feature/relay/relay_config.h"
#include "feature/rend/rendcache.h"
#include "feature/rend/rendclient.h"
+#include "feature/stats/bwhist.h"
#include "feature/stats/geoip_stats.h"
#include "feature/stats/rephist.h"
#include "lib/evloop/compat_libevent.h"
@@ -121,6 +122,7 @@ tor_free_all(int postfork)
rend_cache_free_all();
rend_service_authorization_free_all();
rep_hist_free_all();
+ bwhist_free_all();
circuit_free_all();
circpad_machines_free();
entry_guards_free_all();
diff --git a/src/app/main/subsysmgr.c b/src/app/main/subsysmgr.c
index de601d28cd..349803cd46 100644
--- a/src/app/main/subsysmgr.c
+++ b/src/app/main/subsysmgr.c
@@ -300,7 +300,7 @@ subsystems_thread_cleanup(void)
void
subsystems_dump_list(void)
{
- for (unsigned i = 0; i < n_tor_subsystems - 1; ++i) {
+ for (unsigned i = 0; i < n_tor_subsystems; ++i) {
const subsys_fns_t *sys = tor_subsystems[i];
printf("% 4d\t%16s\t%s\n", sys->level, sys->name,
sys->location?sys->location:"");
diff --git a/src/app/main/subsystem_list.c b/src/app/main/subsystem_list.c
index e32083537f..cb79909e69 100644
--- a/src/app/main/subsystem_list.c
+++ b/src/app/main/subsystem_list.c
@@ -26,10 +26,13 @@
#include "lib/thread/thread_sys.h"
#include "lib/time/time_sys.h"
#include "lib/tls/tortls_sys.h"
+#include "lib/trace/trace_sys.h"
#include "lib/wallclock/wallclock_sys.h"
#include "lib/evloop/evloop_sys.h"
#include "feature/dirauth/dirauth_sys.h"
+#include "feature/hs/hs_sys.h"
+#include "feature/metrics/metrics_sys.h"
#include "feature/relay/relay_sys.h"
#include <stddef.h>
@@ -47,6 +50,8 @@ const subsys_fns_t *tor_subsystems[] = {
&sys_logging,
&sys_threads,
+ &sys_tracing,
+
&sys_time,
&sys_crypto,
@@ -61,10 +66,12 @@ const subsys_fns_t *tor_subsystems[] = {
&sys_or,
&sys_relay,
+ &sys_hs,
&sys_btrack,
&sys_dirauth,
+ &sys_metrics,
};
const unsigned n_tor_subsystems = ARRAY_LENGTH(tor_subsystems);
diff --git a/src/config/torrc.minimal.in-staging b/src/config/torrc.minimal.in-staging
index 90bad7f7cc..7f43cd324e 100644
--- a/src/config/torrc.minimal.in-staging
+++ b/src/config/torrc.minimal.in-staging
@@ -88,7 +88,7 @@
## yourself to make this work.
#ORPort 443 NoListen
#ORPort 127.0.0.1:9090 NoAdvertise
-## If you want to listen on IPv6 your numeric address must be explictly
+## If you want to listen on IPv6 your numeric address must be explicitly
## between square brackets as follows. You must also listen on IPv4.
#ORPort [2001:DB8::1]:9050
diff --git a/src/config/torrc.sample.in b/src/config/torrc.sample.in
index 51e1c3af4b..5d593871dd 100644
--- a/src/config/torrc.sample.in
+++ b/src/config/torrc.sample.in
@@ -88,7 +88,7 @@
## yourself to make this work.
#ORPort 443 NoListen
#ORPort 127.0.0.1:9090 NoAdvertise
-## If you want to listen on IPv6 your numeric address must be explictly
+## If you want to listen on IPv6 your numeric address must be explicitly
## between square brackets as follows. You must also listen on IPv4.
#ORPort [2001:DB8::1]:9050
@@ -242,11 +242,12 @@
#PublishServerDescriptor 0
## Configuration options can be imported from files or folders using the %include
-## option with the value being a path. If the path is a file, the options from the
-## file will be parsed as if they were written where the %include option is. If
-## the path is a folder, all files on that folder will be parsed following lexical
-## order. Files starting with a dot are ignored. Files on subfolders are ignored.
+## option with the value being a path. This path can have wildcards. Wildcards are
+## expanded first, using lexical order. Then, for each matching file or folder, the following
+## rules are followed: if the path is a file, the options from the file will be parsed as if
+## they were written where the %include option is. If the path is a folder, all files on that
+## folder will be parsed following lexical order. Files starting with a dot are ignored. Files
+## on subfolders are ignored.
## The %include option can be used recursively.
-#%include /etc/torrc.d/
-#%include /etc/torrc.custom
+#%include /etc/torrc.d/*.conf
diff --git a/src/core/crypto/onion_crypto.c b/src/core/crypto/onion_crypto.c
index 69b4dc40aa..1f34be1cc1 100644
--- a/src/core/crypto/onion_crypto.c
+++ b/src/core/crypto/onion_crypto.c
@@ -31,7 +31,7 @@
**/
#include "core/or/or.h"
-#include "core/or/circuitbuild.h"
+#include "core/or/extendinfo.h"
#include "core/crypto/onion_crypto.h"
#include "core/crypto/onion_fast.h"
#include "core/crypto/onion_ntor.h"
diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c
index 36b2c6ef63..ada542629a 100644
--- a/src/core/mainloop/connection.c
+++ b/src/core/mainloop/connection.c
@@ -82,6 +82,7 @@
#include "core/or/policies.h"
#include "core/or/reasons.h"
#include "core/or/relay.h"
+#include "core/or/status.h"
#include "core/or/crypt_path.h"
#include "core/proto/proto_haproxy.h"
#include "core/proto/proto_http.h"
@@ -98,6 +99,8 @@
#include "feature/hibernate/hibernate.h"
#include "feature/hs/hs_common.h"
#include "feature/hs/hs_ident.h"
+#include "feature/hs/hs_metrics.h"
+#include "feature/metrics/metrics.h"
#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerlist.h"
#include "feature/relay/dns.h"
@@ -105,8 +108,11 @@
#include "feature/relay/routermode.h"
#include "feature/rend/rendclient.h"
#include "feature/rend/rendcommon.h"
+#include "feature/stats/connstats.h"
#include "feature/stats/rephist.h"
+#include "feature/stats/bwhist.h"
#include "lib/crypt_ops/crypto_util.h"
+#include "lib/crypt_ops/crypto_format.h"
#include "lib/geoip/geoip.h"
#include "lib/cc/ctassert.h"
@@ -214,12 +220,17 @@ static smartlist_t *outgoing_addrs = NULL;
case CONN_TYPE_AP_TRANS_LISTENER: \
case CONN_TYPE_AP_NATD_LISTENER: \
case CONN_TYPE_AP_DNS_LISTENER: \
- case CONN_TYPE_AP_HTTP_CONNECT_LISTENER
+ case CONN_TYPE_AP_HTTP_CONNECT_LISTENER: \
+ case CONN_TYPE_METRICS_LISTENER
/**************************************************************/
-/** Convert a connection_t* to an listener_connection_t*; assert if the cast
- * is invalid. */
+/**
+ * Cast a `connection_t *` to a `listener_connection_t *`.
+ *
+ * Exit with an assertion failure if the input is not a
+ * `listener_connection_t`.
+ **/
listener_connection_t *
TO_LISTENER_CONN(connection_t *c)
{
@@ -227,6 +238,18 @@ TO_LISTENER_CONN(connection_t *c)
return DOWNCAST(listener_connection_t, c);
}
+/**
+ * Cast a `const connection_t *` to a `const listener_connection_t *`.
+ *
+ * Exit with an assertion failure if the input is not a
+ * `listener_connection_t`.
+ **/
+const listener_connection_t *
+CONST_TO_LISTENER_CONN(const connection_t *c)
+{
+ return TO_LISTENER_CONN((connection_t *)c);
+}
+
size_t
connection_get_inbuf_len(connection_t *conn)
{
@@ -263,6 +286,8 @@ conn_type_to_string(int type)
case CONN_TYPE_EXT_OR: return "Extended OR";
case CONN_TYPE_EXT_OR_LISTENER: return "Extended OR listener";
case CONN_TYPE_AP_HTTP_CONNECT_LISTENER: return "HTTP tunnel listener";
+ case CONN_TYPE_METRICS_LISTENER: return "Metrics listener";
+ case CONN_TYPE_METRICS: return "Metrics";
default:
log_warn(LD_BUG, "unknown connection type %d", type);
tor_snprintf(buf, sizeof(buf), "unknown [%d]", type);
@@ -350,13 +375,187 @@ conn_state_to_string(int type, int state)
break;
}
+ if (state == 0) {
+ return "uninitialized";
+ }
+
log_warn(LD_BUG, "unknown connection state %d (type %d)", state, type);
tor_snprintf(buf, sizeof(buf),
"unknown state [%d] on unknown [%s] connection",
state, conn_type_to_string(type));
+ tor_assert_nonfatal_unreached_once();
return buf;
}
+/**
+ * Helper: describe the peer or address of connection @a conn in a
+ * human-readable manner.
+ *
+ * Returns a pointer to a static buffer; future calls to
+ * connection_describe_peer_internal() will invalidate this buffer.
+ *
+ * If <b>include_preposition</b> is true, include a preposition before the
+ * peer address.
+ *
+ * Nobody should parse the output of this function; it can and will change in
+ * future versions of tor.
+ **/
+static const char *
+connection_describe_peer_internal(const connection_t *conn,
+ bool include_preposition)
+{
+ IF_BUG_ONCE(!conn) {
+ return "null peer";
+ }
+
+ static char peer_buf[256];
+ const tor_addr_t *addr = &conn->addr;
+ const char *address = NULL;
+ const char *prep;
+ bool scrub = false;
+ char extra_buf[128];
+ extra_buf[0] = 0;
+
+ /* First, figure out the preposition to use */
+ switch (conn->type) {
+ CASE_ANY_LISTENER_TYPE:
+ prep = "on";
+ break;
+ case CONN_TYPE_EXIT:
+ prep = "to";
+ break;
+ case CONN_TYPE_CONTROL:
+ case CONN_TYPE_AP:
+ case CONN_TYPE_EXT_OR:
+ prep = "from";
+ break;
+ default:
+ prep = "with";
+ break;
+ }
+
+ /* Now figure out the address. */
+ if (conn->socket_family == AF_UNIX) {
+ /* For unix sockets, we always use the `address` string. */
+ address = conn->address ? conn->address : "unix socket";
+ } else if (conn->type == CONN_TYPE_OR) {
+ /* For OR connections, we have a lot to do. */
+ const or_connection_t *or_conn = CONST_TO_OR_CONN(conn);
+ /* We report the IDs we're talking to... */
+ if (fast_digest_is_zero(or_conn->identity_digest)) {
+ // This could be a client, so scrub it. No identity to report.
+ scrub = true;
+ } else {
+ const ed25519_public_key_t *ed_id =
+ connection_or_get_alleged_ed25519_id(or_conn);
+ char ed_id_buf[ED25519_BASE64_LEN+1];
+ char rsa_id_buf[HEX_DIGEST_LEN+1];
+ if (ed_id) {
+ ed25519_public_to_base64(ed_id_buf, ed_id);
+ } else {
+ strlcpy(ed_id_buf, "<none>", sizeof(ed_id_buf));
+ }
+ base16_encode(rsa_id_buf, sizeof(rsa_id_buf),
+ or_conn->identity_digest, DIGEST_LEN);
+ tor_snprintf(extra_buf, sizeof(extra_buf),
+ " ID=%s RSA_ID=%s", ed_id_buf, rsa_id_buf);
+ }
+ if (! scrub && (! tor_addr_eq(addr, &or_conn->canonical_orport.addr) ||
+ conn->port != or_conn->canonical_orport.port)) {
+ /* We report canonical address, if it's different */
+ char canonical_addr_buf[TOR_ADDR_BUF_LEN];
+ if (tor_addr_to_str(canonical_addr_buf, &or_conn->canonical_orport.addr,
+ sizeof(canonical_addr_buf), 1)) {
+ tor_snprintf(extra_buf+strlen(extra_buf),
+ sizeof(extra_buf)-strlen(extra_buf),
+ " canonical_addr=%s:%"PRIu16,
+ canonical_addr_buf,
+ or_conn->canonical_orport.port);
+ }
+ }
+ } else if (conn->type == CONN_TYPE_EXIT) {
+ scrub = true; /* This is a client's request; scrub it with SafeLogging. */
+ if (tor_addr_is_null(addr)) {
+ address = conn->address;
+ strlcpy(extra_buf, " (DNS lookup pending)", sizeof(extra_buf));
+ }
+ }
+
+ char addr_buf[TOR_ADDR_BUF_LEN];
+ if (address == NULL) {
+ if (tor_addr_family(addr) == 0) {
+ address = "<unset>";
+ } else {
+ address = tor_addr_to_str(addr_buf, addr, sizeof(addr_buf), 1);
+ if (!address) {
+ address = "<can't format!>";
+ tor_assert_nonfatal_unreached_once();
+ }
+ }
+ }
+
+ char portbuf[7];
+ portbuf[0]=0;
+ if (scrub && get_options()->SafeLogging_ != SAFELOG_SCRUB_NONE) {
+ address = "[scrubbed]";
+ } else {
+ /* Only set the port if we're not scrubbing the address. */
+ if (conn->port != 0) {
+ tor_snprintf(portbuf, sizeof(portbuf), ":%d", conn->port);
+ }
+ }
+
+ const char *sp = include_preposition ? " " : "";
+ if (! include_preposition)
+ prep = "";
+
+ tor_snprintf(peer_buf, sizeof(peer_buf),
+ "%s%s%s%s%s", prep, sp, address, portbuf, extra_buf);
+ return peer_buf;
+}
+
+/**
+ * Describe the peer or address of connection @a conn in a
+ * human-readable manner.
+ *
+ * Returns a pointer to a static buffer; future calls to
+ * connection_describe_peer() or connection_describe() will invalidate this
+ * buffer.
+ *
+ * Nobody should parse the output of this function; it can and will change in
+ * future versions of tor.
+ **/
+const char *
+connection_describe_peer(const connection_t *conn)
+{
+ return connection_describe_peer_internal(conn, false);
+}
+
+/**
+ * Describe a connection for logging purposes.
+ *
+ * Returns a pointer to a static buffer; future calls to connection_describe()
+ * will invalidate this buffer.
+ *
+ * Nobody should parse the output of this function; it can and will change in
+ * future versions of tor.
+ **/
+const char *
+connection_describe(const connection_t *conn)
+{
+ IF_BUG_ONCE(!conn) {
+ return "null connection";
+ }
+ static char desc_buf[256];
+ const char *peer = connection_describe_peer_internal(conn, true);
+ tor_snprintf(desc_buf, sizeof(desc_buf),
+ "%s connection (%s) %s",
+ conn_type_to_string(conn->type),
+ conn_state_to_string(conn->type, conn->state),
+ peer);
+ return desc_buf;
+}
+
/** Allocate and return a new dir_connection_t, initialized as by
* connection_init(). */
dir_connection_t *
@@ -382,6 +581,7 @@ or_connection_new(int type, int socket_family)
tor_assert(type == CONN_TYPE_OR || type == CONN_TYPE_EXT_OR);
connection_init(now, TO_CONN(or_conn), type, socket_family);
+ tor_addr_make_unspec(&or_conn->canonical_orport.addr);
connection_or_set_canonical(or_conn, 0);
if (type == CONN_TYPE_EXT_OR) {
@@ -852,11 +1052,11 @@ connection_close_immediate(connection_t *conn)
tor_fragile_assert();
return;
}
- if (conn->outbuf_flushlen) {
- log_info(LD_NET,"fd %d, type %s, state %s, %d bytes on outbuf.",
+ if (connection_get_outbuf_len(conn)) {
+ log_info(LD_NET,"fd %d, type %s, state %s, %"TOR_PRIuSZ" bytes on outbuf.",
(int)conn->s, conn_type_to_string(conn->type),
conn_state_to_string(conn->type, conn->state),
- (int)conn->outbuf_flushlen);
+ buf_datalen(conn->outbuf));
}
connection_unregister_events(conn);
@@ -872,7 +1072,6 @@ connection_close_immediate(connection_t *conn)
conn->linked_conn_is_closed = 1;
if (conn->outbuf)
buf_clear(conn->outbuf);
- conn->outbuf_flushlen = 0;
}
/** Mark <b>conn</b> to be closed next time we loop through
@@ -1549,13 +1748,8 @@ connection_listener_new(const struct sockaddr *listensockaddr,
*/
connection_check_oos(get_n_open_sockets(), 0);
- if (conn->socket_family == AF_UNIX) {
- log_notice(LD_NET, "Opened %s on %s",
- conn_type_to_string(type), conn->address);
- } else {
- log_notice(LD_NET, "Opened %s on %s",
- conn_type_to_string(type), fmt_addrport(&addr, gotPort));
- }
+ log_notice(LD_NET, "Opened %s", connection_describe(conn));
+
return conn;
err:
@@ -1836,6 +2030,10 @@ connection_handle_listener_read(connection_t *conn, int new_type)
log_notice(LD_CONTROL, "New control connection opened from %s.",
fmt_and_decorate_addr(&addr));
}
+ if (new_type == CONN_TYPE_METRICS) {
+ log_info(LD_CONTROL, "New metrics connection opened from %s.",
+ fmt_and_decorate_addr(&addr));
+ }
} else if (conn->socket_family == AF_UNIX && conn->type != CONN_TYPE_AP) {
tor_assert(conn->type == CONN_TYPE_CONTROL_LISTENER);
@@ -1863,6 +2061,9 @@ connection_handle_listener_read(connection_t *conn, int new_type)
connection_mark_for_close(newconn);
return 0;
}
+
+ note_connection(true /* inbound */, conn->socket_family);
+
return 0;
}
@@ -2034,6 +2235,8 @@ connection_connect_sockaddr,(connection_t *conn,
}
}
+ note_connection(false /* outbound */, conn->socket_family);
+
/* it succeeded. we're connected. */
log_fn(inprogress ? LOG_DEBUG : LOG_INFO, LD_NET,
"Connection to socket %s (sock "TOR_SOCKET_T_FORMAT").",
@@ -2067,22 +2270,13 @@ connection_connect_log_client_use_ip_version(const connection_t *conn)
return;
}
- const int must_ipv4 = !fascist_firewall_use_ipv6(options);
+ const int must_ipv4 = !reachable_addr_use_ipv6(options);
const int must_ipv6 = (options->ClientUseIPv4 == 0);
const int pref_ipv6 = (conn->type == CONN_TYPE_OR
- ? fascist_firewall_prefer_ipv6_orport(options)
- : fascist_firewall_prefer_ipv6_dirport(options));
+ ? reachable_addr_prefer_ipv6_orport(options)
+ : reachable_addr_prefer_ipv6_dirport(options));
tor_addr_t real_addr;
- tor_addr_make_null(&real_addr, AF_UNSPEC);
-
- /* OR conns keep the original address in real_addr, as addr gets overwritten
- * with the descriptor address */
- if (conn->type == CONN_TYPE_OR) {
- const or_connection_t *or_conn = TO_OR_CONN((connection_t *)conn);
- tor_addr_copy(&real_addr, &or_conn->real_addr);
- } else if (conn->type == CONN_TYPE_DIR) {
- tor_addr_copy(&real_addr, &conn->addr);
- }
+ tor_addr_copy(&real_addr, &conn->addr);
/* Check if we broke a mandatory address family restriction */
if ((must_ipv4 && tor_addr_family(&real_addr) == AF_INET6)
@@ -2105,7 +2299,7 @@ connection_connect_log_client_use_ip_version(const connection_t *conn)
return;
}
- if (fascist_firewall_use_ipv6(options)) {
+ if (reachable_addr_use_ipv6(options)) {
log_info(LD_NET, "Our outgoing connection is using IPv%d.",
tor_addr_family(&real_addr) == AF_INET6 ? 6 : 4);
}
@@ -2115,13 +2309,13 @@ connection_connect_log_client_use_ip_version(const connection_t *conn)
|| (pref_ipv6 && tor_addr_family(&real_addr) == AF_INET)) {
log_info(LD_NET, "Outgoing connection to %s doesn't satisfy "
"ClientPreferIPv6%sPort %d, with ClientUseIPv4 %d, and "
- "fascist_firewall_use_ipv6 %d (ClientUseIPv6 %d and UseBridges "
+ "reachable_addr_use_ipv6 %d (ClientUseIPv6 %d and UseBridges "
"%d).",
fmt_addr(&real_addr),
conn->type == CONN_TYPE_OR ? "OR" : "Dir",
conn->type == CONN_TYPE_OR ? options->ClientPreferIPv6ORPort
: options->ClientPreferIPv6DirPort,
- options->ClientUseIPv4, fascist_firewall_use_ipv6(options),
+ options->ClientUseIPv4, reachable_addr_use_ipv6(options),
options->ClientUseIPv6, options->UseBridges);
}
}
@@ -2155,9 +2349,9 @@ conn_get_outbound_address(sa_family_t family,
ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT]
[fam_index];
} else if (!tor_addr_is_null(
- &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT_AND_OR]
+ &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY]
[fam_index])) {
- ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT_AND_OR]
+ ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY]
[fam_index];
}
} else { // All non-exit connections
@@ -2166,9 +2360,9 @@ conn_get_outbound_address(sa_family_t family,
ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_OR]
[fam_index];
} else if (!tor_addr_is_null(
- &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT_AND_OR]
+ &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY]
[fam_index])) {
- ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT_AND_OR]
+ ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY]
[fam_index];
}
}
@@ -2608,8 +2802,8 @@ connection_read_https_proxy_response(connection_t *conn)
if (parse_http_response(headers, &status_code, &date_header,
NULL, &reason) < 0) {
log_warn(LD_NET,
- "Unparseable headers from proxy (connecting to '%s'). Closing.",
- conn->address);
+ "Unparseable headers from proxy (%s). Closing.",
+ connection_describe(conn));
tor_free(headers);
return -1;
}
@@ -2618,8 +2812,8 @@ connection_read_https_proxy_response(connection_t *conn)
if (status_code == 200) {
log_info(LD_NET,
- "HTTPS connect to '%s' successful! (200 %s) Starting TLS.",
- conn->address, escaped(reason));
+ "HTTPS connect for %s successful! (200 %s) Starting TLS.",
+ connection_describe(conn), escaped(reason));
tor_free(reason);
return 1;
}
@@ -2835,16 +3029,16 @@ connection_read_proxy_handshake(connection_t *conn)
if (ret < 0) {
if (reason) {
- log_warn(LD_NET, "Proxy Client: unable to connect to %s:%d (%s)",
- conn->address, conn->port, escaped(reason));
+ log_warn(LD_NET, "Proxy Client: unable to connect %s (%s)",
+ connection_describe(conn), escaped(reason));
tor_free(reason);
} else {
- log_warn(LD_NET, "Proxy Client: unable to connect to %s:%d",
- conn->address, conn->port);
+ log_warn(LD_NET, "Proxy Client: unable to connect %s",
+ connection_describe(conn));
}
} else if (ret == 1) {
- log_info(LD_NET, "Proxy Client: connection to %s:%d successful",
- conn->address, conn->port);
+ log_info(LD_NET, "Proxy Client: %s successful",
+ connection_describe(conn));
}
return ret;
@@ -3001,10 +3195,10 @@ retry_all_listeners(smartlist_t *new_conns, int close_all_noncontrol)
smartlist_t *replacements = smartlist_new();
const or_options_t *options = get_options();
int retval = 0;
- const uint16_t old_or_port = router_get_advertised_or_port(options);
+ const uint16_t old_or_port = routerconf_find_or_port(options, AF_INET);
const uint16_t old_or_port_ipv6 =
- router_get_advertised_or_port_by_af(options,AF_INET6);
- const uint16_t old_dir_port = router_get_advertised_dir_port(options, 0);
+ routerconf_find_or_port(options,AF_INET6);
+ const uint16_t old_dir_port = routerconf_find_dir_port(options, 0);
SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
if (connection_is_listener(conn) && !conn->marked_for_close)
@@ -3035,8 +3229,8 @@ retry_all_listeners(smartlist_t *new_conns, int close_all_noncontrol)
connection_t *old_conn = r->old_conn;
if (skip) {
- log_debug(LD_NET, "Skipping creating new listener for %s:%d",
- old_conn->address, old_conn->port);
+ log_debug(LD_NET, "Skipping creating new listener for %s",
+ connection_describe(old_conn));
continue;
}
@@ -3059,10 +3253,11 @@ retry_all_listeners(smartlist_t *new_conns, int close_all_noncontrol)
smartlist_add(new_conns, new_conn);
- log_notice(LD_NET, "Closed no-longer-configured %s on %s:%d "
- "(replaced by %s:%d)",
- conn_type_to_string(old_conn->type), old_conn->address,
- old_conn->port, new_conn->address, new_conn->port);
+ char *old_desc = tor_strdup(connection_describe(old_conn));
+ log_notice(LD_NET, "Closed no-longer-configured %s "
+ "(replaced by %s)",
+ old_desc, connection_describe(new_conn));
+ tor_free(old_desc);
} SMARTLIST_FOREACH_END(r);
#endif /* defined(ENABLE_LISTENER_REBIND) */
@@ -3080,10 +3275,9 @@ retry_all_listeners(smartlist_t *new_conns, int close_all_noncontrol)
SMARTLIST_FOREACH(replacements, listener_replacement_t *, r, tor_free(r));
smartlist_free(replacements);
- if (old_or_port != router_get_advertised_or_port(options) ||
- old_or_port_ipv6 != router_get_advertised_or_port_by_af(options,
- AF_INET6) ||
- old_dir_port != router_get_advertised_dir_port(options, 0)) {
+ if (old_or_port != routerconf_find_or_port(options, AF_INET) ||
+ old_or_port_ipv6 != routerconf_find_or_port(options, AF_INET6) ||
+ old_dir_port != routerconf_find_dir_port(options, 0)) {
/* Our chosen ORPort or DirPort is not what it used to be: the
* descriptor we had (if any) should be regenerated. (We won't
* automatically notice this because of changes in the option,
@@ -3261,12 +3455,12 @@ connection_bucket_write_limit(connection_t *conn, time_t now)
{
int base = RELAY_PAYLOAD_SIZE;
int priority = conn->type != CONN_TYPE_DIR;
- size_t conn_bucket = conn->outbuf_flushlen;
+ size_t conn_bucket = buf_datalen(conn->outbuf);
size_t global_bucket_val = token_bucket_rw_get_write(&global_bucket);
if (!connection_is_rate_limited(conn)) {
/* be willing to write to local conns even if our buckets are empty */
- return conn->outbuf_flushlen;
+ return conn_bucket;
}
if (connection_speaks_cells(conn)) {
@@ -3356,9 +3550,9 @@ record_num_bytes_transferred_impl(connection_t *conn,
/* Count bytes of answering direct and tunneled directory requests */
if (conn->type == CONN_TYPE_DIR && conn->purpose == DIR_PURPOSE_SERVER) {
if (num_read > 0)
- rep_hist_note_dir_bytes_read(num_read, now);
+ bwhist_note_dir_bytes_read(num_read, now);
if (num_written > 0)
- rep_hist_note_dir_bytes_written(num_written, now);
+ bwhist_note_dir_bytes_written(num_written, now);
}
/* Linked connections and internal IPs aren't counted for statistics or
@@ -3373,15 +3567,16 @@ record_num_bytes_transferred_impl(connection_t *conn,
if (!connection_is_rate_limited(conn))
return;
+ const bool is_ipv6 = (conn->socket_family == AF_INET6);
if (conn->type == CONN_TYPE_OR)
- rep_hist_note_or_conn_bytes(conn->global_identifier, num_read,
- num_written, now);
+ conn_stats_note_or_conn_bytes(conn->global_identifier, num_read,
+ num_written, now, is_ipv6);
if (num_read > 0) {
- rep_hist_note_bytes_read(num_read, now);
+ bwhist_note_bytes_read(num_read, now, is_ipv6);
}
if (num_written > 0) {
- rep_hist_note_bytes_written(num_written, now);
+ bwhist_note_bytes_written(num_written, now, is_ipv6);
}
if (conn->type == CONN_TYPE_EXIT)
rep_hist_note_exit_bytes(conn->port, num_written, num_read);
@@ -3707,6 +3902,8 @@ connection_handle_read_impl(connection_t *conn)
return connection_handle_listener_read(conn, CONN_TYPE_DIR);
case CONN_TYPE_CONTROL_LISTENER:
return connection_handle_listener_read(conn, CONN_TYPE_CONTROL);
+ case CONN_TYPE_METRICS_LISTENER:
+ return connection_handle_listener_read(conn, CONN_TYPE_METRICS);
case CONN_TYPE_AP_DNS_LISTENER:
/* This should never happen; eventdns.c handles the reads here. */
tor_fragile_assert();
@@ -3870,17 +4067,14 @@ connection_buf_read_from_socket(connection_t *conn, ssize_t *max_to_read,
switch (result) {
case TOR_TLS_CLOSE:
case TOR_TLS_ERROR_IO:
- log_debug(LD_NET,"TLS connection closed %son read. Closing. "
- "(Nickname %s, address %s)",
- result == TOR_TLS_CLOSE ? "cleanly " : "",
- or_conn->nickname ? or_conn->nickname : "not set",
- conn->address);
+ log_debug(LD_NET,"TLS %s closed %son read. Closing.",
+ connection_describe(conn),
+ result == TOR_TLS_CLOSE ? "cleanly " : "");
return result;
CASE_TOR_TLS_ERROR_ANY_NONIO:
- log_debug(LD_NET,"tls error [%s]. breaking (nickname %s, address %s).",
+ log_debug(LD_NET,"tls error [%s] from %s. Breaking.",
tor_tls_err_to_string(result),
- or_conn->nickname ? or_conn->nickname : "not set",
- conn->address);
+ connection_describe(conn));
return result;
case TOR_TLS_WANTWRITE:
connection_start_writing(conn);
@@ -3921,12 +4115,7 @@ connection_buf_read_from_socket(connection_t *conn, ssize_t *max_to_read,
result, (long)n_read, (long)n_written);
} else if (conn->linked) {
if (conn->linked_conn) {
- result = buf_move_to_buf(conn->inbuf, conn->linked_conn->outbuf,
- &conn->linked_conn->outbuf_flushlen);
- if (BUG(result<0)) {
- log_warn(LD_BUG, "reading from linked connection buffer failed.");
- return -1;
- }
+ result = (int) buf_move_all(conn->inbuf, conn->linked_conn->outbuf);
} else {
result = 0;
}
@@ -3961,6 +4150,14 @@ connection_buf_read_from_socket(connection_t *conn, ssize_t *max_to_read,
/* change *max_to_read */
*max_to_read = at_most - n_read;
+ /* Onion service application connection. Note read bytes for metrics. */
+ if (CONN_IS_EDGE(conn) && TO_EDGE_CONN(conn)->hs_ident) {
+ edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
+ hs_metrics_app_read_bytes(&edge_conn->hs_ident->identity_pk,
+ edge_conn->hs_ident->orig_virtual_port,
+ n_read);
+ }
+
/* Update edge_conn->n_read */
if (conn->type == CONN_TYPE_AP) {
edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
@@ -4030,12 +4227,11 @@ connection_fetch_from_buf_http(connection_t *conn,
body_out, body_used, max_bodylen, force_complete);
}
-/** Return conn-\>outbuf_flushlen: how many bytes conn wants to flush
- * from its outbuf. */
+/** Return true if this connection has data to flush. */
int
connection_wants_to_flush(connection_t *conn)
{
- return conn->outbuf_flushlen > 0;
+ return connection_get_outbuf_len(conn) > 0;
}
/** Are there too many bytes on edge connection <b>conn</b>'s outbuf to
@@ -4045,7 +4241,7 @@ connection_wants_to_flush(connection_t *conn)
int
connection_outbuf_too_full(connection_t *conn)
{
- return (conn->outbuf_flushlen > 10*CELL_PAYLOAD_SIZE);
+ return connection_get_outbuf_len(conn) > 10*CELL_PAYLOAD_SIZE;
}
/**
@@ -4171,7 +4367,7 @@ connection_handle_write_impl(connection_t *conn, int force)
return -1;
}
- max_to_write = force ? (ssize_t)conn->outbuf_flushlen
+ max_to_write = force ? (ssize_t)buf_datalen(conn->outbuf)
: connection_bucket_write_limit(conn, now);
if (connection_speaks_cells(conn) &&
@@ -4203,7 +4399,7 @@ connection_handle_write_impl(connection_t *conn, int force)
/* else open, or closing */
initial_size = buf_datalen(conn->outbuf);
result = buf_flush_to_tls(conn->outbuf, or_conn->tls,
- max_to_write, &conn->outbuf_flushlen);
+ max_to_write);
if (result >= 0)
update_send_buffer_size(conn->s);
@@ -4269,7 +4465,7 @@ connection_handle_write_impl(connection_t *conn, int force)
} else {
CONN_LOG_PROTECT(conn,
result = buf_flush_to_socket(conn->outbuf, conn->s,
- max_to_write, &conn->outbuf_flushlen));
+ max_to_write));
if (result < 0) {
if (CONN_IS_EDGE(conn))
connection_edge_end_errno(TO_EDGE_CONN(conn));
@@ -4425,10 +4621,10 @@ connection_write_to_buf_failed(connection_t *conn)
/** Helper for connection_write_to_buf_impl and connection_write_buf_to_buf:
*
* Called when an attempt to add bytes on <b>conn</b>'s outbuf has succeeded:
- * record the number of bytes added.
+ * start writing if appropriate.
*/
static void
-connection_write_to_buf_commit(connection_t *conn, size_t len)
+connection_write_to_buf_commit(connection_t *conn)
{
/* If we receive optimistic data in the EXIT_CONN_STATE_RESOLVING
* state, we don't want to try to write it right away, since
@@ -4437,7 +4633,6 @@ connection_write_to_buf_commit(connection_t *conn, size_t len)
if (conn->write_event) {
connection_start_writing(conn);
}
- conn->outbuf_flushlen += len;
}
/** Append <b>len</b> bytes of <b>string</b> onto <b>conn</b>'s
@@ -4460,25 +4655,20 @@ connection_write_to_buf_impl_,(const char *string, size_t len,
if (!connection_may_write_to_buf(conn))
return;
- size_t written;
-
if (zlib) {
- size_t old_datalen = buf_datalen(conn->outbuf);
dir_connection_t *dir_conn = TO_DIR_CONN(conn);
int done = zlib < 0;
CONN_LOG_PROTECT(conn, r = buf_add_compress(conn->outbuf,
dir_conn->compress_state,
string, len, done));
- written = buf_datalen(conn->outbuf) - old_datalen;
} else {
CONN_LOG_PROTECT(conn, r = buf_add(conn->outbuf, string, len));
- written = len;
}
if (r < 0) {
connection_write_to_buf_failed(conn);
return;
}
- connection_write_to_buf_commit(conn, written);
+ connection_write_to_buf_commit(conn);
}
/**
@@ -4523,7 +4713,7 @@ connection_buf_add_buf(connection_t *conn, buf_t *buf)
return;
buf_move_all(conn->outbuf, buf);
- connection_write_to_buf_commit(conn, len);
+ connection_write_to_buf_commit(conn);
}
#define CONN_GET_ALL_TEMPLATE(var, test) \
@@ -4733,7 +4923,7 @@ any_other_active_or_conns(const or_connection_t *this_conn)
connection_t *conn = connection_get_another_active_or_conn(this_conn);
if (conn != NULL) {
log_debug(LD_DIR, "%s: Found an OR connection: %s",
- __func__, conn->address);
+ __func__, connection_describe(conn));
return 1;
}
@@ -4883,7 +5073,7 @@ client_check_address_changed(tor_socket_t sock)
smartlist_clear(outgoing_addrs);
smartlist_add(outgoing_addrs, tor_memdup(&out_addr, sizeof(tor_addr_t)));
/* We'll need to resolve ourselves again. */
- reset_last_resolved_addr();
+ resolved_addr_reset_last(AF_INET);
/* Okay, now change our keys. */
ip_address_changed(1);
}
@@ -4937,6 +5127,8 @@ connection_process_inbuf(connection_t *conn, int package_partial)
return connection_dir_process_inbuf(TO_DIR_CONN(conn));
case CONN_TYPE_CONTROL:
return connection_control_process_inbuf(TO_CONTROL_CONN(conn));
+ case CONN_TYPE_METRICS:
+ return metrics_connection_process_inbuf(conn);
default:
log_err(LD_BUG,"got unexpected conn type %d.", conn->type);
tor_fragile_assert();
@@ -4995,6 +5187,8 @@ connection_finished_flushing(connection_t *conn)
return connection_dir_finished_flushing(TO_DIR_CONN(conn));
case CONN_TYPE_CONTROL:
return connection_control_finished_flushing(TO_CONTROL_CONN(conn));
+ case CONN_TYPE_METRICS:
+ return metrics_connection_finished_flushing(conn);
default:
log_err(LD_BUG,"got unexpected conn type %d.", conn->type);
tor_fragile_assert();
@@ -5050,6 +5244,8 @@ connection_reached_eof(connection_t *conn)
return connection_dir_reached_eof(TO_DIR_CONN(conn));
case CONN_TYPE_CONTROL:
return connection_control_reached_eof(TO_CONTROL_CONN(conn));
+ case CONN_TYPE_METRICS:
+ return metrics_connection_reached_eof(conn);
default:
log_err(LD_BUG,"got unexpected conn type %d.", conn->type);
tor_fragile_assert();
@@ -5411,18 +5607,6 @@ assert_connection_ok(connection_t *conn, time_t now)
if (conn->linked)
tor_assert(!SOCKET_OK(conn->s));
- if (conn->outbuf_flushlen > 0) {
- /* With optimistic data, we may have queued data in
- * EXIT_CONN_STATE_RESOLVING while the conn is not yet marked to writing.
- * */
- tor_assert((conn->type == CONN_TYPE_EXIT &&
- conn->state == EXIT_CONN_STATE_RESOLVING) ||
- connection_is_writing(conn) ||
- conn->write_blocked_on_bw ||
- (CONN_IS_EDGE(conn) &&
- TO_EDGE_CONN(conn)->edge_blocked_on_circ));
- }
-
if (conn->hold_open_until_flushed)
tor_assert(conn->marked_for_close);
@@ -5512,6 +5696,9 @@ assert_connection_ok(connection_t *conn, time_t now)
tor_assert(conn->state >= CONTROL_CONN_STATE_MIN_);
tor_assert(conn->state <= CONTROL_CONN_STATE_MAX_);
break;
+ case CONN_TYPE_METRICS:
+ /* No state. */
+ break;
default:
tor_assert(0);
}
diff --git a/src/core/mainloop/connection.h b/src/core/mainloop/connection.h
index bcd3d590a5..9dab28c3d9 100644
--- a/src/core/mainloop/connection.h
+++ b/src/core/mainloop/connection.h
@@ -31,6 +31,8 @@ struct tor_addr_t;
struct or_options_t;
struct listener_connection_t *TO_LISTENER_CONN(struct connection_t *);
+const struct listener_connection_t *CONST_TO_LISTENER_CONN(
+ const struct connection_t *);
struct buf_t;
@@ -71,8 +73,12 @@ struct buf_t;
#define CONN_TYPE_EXT_OR_LISTENER 17
/** Type for sockets listening for HTTP CONNECT tunnel connections. */
#define CONN_TYPE_AP_HTTP_CONNECT_LISTENER 18
+/** Type for sockets listening for Metrics query connections. */
+#define CONN_TYPE_METRICS_LISTENER 19
+/** Type for connections from metrics listener. */
+#define CONN_TYPE_METRICS 20
-#define CONN_TYPE_MAX_ 19
+#define CONN_TYPE_MAX_ 21
/* !!!! If _CONN_TYPE_MAX is ever over 31, we must grow the type field in
* struct connection_t. */
@@ -116,6 +122,9 @@ 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);
+const char *connection_describe(const connection_t *conn);
+const char *connection_describe_peer(const 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);
diff --git a/src/core/mainloop/cpuworker.c b/src/core/mainloop/cpuworker.c
index 485ddb9741..2ae7e9aaf2 100644
--- a/src/core/mainloop/cpuworker.c
+++ b/src/core/mainloop/cpuworker.c
@@ -246,7 +246,7 @@ estimated_usec_for_onionskins(uint32_t n_requests, uint16_t onionskin_type)
if (onionskin_type > MAX_ONION_HANDSHAKE_TYPE) /* should be impossible */
return 1000 * (uint64_t)n_requests;
if (PREDICT_UNLIKELY(onionskins_n_processed[onionskin_type] < 100)) {
- /* Until we have 100 data points, just asssume everything takes 1 msec. */
+ /* Until we have 100 data points, just assume everything takes 1 msec. */
return 1000 * (uint64_t)n_requests;
} else {
/* This can't overflow: we'll never have more than 500000 onionskins
diff --git a/src/core/mainloop/mainloop.c b/src/core/mainloop/mainloop.c
index b4dbedbfe4..77ab6f26c8 100644
--- a/src/core/mainloop/mainloop.c
+++ b/src/core/mainloop/mainloop.c
@@ -95,6 +95,7 @@
#include "feature/rend/rendservice.h"
#include "feature/stats/geoip_stats.h"
#include "feature/stats/predict_ports.h"
+#include "feature/stats/connstats.h"
#include "feature/stats/rephist.h"
#include "lib/buf/buffers.h"
#include "lib/crypt_ops/crypto_rand.h"
@@ -984,33 +985,29 @@ conn_close_if_marked(int i)
if (!conn->hold_open_until_flushed)
log_info(LD_NET,
"Conn (addr %s, fd %d, type %s, state %d) marked, but wants "
- "to flush %d bytes. (Marked at %s:%d)",
+ "to flush %"TOR_PRIuSZ" bytes. (Marked at %s:%d)",
escaped_safe_str_client(conn->address),
(int)conn->s, conn_type_to_string(conn->type), conn->state,
- (int)conn->outbuf_flushlen,
- conn->marked_for_close_file, conn->marked_for_close);
+ connection_get_outbuf_len(conn),
+ conn->marked_for_close_file, conn->marked_for_close);
if (conn->linked_conn) {
- retval = buf_move_to_buf(conn->linked_conn->inbuf, conn->outbuf,
- &conn->outbuf_flushlen);
+ retval = (int) buf_move_all(conn->linked_conn->inbuf, conn->outbuf);
if (retval >= 0) {
/* The linked conn will notice that it has data when it notices that
* we're gone. */
connection_start_reading_from_linked_conn(conn->linked_conn);
}
log_debug(LD_GENERAL, "Flushed last %d bytes from a linked conn; "
- "%d left; flushlen %d; wants-to-flush==%d", retval,
+ "%d left; wants-to-flush==%d", retval,
(int)connection_get_outbuf_len(conn),
- (int)conn->outbuf_flushlen,
connection_wants_to_flush(conn));
} else if (connection_speaks_cells(conn)) {
if (conn->state == OR_CONN_STATE_OPEN) {
- retval = buf_flush_to_tls(conn->outbuf, TO_OR_CONN(conn)->tls, sz,
- &conn->outbuf_flushlen);
+ retval = buf_flush_to_tls(conn->outbuf, TO_OR_CONN(conn)->tls, sz);
} else
retval = -1; /* never flush non-open broken tls connections */
} else {
- retval = buf_flush_to_socket(conn->outbuf, conn->s, sz,
- &conn->outbuf_flushlen);
+ retval = buf_flush_to_socket(conn->outbuf, conn->s, sz);
}
if (retval >= 0 && /* Technically, we could survive things like
TLS_WANT_WRITE here. But don't bother for now. */
@@ -1478,7 +1475,7 @@ get_my_roles(const or_options_t *options)
/* We also consider tor to have the role of a client if the ControlPort is
* set because a lot of things can be done over the control port which
- * requires tor to have basic functionnalities. */
+ * requires tor to have basic functionalities. */
int is_client = options_any_client_port_set(options) ||
options->ControlPort_set ||
options->OwningControllerFD != UINT64_MAX;
@@ -1950,7 +1947,7 @@ write_stats_file_callback(time_t now, const or_options_t *options)
next_time_to_write_stats_files = next_write;
}
if (options->ConnDirectionStatistics) {
- time_t next_write = rep_hist_conn_stats_write(now);
+ time_t next_write = conn_stats_save(now);
if (next_write && next_write < next_time_to_write_stats_files)
next_time_to_write_stats_files = next_write;
}
diff --git a/src/core/mainloop/netstatus.c b/src/core/mainloop/netstatus.c
index 61a3469eaa..7367c68219 100644
--- a/src/core/mainloop/netstatus.c
+++ b/src/core/mainloop/netstatus.c
@@ -72,7 +72,7 @@ note_user_activity(time_t now)
}
/**
- * Change the time at which "user activitiy" was last seen to <b>now</b>.
+ * Change the time at which "user activity" was last seen to <b>now</b>.
*
* Unlike note_user_actity, this function sets the time without checking
* whether it is in the past, and without causing any rescan of periodic events
diff --git a/src/core/mainloop/periodic.c b/src/core/mainloop/periodic.c
index b5fd8fab61..29cf8c4831 100644
--- a/src/core/mainloop/periodic.c
+++ b/src/core/mainloop/periodic.c
@@ -90,7 +90,7 @@ periodic_event_dispatch(mainloop_event_t *ev, void *data)
next_interval = r;
} else {
/* no action was taken, it is likely a precondition failed,
- * we should reschedule for next second incase the precondition
+ * we should reschedule for next second in case the precondition
* passes then */
next_interval = 1;
}
diff --git a/src/core/or/channel.c b/src/core/or/channel.c
index 50c03de846..1ac029c152 100644
--- a/src/core/or/channel.c
+++ b/src/core/or/channel.c
@@ -32,7 +32,7 @@
*
* NOTE: For now, the separation between channels and specialized channels
* (like channeltls) is not that well defined. So the channeltls layer calls
- * channel_process_cell() which originally comes from the connection subsytem.
+ * channel_process_cell() which originally comes from the connection subsystem.
* This should be hopefully be fixed with #23993.
*
* For *outbound* cells, the entry point is: channel_write_packed_cell().
@@ -84,13 +84,6 @@
#include "core/or/cell_queue_st.h"
-/* Static function prototypes */
-
-static bool channel_matches_target_addr_for_extend(
- channel_t *chan,
- const tor_addr_t *target_ipv4_addr,
- const tor_addr_t *target_ipv6_addr);
-
/* Global lists of channels */
/* All channel_t instances */
@@ -878,6 +871,8 @@ channel_init(channel_t *chan)
/* Channel is not in the scheduler heap. */
chan->sched_heap_idx = -1;
+
+ tor_addr_make_unspec(&chan->addr_according_to_peer);
}
/**
@@ -2392,7 +2387,7 @@ channel_is_better(channel_t *a, channel_t *b)
* Get a channel to extend a circuit.
*
* Given the desired relay identity, pick a suitable channel to extend a
- * circuit to the target IPv4 or IPv6 address requsted by the client. Search
+ * circuit to the target IPv4 or IPv6 address requested by the client. Search
* for an existing channel for the requested endpoint. Make sure the channel
* is usable for new circuits, and matches one of the target addresses.
*
@@ -2400,12 +2395,16 @@ channel_is_better(channel_t *a, channel_t *b)
* *msg_out to a message describing the channel's state and our next action,
* and set *launch_out to a boolean indicated whether the caller should try to
* launch a new channel with channel_connect().
+ *
+ * If `for_origin_circ` is set, mark the channel as interesting for origin
+ * circuits, and therefore interesting for our bootstrapping reports.
*/
MOCK_IMPL(channel_t *,
channel_get_for_extend,(const char *rsa_id_digest,
const ed25519_public_key_t *ed_id,
const tor_addr_t *target_ipv4_addr,
const tor_addr_t *target_ipv6_addr,
+ bool for_origin_circ,
const char **msg_out,
int *launch_out))
{
@@ -2445,8 +2444,15 @@ channel_get_for_extend,(const char *rsa_id_digest,
if (!CHANNEL_IS_OPEN(chan)) {
/* If the address matches, don't launch a new connection for this
* circuit. */
- if (matches_target)
+ if (matches_target) {
++n_inprogress_goodaddr;
+ if (for_origin_circ) {
+ /* We were looking for a connection for an origin circuit; this one
+ * matches, so we'll note that we decided to use it for an origin
+ * circuit. */
+ channel_mark_as_used_for_origin_circuit(chan);
+ }
+ }
continue;
}
@@ -2573,7 +2579,7 @@ channel_dump_statistics, (channel_t *chan, int severity))
/* Handle remote address and descriptions */
have_remote_addr = channel_get_addr_if_possible(chan, &remote_addr);
if (have_remote_addr) {
- char *actual = tor_strdup(channel_get_actual_remote_descr(chan));
+ char *actual = tor_strdup(channel_describe_peer(chan));
remote_addr_str = tor_addr_to_str_dup(&remote_addr);
tor_log(severity, LD_GENERAL,
" * Channel %"PRIu64 " says its remote address"
@@ -2581,18 +2587,18 @@ channel_dump_statistics, (channel_t *chan, int severity))
"actual description of \"%s\"",
(chan->global_identifier),
safe_str(remote_addr_str),
- safe_str(channel_get_canonical_remote_descr(chan)),
+ safe_str(channel_describe_peer(chan)),
safe_str(actual));
tor_free(remote_addr_str);
tor_free(actual);
} else {
- char *actual = tor_strdup(channel_get_actual_remote_descr(chan));
+ char *actual = tor_strdup(channel_describe_peer(chan));
tor_log(severity, LD_GENERAL,
" * Channel %"PRIu64 " does not know its remote "
"address, but gives a canonical description of \"%s\" and an "
"actual description of \"%s\"",
(chan->global_identifier),
- channel_get_canonical_remote_descr(chan),
+ channel_describe_peer(chan),
actual);
tor_free(actual);
}
@@ -2798,75 +2804,41 @@ channel_listener_dump_transport_statistics(channel_listener_t *chan_l,
}
/**
- * Return text description of the remote endpoint.
- *
- * This function return a test provided by the lower layer of the remote
- * endpoint for this channel; it should specify the actual address connected
- * to/from.
- *
- * Subsequent calls to channel_get_{actual,canonical}_remote_{address,descr}
- * may invalidate the return value from this function.
- */
-const char *
-channel_get_actual_remote_descr(channel_t *chan)
-{
- tor_assert(chan);
- tor_assert(chan->get_remote_descr);
-
- /* Param 1 indicates the actual description */
- return chan->get_remote_descr(chan, GRD_FLAG_ORIGINAL);
-}
-
-/**
- * Return the text address of the remote endpoint.
- *
- * Subsequent calls to channel_get_{actual,canonical}_remote_{address,descr}
- * may invalidate the return value from this function.
- */
-const char *
-channel_get_actual_remote_address(channel_t *chan)
-{
- /* Param 1 indicates the actual description */
- return chan->get_remote_descr(chan, GRD_FLAG_ORIGINAL|GRD_FLAG_ADDR_ONLY);
-}
-
-/**
* Return text description of the remote endpoint canonical address.
*
- * This function return a test provided by the lower layer of the remote
- * endpoint for this channel; it should use the known canonical address for
- * this OR's identity digest if possible.
+ * This function returns a human-readable string for logging; nothing
+ * should parse it or rely on a particular format.
*
- * Subsequent calls to channel_get_{actual,canonical}_remote_{address,descr}
- * may invalidate the return value from this function.
+ * Subsequent calls to this function may invalidate its return value.
*/
MOCK_IMPL(const char *,
-channel_get_canonical_remote_descr,(channel_t *chan))
+channel_describe_peer,(channel_t *chan))
{
tor_assert(chan);
- tor_assert(chan->get_remote_descr);
+ tor_assert(chan->describe_peer);
- /* Param 0 indicates the canonicalized description */
- return chan->get_remote_descr(chan, 0);
+ return chan->describe_peer(chan);
}
/**
- * Get remote address if possible.
+ * Get the remote address for this channel, if possible.
*
* Write the remote address out to a tor_addr_t if the underlying transport
* supports this operation, and return 1. Return 0 if the underlying transport
* doesn't let us do this.
+ *
+ * Always returns the "real" address of the peer -- the one we're connected to
+ * on the internet.
*/
MOCK_IMPL(int,
-channel_get_addr_if_possible,(channel_t *chan, tor_addr_t *addr_out))
+channel_get_addr_if_possible,(const channel_t *chan,
+ tor_addr_t *addr_out))
{
tor_assert(chan);
tor_assert(addr_out);
+ tor_assert(chan->get_remote_addr);
- if (chan->get_remote_addr)
- return chan->get_remote_addr(chan, addr_out);
- /* Else no support, method not implemented */
- else return 0;
+ return chan->get_remote_addr(chan, addr_out);
}
/**
@@ -3290,6 +3262,9 @@ channel_when_last_xmit(channel_t *chan)
*
* This function calls the lower layer and asks if this channel matches a
* given extend_info_t.
+ *
+ * NOTE that this function only checks for an address/port match, and should
+ * be used only when no identity is available.
*/
int
channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info)
@@ -3311,7 +3286,7 @@ channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info)
* This function calls into the lower layer and asks if this channel thinks
* it matches the target addresses for circuit extension purposes.
*/
-static bool
+STATIC bool
channel_matches_target_addr_for_extend(channel_t *chan,
const tor_addr_t *target_ipv4_addr,
const tor_addr_t *target_ipv6_addr)
diff --git a/src/core/or/channel.h b/src/core/or/channel.h
index fa4ce4f703..a1517aee37 100644
--- a/src/core/or/channel.h
+++ b/src/core/or/channel.h
@@ -236,6 +236,9 @@ struct channel_t {
/** The handle to this channel (to free on canceled timers) */
struct channel_handle_t *timer_handle;
+ /** If not UNSPEC, the address that the peer says we have. */
+ tor_addr_t addr_according_to_peer;
+
/**
* These two fields specify the minimum and maximum negotiated timeout
* values for inactivity (send or receive) before we decide to pad a
@@ -329,24 +332,18 @@ struct channel_t {
*/
double (*get_overhead_estimate)(channel_t *);
/*
- * Ask the underlying transport what the remote endpoint address is, in
- * a tor_addr_t. This is optional and subclasses may leave this NULL.
- * If they implement it, they should write the address out to the
- * provided tor_addr_t *, and return 1 if successful or 0 if no address
- * available.
+ * Ask the underlying transport what the remote endpoint address is, in a
+ * tor_addr_t. Write the address out to the provided tor_addr_t *, and
+ * return 1 if successful or 0 if no address available.
*/
- int (*get_remote_addr)(channel_t *, tor_addr_t *);
+ int (*get_remote_addr)(const channel_t *, tor_addr_t *);
int (*get_transport_name)(channel_t *chan, char **transport_out);
-#define GRD_FLAG_ORIGINAL 1
-#define GRD_FLAG_ADDR_ONLY 2
/**
- * Get a text description of the remote endpoint; canonicalized if the flag
- * GRD_FLAG_ORIGINAL is not set, or the one we originally connected
- * to/received from if it is. If GRD_FLAG_ADDR_ONLY is set, we return only
- * the original address.
+ * Get a human-readable text description of the remote endpoint, for
+ * logging.
*/
- const char * (*get_remote_descr)(channel_t *, int);
+ const char * (*describe_peer)(const channel_t *);
/** Check if the lower layer has queued writes */
int (*has_queued_writes)(channel_t *);
/**
@@ -529,6 +526,7 @@ void channel_mark_for_close(channel_t *chan);
int channel_write_packed_cell(channel_t *chan, packed_cell_t *cell);
void channel_listener_mark_for_close(channel_listener_t *chan_l);
+void channel_mark_as_used_for_origin_circuit(channel_t *chan);
/* Channel callback registrations */
@@ -560,7 +558,10 @@ void channel_listener_dumpstats(int severity);
#ifdef CHANNEL_FILE_PRIVATE
STATIC void channel_add_to_digest_map(channel_t *chan);
-
+STATIC bool channel_matches_target_addr_for_extend(
+ channel_t *chan,
+ const tor_addr_t *target_ipv4_addr,
+ const tor_addr_t *target_ipv6_addr);
#endif /* defined(CHANNEL_FILE_PRIVATE) */
/* Channel operations for subclasses and internal use only */
@@ -661,6 +662,7 @@ MOCK_DECL(channel_t *, channel_get_for_extend,(
const struct ed25519_public_key_t *ed_id,
const tor_addr_t *target_ipv4_addr,
const tor_addr_t *target_ipv6_addr,
+ bool for_origin_circ,
const char **msg_out,
int *launch_out));
@@ -719,11 +721,9 @@ channel_is_in_state(channel_t *chan, channel_state_t state)
const char * channel_describe_transport(channel_t *chan);
MOCK_DECL(void, channel_dump_statistics, (channel_t *chan, int severity));
void channel_dump_transport_statistics(channel_t *chan, int severity);
-const char * channel_get_actual_remote_descr(channel_t *chan);
-const char * channel_get_actual_remote_address(channel_t *chan);
-MOCK_DECL(int, channel_get_addr_if_possible, (channel_t *chan,
+MOCK_DECL(int, channel_get_addr_if_possible, (const channel_t *chan,
tor_addr_t *addr_out));
-MOCK_DECL(const char *, channel_get_canonical_remote_descr,(channel_t *chan));
+MOCK_DECL(const char *, channel_describe_peer,(channel_t *chan));
int channel_has_queued_writes(channel_t *chan);
int channel_is_bad_for_new_circs(channel_t *chan);
void channel_mark_bad_for_new_circs(channel_t *chan);
diff --git a/src/core/or/channelpadding.c b/src/core/or/channelpadding.c
index be2ce78a17..d0c43e8bdc 100644
--- a/src/core/or/channelpadding.c
+++ b/src/core/or/channelpadding.c
@@ -90,7 +90,7 @@ static int consensus_nf_pad_single_onion;
* for every single connection, every second.
*/
void
-channelpadding_new_consensus_params(networkstatus_t *ns)
+channelpadding_new_consensus_params(const networkstatus_t *ns)
{
#define DFLT_NETFLOW_INACTIVE_KEEPALIVE_LOW 1500
#define DFLT_NETFLOW_INACTIVE_KEEPALIVE_HIGH 9500
@@ -265,7 +265,7 @@ channelpadding_update_padding_for_channel(channel_t *chan,
log_fn_ratelim(&relay_limit,LOG_PROTOCOL_WARN,LD_PROTOCOL,
"Got a PADDING_NEGOTIATE from relay at %s (%s). "
"This should not happen.",
- chan->get_remote_descr(chan, 0),
+ channel_describe_peer(chan),
hex_str(chan->identity_digest, DIGEST_LEN));
return -1;
}
@@ -399,7 +399,7 @@ channelpadding_send_padding_cell_for_callback(channel_t *chan)
"Sending netflow keepalive on %"PRIu64" to %s (%s) after "
"%"PRId64" ms. Delta %"PRId64"ms",
(chan->global_identifier),
- safe_str_client(chan->get_remote_descr(chan, 0)),
+ safe_str_client(channel_describe_peer(chan)),
safe_str_client(hex_str(chan->identity_digest, DIGEST_LEN)),
(monotime_coarse_diff_msec(&chan->timestamp_xfer,&now)),
(
diff --git a/src/core/or/channelpadding.h b/src/core/or/channelpadding.h
index d1c7192ffd..9246988cdc 100644
--- a/src/core/or/channelpadding.h
+++ b/src/core/or/channelpadding.h
@@ -37,7 +37,6 @@ int channelpadding_send_enable_command(channel_t *chan, uint16_t low_timeout,
int channelpadding_get_circuits_available_timeout(void);
unsigned int channelpadding_get_channel_idle_timeout(const channel_t *, int);
-void channelpadding_new_consensus_params(networkstatus_t *ns);
+void channelpadding_new_consensus_params(const networkstatus_t *ns);
#endif /* !defined(TOR_CHANNELPADDING_H) */
-
diff --git a/src/core/or/channeltls.c b/src/core/or/channeltls.c
index f9eb67c399..dd5e42c47f 100644
--- a/src/core/or/channeltls.c
+++ b/src/core/or/channeltls.c
@@ -63,15 +63,16 @@
#include "trunnel/channelpadding_negotiation.h"
#include "trunnel/netinfo.h"
#include "core/or/channelpadding.h"
+#include "core/or/extendinfo.h"
#include "core/or/cell_st.h"
#include "core/or/cell_queue_st.h"
-#include "core/or/extend_info_st.h"
#include "core/or/or_connection_st.h"
#include "core/or/or_handshake_certs_st.h"
#include "core/or/or_handshake_state_st.h"
#include "feature/nodelist/routerinfo_st.h"
#include "core/or/var_cell_st.h"
+#include "src/feature/relay/relay_find_addr.h"
#include "lib/tls/tortls.h"
#include "lib/tls/x509.h"
@@ -102,12 +103,11 @@ static void channel_tls_close_method(channel_t *chan);
static const char * channel_tls_describe_transport_method(channel_t *chan);
static void channel_tls_free_method(channel_t *chan);
static double channel_tls_get_overhead_estimate_method(channel_t *chan);
-static int
-channel_tls_get_remote_addr_method(channel_t *chan, tor_addr_t *addr_out);
+static int channel_tls_get_remote_addr_method(const channel_t *chan,
+ tor_addr_t *addr_out);
static int
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);
+static const char *channel_tls_describe_peer_method(const channel_t *chan);
static int channel_tls_has_queued_writes_method(channel_t *chan);
static int channel_tls_is_canonical_method(channel_t *chan);
static int
@@ -163,7 +163,7 @@ channel_tls_common_init(channel_tls_t *tlschan)
chan->free_fn = channel_tls_free_method;
chan->get_overhead_estimate = channel_tls_get_overhead_estimate_method;
chan->get_remote_addr = channel_tls_get_remote_addr_method;
- chan->get_remote_descr = channel_tls_get_remote_descr_method;
+ chan->describe_peer = channel_tls_describe_peer_method;
chan->get_transport_name = channel_tls_get_transport_name_method;
chan->has_queued_writes = channel_tls_has_queued_writes_method;
chan->is_canonical = channel_tls_is_canonical_method;
@@ -203,7 +203,7 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
tlschan,
(chan->global_identifier));
- if (is_local_addr(addr)) {
+ if (is_local_to_resolve_addr(addr)) {
log_debug(LD_CHANNEL,
"Marking new outgoing channel %"PRIu64 " at %p as local",
(chan->global_identifier), chan);
@@ -340,7 +340,7 @@ channel_tls_handle_incoming(or_connection_t *orconn)
tlschan->conn = orconn;
orconn->chan = tlschan;
- if (is_local_addr(&(TO_CONN(orconn)->addr))) {
+ if (is_local_to_resolve_addr(&(TO_CONN(orconn)->addr))) {
log_debug(LD_CHANNEL,
"Marking new incoming channel %"PRIu64 " at %p as local",
(chan->global_identifier), chan);
@@ -360,6 +360,31 @@ channel_tls_handle_incoming(or_connection_t *orconn)
return chan;
}
+/**
+ * Set the `potentially_used_for_bootstrapping` flag on the or_connection_t
+ * corresponding to the provided channel.
+ *
+ * This flag indicates that if the connection fails, it might be interesting
+ * to the bootstrapping subsystem. (The bootstrapping system only cares about
+ * channels that we have tried to use for our own circuits. Other channels
+ * may have been launched in response to EXTEND cells from somebody else, and
+ * if they fail, it won't necessarily indicate a bootstrapping problem.)
+ **/
+void
+channel_mark_as_used_for_origin_circuit(channel_t *chan)
+{
+ if (BUG(!chan))
+ return;
+ if (chan->magic != TLS_CHAN_MAGIC)
+ return;
+ channel_tls_t *tlschan = channel_tls_from_base(chan);
+ if (BUG(!tlschan))
+ return;
+
+ if (tlschan->conn)
+ tlschan->conn->potentially_used_for_bootstrapping = 1;
+}
+
/*********
* Casts *
********/
@@ -389,6 +414,25 @@ channel_tls_from_base(channel_t *chan)
return (channel_tls_t *)(chan);
}
+/**
+ * Cast a const channel_tls_t to a const channel_t.
+ */
+const channel_t *
+channel_tls_to_base_const(const channel_tls_t *tlschan)
+{
+ return channel_tls_to_base((channel_tls_t*) tlschan);
+}
+
+/**
+ * Cast a const channel_t to a const channel_tls_t, with appropriate
+ * type-checking asserts.
+ */
+const channel_tls_t *
+channel_tls_from_base_const(const channel_t *chan)
+{
+ return channel_tls_from_base((channel_t *)chan);
+}
+
/********************************************
* Method implementations for channel_tls_t *
*******************************************/
@@ -510,24 +554,29 @@ channel_tls_get_overhead_estimate_method(channel_t *chan)
* Get the remote address of a channel_tls_t.
*
* This implements the get_remote_addr method for channel_tls_t; copy the
- * remote endpoint of the channel to addr_out and return 1 (always
- * succeeds for this transport).
+ * remote endpoint of the channel to addr_out and return 1. (Always
+ * succeeds if this channel is attached to an OR connection.)
+ *
+ * Always returns the real address of the peer, not the canonical address.
*/
static int
-channel_tls_get_remote_addr_method(channel_t *chan, tor_addr_t *addr_out)
+channel_tls_get_remote_addr_method(const channel_t *chan,
+ tor_addr_t *addr_out)
{
- int rv = 0;
- channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan);
+ const channel_tls_t *tlschan = CONST_BASE_CHAN_TO_TLS(chan);
tor_assert(tlschan);
tor_assert(addr_out);
- if (tlschan->conn) {
- tor_addr_copy(addr_out, &(tlschan->conn->real_addr));
- rv = 1;
- } else tor_addr_make_unspec(addr_out);
+ if (tlschan->conn == NULL) {
+ tor_addr_make_unspec(addr_out);
+ return 0;
+ }
- return rv;
+ /* They want the real address, so give it to them. */
+ tor_addr_copy(addr_out, &TO_CONN(tlschan->conn)->addr);
+
+ return 1;
}
/**
@@ -555,62 +604,22 @@ channel_tls_get_transport_name_method(channel_t *chan, char **transport_out)
}
/**
- * Get endpoint description of a channel_tls_t.
+ * Get a human-readable endpoint description of a channel_tls_t.
*
- * This implements the get_remote_descr method for channel_tls_t; it returns
- * a text description of the remote endpoint of the channel suitable for use
- * in log messages. The req parameter is 0 for the canonical address or 1 for
- * the actual address seen.
+ * This format is intended for logging, and may change in the future;
+ * nothing should parse or rely on its particular details.
*/
static const char *
-channel_tls_get_remote_descr_method(channel_t *chan, int flags)
+channel_tls_describe_peer_method(const channel_t *chan)
{
- static char buf[TOR_ADDRPORT_BUF_LEN];
- channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan);
- connection_t *conn;
- const char *answer = NULL;
- char *addr_str;
-
+ const channel_tls_t *tlschan = CONST_BASE_CHAN_TO_TLS(chan);
tor_assert(tlschan);
if (tlschan->conn) {
- conn = TO_CONN(tlschan->conn);
- switch (flags) {
- case 0:
- /* Canonical address with port*/
- tor_snprintf(buf, TOR_ADDRPORT_BUF_LEN,
- "%s:%u", conn->address, conn->port);
- answer = buf;
- break;
- case GRD_FLAG_ORIGINAL:
- /* Actual address with port */
- addr_str = tor_addr_to_str_dup(&(tlschan->conn->real_addr));
- tor_snprintf(buf, TOR_ADDRPORT_BUF_LEN, "%s:%u", addr_str, conn->port);
- tor_free(addr_str);
- answer = buf;
- break;
- case GRD_FLAG_ADDR_ONLY:
- /* Canonical address, no port */
- strlcpy(buf, conn->address, sizeof(buf));
- answer = buf;
- break;
- case GRD_FLAG_ORIGINAL|GRD_FLAG_ADDR_ONLY:
- /* Actual address, no port */
- addr_str = tor_addr_to_str_dup(&(tlschan->conn->real_addr));
- strlcpy(buf, addr_str, sizeof(buf));
- tor_free(addr_str);
- answer = buf;
- break;
- default:
- /* Something's broken in channel.c */
- tor_assert_nonfatal_unreached_once();
- }
+ return connection_describe_peer(TO_CONN(tlschan->conn));
} else {
- strlcpy(buf, "(No connection)", sizeof(buf));
- answer = buf;
+ return "(No connection)";
}
-
- return answer;
}
/**
@@ -671,6 +680,9 @@ channel_tls_is_canonical_method(channel_t *chan)
*
* This implements the matches_extend_info method for channel_tls_t; the upper
* layer wants to know if this channel matches an extend_info_t.
+ *
+ * NOTE that this function only checks for an address/port match, and should
+ * be used only when no identify is available.
*/
static int
channel_tls_matches_extend_info_method(channel_t *chan,
@@ -690,9 +702,19 @@ channel_tls_matches_extend_info_method(channel_t *chan,
return 0;
}
- return (tor_addr_eq(&(extend_info->addr),
- &(TO_CONN(tlschan->conn)->addr)) &&
- (extend_info->port == TO_CONN(tlschan->conn)->port));
+ const tor_addr_port_t *orport = &tlschan->conn->canonical_orport;
+ // If the canonical address is set, then we'll allow matches based on that.
+ if (! tor_addr_is_unspec(&orport->addr)) {
+ if (extend_info_has_orport(extend_info, &orport->addr, orport->port)) {
+ return 1;
+ }
+ }
+
+ // We also want to match if the true address and port are listed in the
+ // extend info.
+ return extend_info_has_orport(extend_info,
+ &TO_CONN(tlschan->conn)->addr,
+ TO_CONN(tlschan->conn)->port);
}
/**
@@ -720,8 +742,8 @@ channel_tls_matches_target_method(channel_t *chan,
return 0;
}
- /* real_addr is the address this connection came from.
- * base_.addr is updated by connection_or_init_conn_from_address()
+ /* addr is the address this connection came from.
+ * canonical_orport is updated by connection_or_init_conn_from_address()
* to be the address in the descriptor. It may be tempting to
* allow either address to be allowed, but if we did so, it would
* enable someone who steals a relay's keys to covertly impersonate/MITM it
@@ -732,7 +754,7 @@ channel_tls_matches_target_method(channel_t *chan,
* An adversary who has stolen a relay's keys could also post a fake relay
* descriptor, but that attack is easier to detect.
*/
- return tor_addr_eq(&(tlschan->conn->real_addr), target);
+ return tor_addr_eq(&TO_CONN(tlschan->conn)->addr, target);
}
/**
@@ -1340,7 +1362,7 @@ channel_tls_update_marks(or_connection_t *conn)
chan = TLS_CHAN_TO_BASE(conn->chan);
- if (is_local_addr(&(TO_CONN(conn)->addr))) {
+ if (is_local_to_resolve_addr(&(TO_CONN(conn)->addr))) {
if (!channel_is_local(chan)) {
log_debug(LD_CHANNEL,
"Marking channel %"PRIu64 " at %p as local",
@@ -1405,7 +1427,7 @@ enter_v3_handshake_with_cell(var_cell_t *cell, channel_tls_t *chan)
"OR_HANDSHAKING_V3, on a connection we originated.");
}
connection_or_block_renegotiation(chan->conn);
- chan->conn->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3;
+ connection_or_change_state(chan->conn, OR_CONN_STATE_OR_HANDSHAKING_V3);
if (connection_init_or_handshake_state(chan->conn, started_here) < 0) {
connection_or_close_for_error(chan->conn, 0);
return -1;
@@ -1504,7 +1526,7 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan)
log_fn(LOG_WARN, LD_OR,
"Negotiated link with non-2 protocol after doing a v2 TLS "
"handshake with %s. Closing connection.",
- fmt_addr(&chan->conn->base_.addr));
+ connection_describe_peer(TO_CONN(chan->conn)));
connection_or_close_for_error(chan->conn, 0);
return;
}
@@ -1516,10 +1538,9 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan)
if (chan->conn->link_proto == 2) {
log_info(LD_OR,
- "Negotiated version %d with %s:%d; sending NETINFO.",
+ "Negotiated version %d on %s; sending NETINFO.",
highest_supported_version,
- safe_str_client(chan->conn->base_.address),
- chan->conn->base_.port);
+ connection_describe(TO_CONN(chan->conn)));
if (connection_or_send_netinfo(chan->conn) < 0) {
connection_or_close_for_error(chan->conn, 0);
@@ -1539,10 +1560,9 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan)
tor_assert(chan->conn->link_proto >= 3);
log_info(LD_OR,
- "Negotiated version %d with %s:%d; %s%s%s%s%s",
+ "Negotiated version %d with on %s; %s%s%s%s%s",
highest_supported_version,
- safe_str_client(chan->conn->base_.address),
- chan->conn->base_.port,
+ connection_describe(TO_CONN(chan->conn)),
send_any ? "Sending cells:" : "Waiting for CERTS cell",
send_versions ? " VERSIONS" : "",
send_certs ? " CERTS" : "",
@@ -1675,6 +1695,85 @@ time_abs(time_t val)
return (val < 0) ? -val : val;
}
+/** Return true iff the channel can process a NETINFO cell. For this to return
+ * true, these channel conditions apply:
+ *
+ * 1. Link protocol is version 2 or higher (tor-spec.txt, NETINFO cells
+ * section).
+ *
+ * 2. Underlying OR connection of the channel is either in v2 or v3
+ * handshaking state.
+ */
+static bool
+can_process_netinfo_cell(const channel_tls_t *chan)
+{
+ /* NETINFO cells can only be negotiated on link protocol 2 or higher. */
+ if (chan->conn->link_proto < 2) {
+ log_fn(LOG_PROTOCOL_WARN, LD_OR,
+ "Received a NETINFO cell on %s connection; dropping.",
+ chan->conn->link_proto == 0 ? "non-versioned" : "a v1");
+ return false;
+ }
+
+ /* Can't process a NETINFO cell if the connection is not handshaking. */
+ if (chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V2 &&
+ chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V3) {
+ log_fn(LOG_PROTOCOL_WARN, LD_OR,
+ "Received a NETINFO cell on non-handshaking connection; dropping.");
+ return false;
+ }
+
+ /* Make sure we do have handshake state. */
+ tor_assert(chan->conn->handshake_state);
+ tor_assert(chan->conn->handshake_state->received_versions);
+
+ return true;
+}
+
+/** Mark the given channel endpoint as a client (which means either a tor
+ * client or a tor bridge).
+ *
+ * This MUST be done on an _unauthenticated_ channel. It is a mistake to mark
+ * an authenticated channel as a client.
+ *
+ * The following is done on the channel:
+ *
+ * 1. Marked as a client.
+ * 2. Type of circuit ID type is set.
+ * 3. The underlying OR connection is initialized with the address of the
+ * endpoint.
+ */
+static void
+mark_channel_tls_endpoint_as_client(channel_tls_t *chan)
+{
+ /* Ending up here for an authenticated link is a mistake. */
+ if (BUG(chan->conn->handshake_state->authenticated)) {
+ return;
+ }
+
+ tor_assert(tor_digest_is_zero(
+ (const char*)(chan->conn->handshake_state->
+ authenticated_rsa_peer_id)));
+ tor_assert(fast_mem_is_zero(
+ (const char*)(chan->conn->handshake_state->
+ authenticated_ed25519_peer_id.pubkey), 32));
+ /* If the client never authenticated, it's a tor client or bridge
+ * relay, and we must not use it for EXTEND requests (nor could we, as
+ * there are no authenticated peer IDs) */
+ channel_mark_client(TLS_CHAN_TO_BASE(chan));
+ channel_set_circid_type(TLS_CHAN_TO_BASE(chan), NULL,
+ chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS);
+
+ connection_or_init_conn_from_address(chan->conn,
+ &(chan->conn->base_.addr),
+ chan->conn->base_.port,
+ /* zero, checked above */
+ (const char*)(chan->conn->handshake_state->
+ authenticated_rsa_peer_id),
+ NULL, /* Ed25519 ID: Also checked as zero */
+ 0);
+}
+
/**
* Process a 'netinfo' cell
*
@@ -1700,20 +1799,12 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
tor_assert(chan);
tor_assert(chan->conn);
- if (chan->conn->link_proto < 2) {
- log_fn(LOG_PROTOCOL_WARN, LD_OR,
- "Received a NETINFO cell on %s connection; dropping.",
- chan->conn->link_proto == 0 ? "non-versioned" : "a v1");
- return;
- }
- if (chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V2 &&
- chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V3) {
- log_fn(LOG_PROTOCOL_WARN, LD_OR,
- "Received a NETINFO cell on non-handshaking connection; dropping.");
+ /* Make sure we can process a NETINFO cell. Link protocol and state
+ * validation is done to make sure of it. */
+ if (!can_process_netinfo_cell(chan)) {
return;
}
- tor_assert(chan->conn->handshake_state &&
- chan->conn->handshake_state->received_versions);
+
started_here = connection_or_nonopen_was_started_here(chan->conn);
identity_digest = chan->conn->identity_digest;
@@ -1728,30 +1819,13 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
return;
}
} else {
- /* we're the server. If the client never authenticated, we have
- some housekeeping to do.*/
+ /* We're the server. If the client never authenticated, we have some
+ * housekeeping to do.
+ *
+ * It's a tor client or bridge relay, and we must not use it for EXTEND
+ * requests (nor could we, as there are no authenticated peer IDs) */
if (!(chan->conn->handshake_state->authenticated)) {
- tor_assert(tor_digest_is_zero(
- (const char*)(chan->conn->handshake_state->
- authenticated_rsa_peer_id)));
- tor_assert(fast_mem_is_zero(
- (const char*)(chan->conn->handshake_state->
- authenticated_ed25519_peer_id.pubkey), 32));
- /* If the client never authenticated, it's a tor client or bridge
- * relay, and we must not use it for EXTEND requests (nor could we, as
- * there are no authenticated peer IDs) */
- channel_mark_client(TLS_CHAN_TO_BASE(chan));
- channel_set_circid_type(TLS_CHAN_TO_BASE(chan), NULL,
- chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS);
-
- connection_or_init_conn_from_address(chan->conn,
- &(chan->conn->base_.addr),
- chan->conn->base_.port,
- /* zero, checked above */
- (const char*)(chan->conn->handshake_state->
- authenticated_rsa_peer_id),
- NULL, /* Ed25519 ID: Also checked as zero */
- 0);
+ mark_channel_tls_endpoint_as_client(chan);
}
}
}
@@ -1794,7 +1868,7 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
if (my_addr_type == NETINFO_ADDR_TYPE_IPV4 && my_addr_len == 4) {
if (!get_options()->BridgeRelay && me &&
- tor_addr_eq_ipv4h(&my_apparent_addr, me->addr)) {
+ tor_addr_eq(&my_apparent_addr, &me->ipv4_addr)) {
TLS_CHAN_TO_BASE(chan)->is_canonical_to_peer = 1;
}
} else if (my_addr_type == NETINFO_ADDR_TYPE_IPV6 &&
@@ -1806,6 +1880,13 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
}
}
+ if (me) {
+ /* We have a descriptor, so we are a relay: record the address that the
+ * other side said we had. */
+ tor_addr_copy(&TLS_CHAN_TO_BASE(chan)->addr_according_to_peer,
+ &my_apparent_addr);
+ }
+
n_other_addrs = netinfo_cell_get_n_my_addrs(netinfo_cell);
for (uint8_t i = 0; i < n_other_addrs; i++) {
/* Consider all the other addresses; if any matches, this connection is
@@ -1828,7 +1909,7 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
* might be doing something funny, but nobody else is doing a MITM
* on the relay's TCP.
*/
- if (tor_addr_eq(&addr, &(chan->conn->real_addr))) {
+ if (tor_addr_eq(&addr, &TO_CONN(chan->conn)->addr)) {
connection_or_set_canonical(chan->conn, 1);
break;
}
@@ -1838,8 +1919,8 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
if (me && !TLS_CHAN_TO_BASE(chan)->is_canonical_to_peer &&
channel_is_canonical(TLS_CHAN_TO_BASE(chan))) {
- const char *descr =
- TLS_CHAN_TO_BASE(chan)->get_remote_descr(TLS_CHAN_TO_BASE(chan), 0);
+ const char *descr = channel_describe_peer(
+ TLS_CHAN_TO_BASE(chan));
log_info(LD_OR,
"We made a connection to a relay at %s (fp=%s) but we think "
"they will not consider this connection canonical. They "
@@ -1848,7 +1929,7 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
safe_str(hex_str(identity_digest, DIGEST_LEN)),
safe_str(tor_addr_is_null(&my_apparent_addr) ?
"<none>" : fmt_and_decorate_addr(&my_apparent_addr)),
- safe_str(fmt_addr32(me->addr)));
+ safe_str(fmt_addr(&me->ipv4_addr)));
}
/* Act on apparent skew. */
@@ -1862,8 +1943,12 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
"NETINFO cell", "OR");
}
- /* XXX maybe act on my_apparent_addr, if the source is sufficiently
- * trustworthy. */
+ /* Consider our apparent address as a possible suggestion for our address if
+ * we were unable to resolve it previously. The endpoint address is passed
+ * in order to make sure to never consider an address that is the same as
+ * our endpoint. */
+ relay_address_new_suggestion(&my_apparent_addr, &TO_CONN(chan->conn)->addr,
+ identity_digest);
if (! chan->conn->handshake_state->sent_netinfo) {
/* If we were prepared to authenticate, but we never got an AUTH_CHALLENGE
@@ -1877,18 +1962,16 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
if (connection_or_set_state_open(chan->conn) < 0) {
log_fn(LOG_PROTOCOL_WARN, LD_OR,
- "Got good NETINFO cell from %s:%d; but "
+ "Got good NETINFO cell on %s; but "
"was unable to make the OR connection become open.",
- safe_str_client(chan->conn->base_.address),
- chan->conn->base_.port);
+ connection_describe(TO_CONN(chan->conn)));
connection_or_close_for_error(chan->conn, 0);
} else {
log_info(LD_OR,
- "Got good NETINFO cell from %s:%d; OR connection is now "
+ "Got good NETINFO cell on %s; OR connection is now "
"open, using protocol version %d. Its ID digest is %s. "
"Our address is apparently %s.",
- safe_str_client(chan->conn->base_.address),
- chan->conn->base_.port,
+ connection_describe(TO_CONN(chan->conn)),
(int)(chan->conn->link_proto),
hex_str(identity_digest, DIGEST_LEN),
tor_addr_is_null(&my_apparent_addr) ?
@@ -1973,9 +2056,9 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
#define ERR(s) \
do { \
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \
- "Received a bad CERTS cell from %s:%d: %s", \
- safe_str(chan->conn->base_.address), \
- chan->conn->base_.port, (s)); \
+ "Received a bad CERTS cell on %s: %s", \
+ connection_describe(TO_CONN(chan->conn)), \
+ (s)); \
connection_or_close_for_error(chan->conn, 0); \
goto err; \
} while (0)
@@ -2023,9 +2106,8 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
tor_x509_cert_t *x509_cert = tor_x509_cert_decode(cert_body, cert_len);
if (!x509_cert) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Received undecodable certificate in CERTS cell from %s:%d",
- safe_str(chan->conn->base_.address),
- chan->conn->base_.port);
+ "Received undecodable certificate in CERTS cell on %s",
+ connection_describe(TO_CONN(chan->conn)));
} else {
if (x509_certs[cert_type]) {
tor_x509_cert_free(x509_cert);
@@ -2041,9 +2123,8 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
if (!ed_cert) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Received undecodable Ed certificate "
- "in CERTS cell from %s:%d",
- safe_str(chan->conn->base_.address),
- chan->conn->base_.port);
+ "in CERTS cell on %s",
+ connection_describe(TO_CONN(chan->conn)));
} else {
if (ed_certs[cert_type]) {
tor_cert_free(ed_cert);
@@ -2153,9 +2234,9 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
ERR("Problem setting or checking peer id");
log_info(LD_HANDSHAKE,
- "Got some good certificates from %s:%d: Authenticated it with "
+ "Got some good certificates on %s: Authenticated it with "
"RSA%s",
- safe_str(chan->conn->base_.address), chan->conn->base_.port,
+ connection_describe(TO_CONN(chan->conn)),
checked_ed_id ? " and Ed25519" : "");
if (!public_server_mode(get_options())) {
@@ -2167,11 +2248,10 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
} else {
/* We can't call it authenticated till we see an AUTHENTICATE cell. */
log_info(LD_OR,
- "Got some good RSA%s certificates from %s:%d. "
+ "Got some good RSA%s certificates on %s. "
"Waiting for AUTHENTICATE.",
checked_ed_id ? " and Ed25519" : "",
- safe_str(chan->conn->base_.address),
- chan->conn->base_.port);
+ connection_describe(TO_CONN(chan->conn)));
/* XXXX check more stuff? */
}
@@ -2220,9 +2300,9 @@ channel_tls_process_auth_challenge_cell(var_cell_t *cell, channel_tls_t *chan)
#define ERR(s) \
do { \
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \
- "Received a bad AUTH_CHALLENGE cell from %s:%d: %s", \
- safe_str(chan->conn->base_.address), \
- chan->conn->base_.port, (s)); \
+ "Received a bad AUTH_CHALLENGE cell on %s: %s", \
+ connection_describe(TO_CONN(chan->conn)), \
+ (s)); \
connection_or_close_for_error(chan->conn, 0); \
goto done; \
} while (0)
@@ -2267,10 +2347,9 @@ channel_tls_process_auth_challenge_cell(var_cell_t *cell, channel_tls_t *chan)
if (use_type >= 0) {
log_info(LD_OR,
- "Got an AUTH_CHALLENGE cell from %s:%d: Sending "
+ "Got an AUTH_CHALLENGE cell on %s: Sending "
"authentication type %d",
- safe_str(chan->conn->base_.address),
- chan->conn->base_.port,
+ connection_describe(TO_CONN(chan->conn)),
use_type);
if (connection_or_send_authenticate_cell(chan->conn, use_type) < 0) {
@@ -2281,10 +2360,9 @@ channel_tls_process_auth_challenge_cell(var_cell_t *cell, channel_tls_t *chan)
}
} else {
log_info(LD_OR,
- "Got an AUTH_CHALLENGE cell from %s:%d, but we don't "
+ "Got an AUTH_CHALLENGE cell on %s, but we don't "
"know any of its authentication types. Not authenticating.",
- safe_str(chan->conn->base_.address),
- chan->conn->base_.port);
+ connection_describe(TO_CONN(chan->conn)));
}
if (connection_or_send_netinfo(chan->conn) < 0) {
@@ -2324,9 +2402,9 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan)
#define ERR(s) \
do { \
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \
- "Received a bad AUTHENTICATE cell from %s:%d: %s", \
- safe_str(chan->conn->base_.address), \
- chan->conn->base_.port, (s)); \
+ "Received a bad AUTHENTICATE cell on %s: %s", \
+ connection_describe(TO_CONN(chan->conn)), \
+ (s)); \
connection_or_close_for_error(chan->conn, 0); \
var_cell_free(expected_cell); \
return; \
@@ -2487,9 +2565,9 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan)
crypto_pk_free(identity_rcvd);
log_debug(LD_HANDSHAKE,
- "Calling connection_or_init_conn_from_address for %s "
+ "Calling connection_or_init_conn_from_address on %s "
" from %s, with%s ed25519 id.",
- safe_str(chan->conn->base_.address),
+ connection_describe(TO_CONN(chan->conn)),
__func__,
ed_identity_received ? "" : "out");
@@ -2502,10 +2580,9 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan)
0);
log_debug(LD_HANDSHAKE,
- "Got an AUTHENTICATE cell from %s:%d, type %d: Looks good.",
- safe_str(chan->conn->base_.address),
- chan->conn->base_.port,
- authtype);
+ "Got an AUTHENTICATE cell on %s, type %d: Looks good.",
+ connection_describe(TO_CONN(chan->conn)),
+ authtype);
}
var_cell_free(expected_cell);
diff --git a/src/core/or/channeltls.h b/src/core/or/channeltls.h
index f04ce0fa9c..e7010a51fc 100644
--- a/src/core/or/channeltls.h
+++ b/src/core/or/channeltls.h
@@ -19,6 +19,8 @@ struct curve25519_public_key_t;
#define BASE_CHAN_TO_TLS(c) (channel_tls_from_base((c)))
#define TLS_CHAN_TO_BASE(c) (channel_tls_to_base((c)))
+#define CONST_BASE_CHAN_TO_TLS(c) (channel_tls_from_base_const((c)))
+#define CONST_TLS_CHAN_TO_BASE(c) (channel_tls_to_base_const((c)))
#define TLS_CHAN_MAGIC 0x8a192427U
@@ -44,6 +46,8 @@ channel_t * channel_tls_handle_incoming(or_connection_t *orconn);
channel_t * channel_tls_to_base(channel_tls_t *tlschan);
channel_tls_t * channel_tls_from_base(channel_t *chan);
+const channel_t * channel_tls_to_base_const(const channel_tls_t *tlschan);
+const channel_tls_t * channel_tls_from_base_const(const channel_t *chan);
/* Things for connection_or.c to call back into */
void channel_tls_handle_cell(cell_t *cell, or_connection_t *conn);
diff --git a/src/core/or/circuit_st.h b/src/core/or/circuit_st.h
index 4baafb1848..35d214ce08 100644
--- a/src/core/or/circuit_st.h
+++ b/src/core/or/circuit_st.h
@@ -238,6 +238,12 @@ struct circuit_t {
* Each element of this array corresponds to a different padding machine,
* and we can have up to CIRCPAD_MAX_MACHINES such machines. */
struct circpad_machine_runtime_t *padding_info[CIRCPAD_MAX_MACHINES];
+
+ /** padding_machine_ctr increments each time a new padding machine
+ * is negotiated. It is used for shutdown conditions, to ensure
+ * that STOP commands actually correspond to the current machine,
+ * and not a previous one. */
+ uint32_t padding_machine_ctr;
};
#endif /* !defined(CIRCUIT_ST_H) */
diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c
index ec61b4a455..78501c0aa2 100644
--- a/src/core/or/circuitbuild.c
+++ b/src/core/or/circuitbuild.c
@@ -7,7 +7,7 @@
/**
* \file circuitbuild.c
*
- * \brief Implements the details of building circuits (by chosing paths,
+ * \brief Implements the details of building circuits (by choosing paths,
* constructing/sending create/extend cells, and so on).
*
* On the client side, this module handles launching circuits. Circuit
@@ -45,10 +45,12 @@
#include "core/or/command.h"
#include "core/or/connection_edge.h"
#include "core/or/connection_or.h"
+#include "core/or/extendinfo.h"
#include "core/or/onion.h"
#include "core/or/ocirc_event.h"
#include "core/or/policies.h"
#include "core/or/relay.h"
+#include "core/or/trace_probes_circuit.h"
#include "core/or/crypt_path.h"
#include "feature/client/bridges.h"
#include "feature/client/circpathbias.h"
@@ -70,6 +72,7 @@
#include "feature/rend/rendcommon.h"
#include "feature/stats/predict_ports.h"
#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/trace/events.h"
#include "core/or/cell_st.h"
#include "core/or/cpath_build_state_st.h"
@@ -78,9 +81,6 @@
#include "feature/nodelist/node_st.h"
#include "core/or/or_circuit_st.h"
#include "core/or/origin_circuit_st.h"
-#include "feature/nodelist/microdesc_st.h"
-#include "feature/nodelist/routerinfo_st.h"
-#include "feature/nodelist/routerstatus_st.h"
static int circuit_send_first_onion_skin(origin_circuit_t *circ);
static int circuit_build_no_more_hops(origin_circuit_t *circ);
@@ -96,13 +96,17 @@ static const node_t *choose_good_middle_server(uint8_t purpose,
* callbacks.
*/
MOCK_IMPL(channel_t *,
-channel_connect_for_circuit,(const tor_addr_t *addr, uint16_t port,
- const char *id_digest,
- const struct ed25519_public_key_t *ed_id))
+channel_connect_for_circuit,(const extend_info_t *ei))
{
channel_t *chan;
- chan = channel_connect(addr, port, id_digest, ed_id);
+ const tor_addr_port_t *orport = extend_info_pick_orport(ei);
+ if (!orport)
+ return NULL;
+ const char *id_digest = ei->identity_digest;
+ const ed25519_public_key_t *ed_id = &ei->ed_identity;
+
+ chan = channel_connect(&orport->addr, orport->port, id_digest, ed_id);
if (chan) command_setup_channel(chan);
return chan;
@@ -439,7 +443,8 @@ onion_populate_cpath(origin_circuit_t *circ)
/** Create and return a new origin circuit. Initialize its purpose and
* build-state based on our arguments. The <b>flags</b> argument is a
- * bitfield of CIRCLAUNCH_* flags. */
+ * bitfield of CIRCLAUNCH_* flags, see circuit_launch_by_extend_info() for
+ * more details. */
origin_circuit_t *
origin_circuit_init(uint8_t purpose, int flags)
{
@@ -455,13 +460,16 @@ origin_circuit_init(uint8_t purpose, int flags)
((flags & CIRCLAUNCH_NEED_CAPACITY) ? 1 : 0);
circ->build_state->is_internal =
((flags & CIRCLAUNCH_IS_INTERNAL) ? 1 : 0);
+ circ->build_state->is_ipv6_selftest =
+ ((flags & CIRCLAUNCH_IS_IPV6_SELFTEST) ? 1 : 0);
circ->base_.purpose = purpose;
return circ;
}
-/** Build a new circuit for <b>purpose</b>. If <b>exit</b>
- * is defined, then use that as your exit router, else choose a suitable
- * exit node.
+/** Build a new circuit for <b>purpose</b>. If <b>exit</b> is defined, then use
+ * that as your exit router, else choose a suitable exit node. The <b>flags</b>
+ * argument is a bitfield of CIRCLAUNCH_* flags, see
+ * circuit_launch_by_extend_info() for more details.
*
* Also launch a connection to the first OR in the chosen path, if
* it's not open already.
@@ -491,6 +499,8 @@ circuit_establish_circuit(uint8_t purpose, extend_info_t *exit_ei, int flags)
circuit_mark_for_close(TO_CIRCUIT(circ), -err_reason);
return NULL;
}
+
+ tor_trace(TR_SUBSYS(circuit), TR_EV(establish), circ);
return circ;
}
@@ -546,7 +556,7 @@ circuit_handle_first_hop(origin_circuit_t *circ)
* - the address is internal, and
* - we're not connecting to a configured bridge, and
* - we're not configured to allow extends to private addresses. */
- if (tor_addr_is_internal(&firsthop->extend_info->addr, 0) &&
+ if (extend_info_any_orport_addr_is_internal(firsthop->extend_info) &&
!extend_info_is_a_configured_bridge(firsthop->extend_info) &&
!options->ExtendAllowPrivateAddresses) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
@@ -555,19 +565,16 @@ circuit_handle_first_hop(origin_circuit_t *circ)
}
/* now see if we're already connected to the first OR in 'route' */
- log_debug(LD_CIRC,"Looking for firsthop '%s'",
- fmt_addrport(&firsthop->extend_info->addr,
- firsthop->extend_info->port));
-
- /* We'll cleanup this code in #33220, when we add an IPv6 address to
- * extend_info_t. */
- const bool addr_is_ipv4 =
- (tor_addr_family(&firsthop->extend_info->addr) == AF_INET);
+ const tor_addr_port_t *orport4 =
+ extend_info_get_orport(firsthop->extend_info, AF_INET);
+ const tor_addr_port_t *orport6 =
+ extend_info_get_orport(firsthop->extend_info, AF_INET6);
n_chan = channel_get_for_extend(
firsthop->extend_info->identity_digest,
&firsthop->extend_info->ed_identity,
- addr_is_ipv4 ? &firsthop->extend_info->addr : NULL,
- addr_is_ipv4 ? NULL : &firsthop->extend_info->addr,
+ orport4 ? &orport4->addr : NULL,
+ orport6 ? &orport6->addr : NULL,
+ true,
&msg,
&should_launch);
@@ -579,15 +586,16 @@ circuit_handle_first_hop(origin_circuit_t *circ)
circ->base_.n_hop = extend_info_dup(firsthop->extend_info);
if (should_launch) {
- n_chan = channel_connect_for_circuit(
- &firsthop->extend_info->addr,
- firsthop->extend_info->port,
- firsthop->extend_info->identity_digest,
- &firsthop->extend_info->ed_identity);
+ n_chan = channel_connect_for_circuit(firsthop->extend_info);
if (!n_chan) { /* connect failed, forget the whole thing */
log_info(LD_CIRC,"connect to firsthop failed. Closing.");
return -END_CIRC_REASON_CONNECTFAILED;
}
+ /* We didn't find a channel, but we're launching one for an origin
+ * circuit. (If we decided not to launch a channel, then we found at
+ * least one once good in-progress channel use for this circuit, and
+ * marked it in channel_get_for_extend().) */
+ channel_mark_as_used_for_origin_circuit(n_chan);
circuit_chan_publish(circ, n_chan);
}
@@ -600,8 +608,11 @@ circuit_handle_first_hop(origin_circuit_t *circ)
} else { /* it's already open. use it. */
tor_assert(!circ->base_.n_hop);
circ->base_.n_chan = n_chan;
+ /* We found a channel, and we're using it for an origin circuit. */
+ channel_mark_as_used_for_origin_circuit(n_chan);
circuit_chan_publish(circ, n_chan);
- log_debug(LD_CIRC,"Conn open. Delivering first onion skin.");
+ log_debug(LD_CIRC,"Conn open for %s. Delivering first onion skin.",
+ safe_str_client(extend_info_describe(firsthop->extend_info)));
if ((err_reason = circuit_send_next_onion_skin(circ)) < 0) {
log_info(LD_CIRC,"circuit_send_next_onion_skin failed.");
circ->base_.n_chan = NULL;
@@ -629,7 +640,7 @@ circuit_n_chan_done(channel_t *chan, int status, int close_origin_circuits)
tor_assert(chan);
log_debug(LD_CIRC,"chan to %s, status=%d",
- channel_get_canonical_remote_descr(chan), status);
+ channel_describe_peer(chan), status);
pending_circs = smartlist_new();
circuit_get_all_pending_on_channel(pending_circs, chan);
@@ -783,27 +794,15 @@ circuit_deliver_create_cell,(circuit_t *circ,
return -1;
}
-/** Return true iff we should send a create_fast cell to start building a given
- * circuit */
-static inline int
+/** Return true iff we should send a create_fast cell to start building a
+ * given circuit */
+static inline bool
should_use_create_fast_for_circuit(origin_circuit_t *circ)
{
- const or_options_t *options = get_options();
tor_assert(circ->cpath);
tor_assert(circ->cpath->extend_info);
- if (!circuit_has_usable_onion_key(circ)) {
- /* We don't have ntor, and we don't have or can't use TAP,
- * so our hand is forced: only a create_fast will work. */
- return 1;
- }
- if (public_server_mode(options)) {
- /* We're a server, and we have a usable onion key. We can choose.
- * Prefer to blend our circuit into the other circuits we are
- * creating on behalf of others. */
- return 0;
- }
- return networkstatus_get_param(NULL, "usecreatefast", 0, 0, 1);
+ return ! circuit_has_usable_onion_key(circ);
}
/**
@@ -882,14 +881,22 @@ circuit_pick_extend_handshake(uint8_t *cell_type_out,
}
/**
- * Return true iff <b>purpose</b> is a purpose for a circuit which is
- * allowed to have no guard configured, even if the circuit is multihop
+ * Return true iff <b>circ</b> is allowed
+ * to have no guard configured, even if the circuit is multihop
* and guards are enabled.
*/
static int
-circuit_purpose_may_omit_guard(int purpose)
+circuit_may_omit_guard(const origin_circuit_t *circ)
{
- switch (purpose) {
+ if (BUG(!circ))
+ return 0;
+
+ if (circ->first_hop_from_controller) {
+ /* The controller picked the first hop: that bypasses the guard system. */
+ return 1;
+ }
+
+ switch (circ->base_.purpose) {
case CIRCUIT_PURPOSE_TESTING:
case CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT:
/* Testing circuits may omit guards because they're measuring
@@ -998,6 +1005,7 @@ circuit_send_first_onion_skin(origin_circuit_t *circ)
if (circuit_deliver_create_cell(TO_CIRCUIT(circ), &cc, 0) < 0)
return - END_CIRC_REASON_RESOURCELIMIT;
+ tor_trace(TR_SUBSYS(circuit), TR_EV(first_onion_skin), circ, circ->cpath);
circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
@@ -1019,7 +1027,7 @@ circuit_build_no_more_hops(origin_circuit_t *circ)
guard_usable_t r;
if (! circ->guard_state) {
if (circuit_get_cpath_len(circ) != 1 &&
- ! circuit_purpose_may_omit_guard(circ->base_.purpose) &&
+ ! circuit_may_omit_guard(circ) &&
get_options()->UseEntryGuards) {
log_warn(LD_BUG, "%d-hop circuit %p with purpose %d has no "
"guard state",
@@ -1068,8 +1076,8 @@ circuit_build_no_more_hops(origin_circuit_t *circ)
control_event_bootstrap(BOOTSTRAP_STATUS_DONE, 0);
control_event_client_status(LOG_NOTICE, "CIRCUIT_ESTABLISHED");
clear_broken_connection_map(1);
- if (server_mode(options) && !check_whether_orport_reachable(options)) {
- inform_testing_reachability();
+ if (server_mode(options) &&
+ !router_all_orports_seem_reachable(options)) {
router_do_reachability_checks(1, 1);
}
}
@@ -1093,23 +1101,40 @@ circuit_send_intermediate_onion_skin(origin_circuit_t *circ,
{
int len;
extend_cell_t ec;
+ /* Relays and bridges can send IPv6 extends. But for clients, it's an
+ * obvious version distinguisher. */
+ const bool include_ipv6 = server_mode(get_options());
memset(&ec, 0, sizeof(ec));
+ tor_addr_make_unspec(&ec.orport_ipv4.addr);
+ tor_addr_make_unspec(&ec.orport_ipv6.addr);
log_debug(LD_CIRC,"starting to send subsequent skin.");
- if (tor_addr_family(&hop->extend_info->addr) != AF_INET) {
- log_warn(LD_BUG, "Trying to extend to a non-IPv4 address.");
- return - END_CIRC_REASON_INTERNAL;
- }
-
circuit_pick_extend_handshake(&ec.cell_type,
&ec.create_cell.cell_type,
&ec.create_cell.handshake_type,
hop->extend_info);
- tor_addr_copy(&ec.orport_ipv4.addr, &hop->extend_info->addr);
- ec.orport_ipv4.port = hop->extend_info->port;
- tor_addr_make_unspec(&ec.orport_ipv6.addr);
+ const tor_addr_port_t *orport4 =
+ extend_info_get_orport(hop->extend_info, AF_INET);
+ const tor_addr_port_t *orport6 =
+ extend_info_get_orport(hop->extend_info, AF_INET6);
+ int n_addrs_set = 0;
+ if (orport4) {
+ tor_addr_copy(&ec.orport_ipv4.addr, &orport4->addr);
+ ec.orport_ipv4.port = orport4->port;
+ ++n_addrs_set;
+ }
+ if (orport6 && include_ipv6) {
+ tor_addr_copy(&ec.orport_ipv6.addr, &orport6->addr);
+ ec.orport_ipv6.port = orport6->port;
+ ++n_addrs_set;
+ }
+
+ if (n_addrs_set == 0) {
+ log_warn(LD_BUG, "No supported address family found in extend_info.");
+ return - END_CIRC_REASON_INTERNAL;
+ }
memcpy(ec.node_id, hop->extend_info->identity_digest, DIGEST_LEN);
/* Set the ED25519 identity too -- it will only get included
* in the extend2 cell if we're configured to use it, though. */
@@ -1144,6 +1169,7 @@ circuit_send_intermediate_onion_skin(origin_circuit_t *circ,
return 0; /* circuit is closed */
}
hop->state = CPATH_STATE_AWAITING_KEYS;
+ tor_trace(TR_SUBSYS(circuit), TR_EV(intermediate_onion_skin), circ, hop);
return 0;
}
@@ -1557,7 +1583,23 @@ choose_good_exit_server_general(router_crn_flags_t flags)
const node_t *selected_node=NULL;
const int need_uptime = (flags & CRN_NEED_UPTIME) != 0;
const int need_capacity = (flags & CRN_NEED_CAPACITY) != 0;
- const int direct_conn = (flags & CRN_DIRECT_CONN) != 0;
+
+ /* We should not require guard flags on exits. */
+ IF_BUG_ONCE(flags & CRN_NEED_GUARD)
+ return NULL;
+
+ /* We reject single-hop exits for all node positions. */
+ IF_BUG_ONCE(flags & CRN_DIRECT_CONN)
+ return NULL;
+
+ /* This isn't the function for picking rendezvous nodes. */
+ IF_BUG_ONCE(flags & CRN_RENDEZVOUS_V3)
+ return NULL;
+
+ /* We only want exits to extend if we cannibalize the circuit.
+ * But we don't require IPv6 extends yet. */
+ IF_BUG_ONCE(flags & CRN_INITIATE_IPV6_EXTEND)
+ return NULL;
connections = get_connection_array();
@@ -1590,19 +1632,14 @@ choose_good_exit_server_general(router_crn_flags_t flags)
*/
continue;
}
- if (!node_has_preferred_descriptor(node, direct_conn)) {
+ if (!router_can_choose_node(node, flags)) {
n_supported[i] = -1;
continue;
}
- if (!node->is_running || node->is_bad_exit) {
+ if (node->is_bad_exit) {
n_supported[i] = -1;
continue; /* skip routers that are known to be down or bad exits */
}
- if (node_get_purpose(node) != ROUTER_PURPOSE_GENERAL) {
- /* never pick a non-general node as a random exit. */
- n_supported[i] = -1;
- continue;
- }
if (routerset_contains_node(options->ExcludeExitNodesUnion_, node)) {
n_supported[i] = -1;
continue; /* user asked us not to use it, no matter what */
@@ -1612,27 +1649,6 @@ choose_good_exit_server_general(router_crn_flags_t flags)
n_supported[i] = -1;
continue; /* not one of our chosen exit nodes */
}
-
- if (node_is_unreliable(node, need_uptime, need_capacity, 0)) {
- n_supported[i] = -1;
- continue; /* skip routers that are not suitable. Don't worry if
- * this makes us reject all the possible routers: if so,
- * we'll retry later in this function with need_update and
- * need_capacity set to 0. */
- }
- if (!(node->is_valid)) {
- /* if it's invalid and we don't want it */
- n_supported[i] = -1;
-// log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- invalid router.",
-// router->nickname, i);
- continue; /* skip invalid routers */
- }
- /* We do not allow relays that allow single hop exits by default. Option
- * was deprecated in 0.2.9.2-alpha and removed in 0.3.1.0-alpha. */
- if (node_allows_single_hop_exits(node)) {
- n_supported[i] = -1;
- continue;
- }
if (node_exit_policy_rejects_all(node)) {
n_supported[i] = -1;
// log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- it rejects all.",
@@ -1783,35 +1799,29 @@ pick_restricted_middle_node(router_crn_flags_t flags,
{
const node_t *middle_node = NULL;
- smartlist_t *whitelisted_live_middles = smartlist_new();
+ smartlist_t *allowlisted_live_middles = smartlist_new();
smartlist_t *all_live_nodes = smartlist_new();
tor_assert(pick_from);
/* Add all running nodes to all_live_nodes */
- router_add_running_nodes_to_smartlist(all_live_nodes,
- (flags & CRN_NEED_UPTIME) != 0,
- (flags & CRN_NEED_CAPACITY) != 0,
- (flags & CRN_NEED_GUARD) != 0,
- (flags & CRN_NEED_DESC) != 0,
- (flags & CRN_PREF_ADDR) != 0,
- (flags & CRN_DIRECT_CONN) != 0);
-
- /* Filter all_live_nodes to only add live *and* whitelisted middles
- * to the list whitelisted_live_middles. */
+ router_add_running_nodes_to_smartlist(all_live_nodes, flags);
+
+ /* Filter all_live_nodes to only add live *and* allowlisted middles
+ * to the list allowlisted_live_middles. */
SMARTLIST_FOREACH_BEGIN(all_live_nodes, node_t *, live_node) {
if (routerset_contains_node(pick_from, live_node)) {
- smartlist_add(whitelisted_live_middles, live_node);
+ smartlist_add(allowlisted_live_middles, live_node);
}
} SMARTLIST_FOREACH_END(live_node);
/* Honor ExcludeNodes */
if (exclude_set) {
- routerset_subtract_nodes(whitelisted_live_middles, exclude_set);
+ routerset_subtract_nodes(allowlisted_live_middles, exclude_set);
}
if (exclude_list) {
- smartlist_subtract(whitelisted_live_middles, exclude_list);
+ smartlist_subtract(allowlisted_live_middles, exclude_list);
}
/**
@@ -1827,9 +1837,9 @@ pick_restricted_middle_node(router_crn_flags_t flags,
* If there are a lot of nodes in here, assume they did not load balance
* and do it for them, but also warn them that they may be Doing It Wrong.
*/
- if (smartlist_len(whitelisted_live_middles) <=
+ if (smartlist_len(allowlisted_live_middles) <=
MAX_SANE_RESTRICTED_NODES) {
- middle_node = smartlist_choose(whitelisted_live_middles);
+ middle_node = smartlist_choose(allowlisted_live_middles);
} else {
static ratelim_t pinned_notice_limit = RATELIM_INIT(24*3600);
log_fn_ratelim(&pinned_notice_limit, LOG_NOTICE, LD_CIRC,
@@ -1837,17 +1847,17 @@ pick_restricted_middle_node(router_crn_flags_t flags,
"in %d total nodes. This is a lot of nodes. "
"You may want to consider using a Tor controller "
"to select and update a smaller set of nodes instead.",
- position_hint, smartlist_len(whitelisted_live_middles));
+ position_hint, smartlist_len(allowlisted_live_middles));
/* NO_WEIGHTING here just means don't take node flags into account
* (ie: use consensus measurement only). This is done so that
* we don't further surprise the user by not using Exits that they
* specified at all */
- middle_node = node_sl_choose_by_bandwidth(whitelisted_live_middles,
+ middle_node = node_sl_choose_by_bandwidth(allowlisted_live_middles,
NO_WEIGHTING);
}
- smartlist_free(whitelisted_live_middles);
+ smartlist_free(allowlisted_live_middles);
smartlist_free(all_live_nodes);
return middle_node;
@@ -1975,6 +1985,43 @@ warn_if_last_router_excluded(origin_circuit_t *circ,
return;
}
+/* Return a set of generic CRN_* flags based on <b>state</b>.
+ *
+ * Called for every position in the circuit. */
+STATIC int
+cpath_build_state_to_crn_flags(const cpath_build_state_t *state)
+{
+ router_crn_flags_t flags = 0;
+ /* These flags apply to entry, middle, and exit nodes.
+ * If a flag only applies to a specific position, it should be checked in
+ * that function. */
+ if (state->need_uptime)
+ flags |= CRN_NEED_UPTIME;
+ if (state->need_capacity)
+ flags |= CRN_NEED_CAPACITY;
+ return flags;
+}
+
+/* Return the CRN_INITIATE_IPV6_EXTEND flag, based on <b>state</b> and
+ * <b>cur_len</b>.
+ *
+ * Only called for middle nodes (for now). Must not be called on single-hop
+ * circuits. */
+STATIC int
+cpath_build_state_to_crn_ipv6_extend_flag(const cpath_build_state_t *state,
+ int cur_len)
+{
+ IF_BUG_ONCE(state->desired_path_len < 2)
+ return 0;
+
+ /* The last node is the relay doing the self-test. So we want to extend over
+ * IPv6 from the second-last node. */
+ if (state->is_ipv6_selftest && cur_len == state->desired_path_len - 2)
+ return CRN_INITIATE_IPV6_EXTEND;
+ else
+ return 0;
+}
+
/** Decide a suitable length for circ's cpath, and pick an exit
* router (or use <b>exit</b> if provided). Store these in the
* cpath.
@@ -2008,14 +2055,13 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit_ei,
exit_ei = extend_info_dup(exit_ei);
} else { /* we have to decide one */
router_crn_flags_t flags = CRN_NEED_DESC;
- if (state->need_uptime)
- flags |= CRN_NEED_UPTIME;
- if (state->need_capacity)
- flags |= CRN_NEED_CAPACITY;
- if (is_hs_v3_rp_circuit)
- flags |= CRN_RENDEZVOUS_V3;
+ flags |= cpath_build_state_to_crn_flags(state);
+ /* Some internal exits are one hop, for example directory connections.
+ * (Guards are always direct, middles are never direct.) */
if (state->onehop_tunnel)
flags |= CRN_DIRECT_CONN;
+ if (is_hs_v3_rp_circuit)
+ flags |= CRN_RENDEZVOUS_V3;
const node_t *node =
choose_good_exit_server(circ, flags, state->is_internal);
if (!node) {
@@ -2077,32 +2123,27 @@ circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *exit_ei)
return 0;
}
-/** Return the number of routers in <b>routers</b> that are currently up
- * and available for building circuits through.
+/** Return the number of routers in <b>nodes</b> that are currently up and
+ * available for building circuits through.
*
- * (Note that this function may overcount or undercount, if we have
- * descriptors that are not the type we would prefer to use for some
- * particular router. See bug #25885.)
+ * If <b>direct</b> is true, only count nodes that are suitable for direct
+ * connections. Counts nodes regardless of whether their addresses are
+ * preferred.
*/
MOCK_IMPL(STATIC int,
count_acceptable_nodes, (const smartlist_t *nodes, int direct))
{
int num=0;
+ int flags = CRN_NEED_DESC;
+
+ if (direct)
+ flags |= CRN_DIRECT_CONN;
SMARTLIST_FOREACH_BEGIN(nodes, const node_t *, node) {
// log_debug(LD_CIRC,
-// "Contemplating whether router %d (%s) is a new option.",
-// i, r->nickname);
- if (! node->is_running)
-// log_debug(LD_CIRC,"Nope, the directory says %d is not running.",i);
- continue;
- if (! node->is_valid)
-// log_debug(LD_CIRC,"Nope, the directory says %d is not valid.",i);
- continue;
- if (! node_has_preferred_descriptor(node, direct))
- continue;
- /* The node has a descriptor, so we can just check the ntor key directly */
- if (!node_has_curve25519_onion_key(node))
+ // "Contemplating whether router %d (%s) is a new option.",
+ // i, r->nickname);
+ if (!router_can_choose_node(node, flags))
continue;
++num;
} SMARTLIST_FOREACH_END(node);
@@ -2127,7 +2168,7 @@ count_acceptable_nodes, (const smartlist_t *nodes, int direct))
* The alternative is building the circuit in reverse. Reverse calls to
* onion_extend_cpath() (ie: select outer hops first) would then have the
* property that you don't gain information about inner hops by observing
- * outer ones. See https://trac.torproject.org/projects/tor/ticket/24487
+ * outer ones. See https://bugs.torproject.org/tpo/core/tor/24487
* for this.
*
* (Note further that we still exclude the exit to prevent A - B - A
@@ -2296,10 +2337,8 @@ choose_good_middle_server(uint8_t purpose,
excluded = build_middle_exclude_list(purpose, state, head, cur_len);
- if (state->need_uptime)
- flags |= CRN_NEED_UPTIME;
- if (state->need_capacity)
- flags |= CRN_NEED_CAPACITY;
+ flags |= cpath_build_state_to_crn_flags(state);
+ flags |= cpath_build_state_to_crn_ipv6_extend_flag(state, cur_len);
/** If a hidden service circuit wants a specific middle node, pin it. */
if (middle_node_must_be_vanguard(options, purpose, cur_len)) {
@@ -2375,10 +2414,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state,
}
if (state) {
- if (state->need_uptime)
- flags |= CRN_NEED_UPTIME;
- if (state->need_capacity)
- flags |= CRN_NEED_CAPACITY;
+ flags |= cpath_build_state_to_crn_flags(state);
}
choice = router_choose_random_node(excluded, options->ExcludeNodes, flags);
@@ -2428,7 +2464,6 @@ onion_extend_cpath(origin_circuit_t *circ)
choose_good_middle_server(purpose, state, circ->cpath, cur_len);
if (r) {
info = extend_info_from_node(r, 0);
- tor_assert_nonfatal(info);
}
}
@@ -2447,143 +2482,6 @@ onion_extend_cpath(origin_circuit_t *circ)
return 0;
}
-/** Allocate a new extend_info object based on the various arguments. */
-extend_info_t *
-extend_info_new(const char *nickname,
- const char *rsa_id_digest,
- const ed25519_public_key_t *ed_id,
- crypto_pk_t *onion_key,
- const curve25519_public_key_t *ntor_key,
- const tor_addr_t *addr, uint16_t port)
-{
- extend_info_t *info = tor_malloc_zero(sizeof(extend_info_t));
- memcpy(info->identity_digest, rsa_id_digest, DIGEST_LEN);
- if (ed_id && !ed25519_public_key_is_zero(ed_id))
- memcpy(&info->ed_identity, ed_id, sizeof(ed25519_public_key_t));
- if (nickname)
- strlcpy(info->nickname, nickname, sizeof(info->nickname));
- if (onion_key)
- info->onion_key = crypto_pk_dup_key(onion_key);
- if (ntor_key)
- memcpy(&info->curve25519_onion_key, ntor_key,
- sizeof(curve25519_public_key_t));
- tor_addr_copy(&info->addr, addr);
- info->port = port;
- return info;
-}
-
-/** Allocate and return a new extend_info that can be used to build a
- * circuit to or through the node <b>node</b>. Use the primary address
- * of the node (i.e. its IPv4 address) unless
- * <b>for_direct_connect</b> is true, in which case the preferred
- * address is used instead. May return NULL if there is not enough
- * info about <b>node</b> to extend to it--for example, if the preferred
- * routerinfo_t or microdesc_t is missing, or if for_direct_connect is
- * true and none of the node's addresses is allowed by tor's firewall
- * and IP version config.
- **/
-extend_info_t *
-extend_info_from_node(const node_t *node, int for_direct_connect)
-{
- crypto_pk_t *rsa_pubkey = NULL;
- extend_info_t *info = NULL;
- tor_addr_port_t ap;
- int valid_addr = 0;
-
- if (!node_has_preferred_descriptor(node, for_direct_connect)) {
- return NULL;
- }
-
- /* Choose a preferred address first, but fall back to an allowed address. */
- if (for_direct_connect)
- fascist_firewall_choose_address_node(node, FIREWALL_OR_CONNECTION, 0, &ap);
- else {
- node_get_prim_orport(node, &ap);
- }
- valid_addr = tor_addr_port_is_valid_ap(&ap, 0);
-
- if (valid_addr)
- log_debug(LD_CIRC, "using %s for %s",
- fmt_addrport(&ap.addr, ap.port),
- node->ri ? node->ri->nickname : node->rs->nickname);
- else
- log_warn(LD_CIRC, "Could not choose valid address for %s",
- node->ri ? node->ri->nickname : node->rs->nickname);
-
- /* Every node we connect or extend to must support ntor */
- if (!node_has_curve25519_onion_key(node)) {
- log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
- "Attempted to create extend_info for a node that does not support "
- "ntor: %s", node_describe(node));
- return NULL;
- }
-
- const ed25519_public_key_t *ed_pubkey = NULL;
-
- /* Don't send the ed25519 pubkey unless the target node actually supports
- * authenticating with it. */
- if (node_supports_ed25519_link_authentication(node, 0)) {
- log_info(LD_CIRC, "Including Ed25519 ID for %s", node_describe(node));
- ed_pubkey = node_get_ed25519_id(node);
- } else if (node_get_ed25519_id(node)) {
- log_info(LD_CIRC, "Not including the ed25519 ID for %s, since it won't "
- "be able to authenticate it.",
- node_describe(node));
- }
-
- /* Retrieve the curve25519 pubkey. */
- const curve25519_public_key_t *curve_pubkey =
- node_get_curve25519_onion_key(node);
- rsa_pubkey = node_get_rsa_onion_key(node);
-
- if (valid_addr && node->ri) {
- info = extend_info_new(node->ri->nickname,
- node->identity,
- ed_pubkey,
- rsa_pubkey,
- curve_pubkey,
- &ap.addr,
- ap.port);
- } else if (valid_addr && node->rs && node->md) {
- info = extend_info_new(node->rs->nickname,
- node->identity,
- ed_pubkey,
- rsa_pubkey,
- curve_pubkey,
- &ap.addr,
- ap.port);
- }
-
- crypto_pk_free(rsa_pubkey);
- return info;
-}
-
-/** Release storage held by an extend_info_t struct. */
-void
-extend_info_free_(extend_info_t *info)
-{
- if (!info)
- return;
- crypto_pk_free(info->onion_key);
- tor_free(info);
-}
-
-/** Allocate and return a new extend_info_t with the same contents as
- * <b>info</b>. */
-extend_info_t *
-extend_info_dup(extend_info_t *info)
-{
- extend_info_t *newinfo;
- tor_assert(info);
- newinfo = tor_malloc(sizeof(extend_info_t));
- memcpy(newinfo, info, sizeof(extend_info_t));
- if (info->onion_key)
- newinfo->onion_key = crypto_pk_dup_key(info->onion_key);
- else
- newinfo->onion_key = NULL;
- return newinfo;
-}
-
/** Return the node_t for the chosen exit router in <b>state</b>.
* If there is no chosen exit, or if we don't know the node_t for
* the chosen exit, return NULL.
@@ -2619,43 +2517,6 @@ build_state_get_exit_nickname(cpath_build_state_t *state)
return state->chosen_exit->nickname;
}
-/** Return true iff the given address can be used to extend to. */
-int
-extend_info_addr_is_allowed(const tor_addr_t *addr)
-{
- tor_assert(addr);
-
- /* Check if we have a private address and if we can extend to it. */
- if ((tor_addr_is_internal(addr, 0) || tor_addr_is_multicast(addr)) &&
- !get_options()->ExtendAllowPrivateAddresses) {
- goto disallow;
- }
- /* Allowed! */
- return 1;
- disallow:
- return 0;
-}
-
-/* Does ei have a valid TAP key? */
-int
-extend_info_supports_tap(const extend_info_t* ei)
-{
- tor_assert(ei);
- /* Valid TAP keys are not NULL */
- return ei->onion_key != NULL;
-}
-
-/* Does ei have a valid ntor key? */
-int
-extend_info_supports_ntor(const extend_info_t* ei)
-{
- tor_assert(ei);
- /* Valid ntor keys have at least one non-zero byte */
- return !fast_mem_is_zero(
- (const char*)ei->curve25519_onion_key.public_key,
- CURVE25519_PUBKEY_LEN);
-}
-
/* Is circuit purpose allowed to use the deprecated TAP encryption protocol?
* The hidden service protocol still uses TAP for some connections, because
* ntor onion keys aren't included in HS descriptors or INTRODUCE cells. */
@@ -2690,15 +2551,6 @@ circuit_has_usable_onion_key(const origin_circuit_t *circ)
circuit_can_use_tap(circ));
}
-/* Does ei have an onion key which it would prefer to use?
- * Currently, we prefer ntor keys*/
-int
-extend_info_has_preferred_onion_key(const extend_info_t* ei)
-{
- tor_assert(ei);
- return extend_info_supports_ntor(ei);
-}
-
/** Find the circuits that are waiting to find out whether their guards are
* usable, and if any are ready to become usable, mark them open and try
* attaching streams as appropriate. */
diff --git a/src/core/or/circuitbuild.h b/src/core/or/circuitbuild.h
index e62bb41de9..0cd1eb4f45 100644
--- a/src/core/or/circuitbuild.h
+++ b/src/core/or/circuitbuild.h
@@ -42,23 +42,8 @@ MOCK_DECL(int, circuit_all_predicted_ports_handled, (time_t now,
int circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info);
int circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info);
-extend_info_t *extend_info_new(const char *nickname,
- const char *rsa_id_digest,
- const struct ed25519_public_key_t *ed_id,
- crypto_pk_t *onion_key,
- const struct curve25519_public_key_t *ntor_key,
- const tor_addr_t *addr, uint16_t port);
-extend_info_t *extend_info_from_node(const node_t *r, int for_direct_connect);
-extend_info_t *extend_info_dup(extend_info_t *info);
-void extend_info_free_(extend_info_t *info);
-#define extend_info_free(info) \
- FREE_AND_NULL(extend_info_t, extend_info_free_, (info))
-int extend_info_addr_is_allowed(const tor_addr_t *addr);
-int extend_info_supports_tap(const extend_info_t* ei);
-int extend_info_supports_ntor(const extend_info_t* ei);
int circuit_can_use_tap(const origin_circuit_t *circ);
int circuit_has_usable_onion_key(const origin_circuit_t *circ);
-int extend_info_has_preferred_onion_key(const extend_info_t* ei);
const uint8_t *build_state_get_exit_rsa_id(cpath_build_state_t *state);
MOCK_DECL(const node_t *,
build_state_get_exit_node,(cpath_build_state_t *state));
@@ -71,13 +56,7 @@ const node_t *choose_good_entry_server(uint8_t purpose,
struct circuit_guard_state_t **guard_state_out);
void circuit_upgrade_circuits_from_guard_wait(void);
-struct ed25519_public_key_t;
-
-MOCK_DECL(channel_t *,
-channel_connect_for_circuit,(const tor_addr_t *addr,
- uint16_t port,
- const char *id_digest,
- const struct ed25519_public_key_t *ed_id));
+MOCK_DECL(channel_t *, channel_connect_for_circuit,(const extend_info_t *ei));
struct create_cell_t;
MOCK_DECL(int,
@@ -97,6 +76,10 @@ STATIC int onion_extend_cpath(origin_circuit_t *circ);
STATIC int
onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit_ei,
int is_hs_v3_rp_circuit);
+STATIC int cpath_build_state_to_crn_flags(const cpath_build_state_t *state);
+STATIC int cpath_build_state_to_crn_ipv6_extend_flag(
+ const cpath_build_state_t *state,
+ int cur_len);
#endif /* defined(CIRCUITBUILD_PRIVATE) */
diff --git a/src/core/or/circuitlist.c b/src/core/or/circuitlist.c
index 384835667d..bd36683880 100644
--- a/src/core/or/circuitlist.c
+++ b/src/core/or/circuitlist.c
@@ -64,6 +64,8 @@
#include "core/or/circuitstats.h"
#include "core/or/circuitpadding.h"
#include "core/or/crypt_path.h"
+#include "core/or/extendinfo.h"
+#include "core/or/trace_probes_circuit.h"
#include "core/mainloop/connection.h"
#include "app/config/config.h"
#include "core/or/connection_edge.h"
@@ -89,6 +91,7 @@
#include "feature/rend/rendclient.h"
#include "feature/rend/rendcommon.h"
#include "feature/stats/predict_ports.h"
+#include "feature/stats/bwhist.h"
#include "feature/stats/rephist.h"
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/routerset.h"
@@ -564,6 +567,8 @@ circuit_set_state(circuit_t *circ, uint8_t state)
}
if (state == CIRCUIT_STATE_GUARD_WAIT || state == CIRCUIT_STATE_OPEN)
tor_assert(!circ->n_chan_create_cell);
+
+ tor_trace(TR_SUBSYS(circuit), TR_EV(change_state), circ, circ->state, state);
circ->state = state;
if (CIRCUIT_IS_ORIGIN(circ))
circuit_state_publish(circ);
@@ -614,7 +619,7 @@ circuit_count_pending_on_channel(channel_t *chan)
cnt = smartlist_len(sl);
smartlist_free(sl);
log_debug(LD_CIRC,"or_conn to %s, %d pending circs",
- channel_get_canonical_remote_descr(chan),
+ channel_describe_peer(chan),
cnt);
return cnt;
}
@@ -1078,6 +1083,7 @@ origin_circuit_new(void)
prediction_time_remaining);
}
+ tor_trace(TR_SUBSYS(circuit), TR_EV(new_origin), circ);
return circ;
}
@@ -1100,6 +1106,7 @@ or_circuit_new(circid_t p_circ_id, channel_t *p_chan)
init_circuit_base(TO_CIRCUIT(circ));
+ tor_trace(TR_SUBSYS(circuit), TR_EV(new_or), circ);
return circ;
}
@@ -1252,6 +1259,10 @@ circuit_free_(circuit_t *circ)
/* Clear all dangling handle references. */
circuit_handles_clear(circ);
+ /* Tracepoint. Data within the circuit object is recorded so do this before
+ * the actual memory free. */
+ tor_trace(TR_SUBSYS(circuit), TR_EV(free), circ);
+
if (should_free) {
memwipe(mem, 0xAA, memlen); /* poison memory */
tor_free(mem);
@@ -1944,7 +1955,7 @@ circuit_find_to_cannibalize(uint8_t purpose_to_produce, extend_info_t *info,
/* Ignore any circuits for which we can't use the Guard. It is possible
* that the Guard was removed from the sampled set after the circuit
- * was created so avoid using it. */
+ * was created, so avoid using it. */
if (!entry_guard_could_succeed(circ->guard_state)) {
goto next;
}
@@ -2133,7 +2144,7 @@ circuit_mark_all_dirty_circs_as_unusable(void)
* This function is in the critical path of circuit_mark_for_close().
* It must be (and is) O(1)!
*
- * See https://trac.torproject.org/projects/tor/ticket/23512.
+ * See https://bugs.torproject.org/tpo/core/tor/23512
*/
void
circuit_synchronize_written_or_bandwidth(const circuit_t *c,
@@ -2165,6 +2176,12 @@ circuit_synchronize_written_or_bandwidth(const circuit_t *c,
else
cell_size = CELL_MAX_NETWORK_SIZE;
+ /* If we know the channel, find out if it's IPv6. */
+ tor_addr_t remote_addr;
+ bool is_ipv6 = chan &&
+ channel_get_addr_if_possible(chan, &remote_addr) &&
+ tor_addr_family(&remote_addr) == AF_INET6;
+
/* The missing written bytes are the cell counts times their cell
* size plus TLS per cell overhead */
written_sync = cells*(cell_size+TLS_PER_CELL_OVERHEAD);
@@ -2172,7 +2189,7 @@ circuit_synchronize_written_or_bandwidth(const circuit_t *c,
/* Report the missing bytes as written, to avoid asymmetry.
* We must use time() for consistency with rephist, even though on
* some very old rare platforms, approx_time() may be faster. */
- rep_hist_note_bytes_written(written_sync, time(NULL));
+ bwhist_note_bytes_written(written_sync, time(NULL), is_ipv6);
}
/** Mark <b>circ</b> to be closed next time we call
@@ -2274,6 +2291,7 @@ circuit_mark_for_close_, (circuit_t *circ, int reason, int line,
CIRCUIT_IS_ORIGIN(circ) ?
TO_ORIGIN_CIRCUIT(circ)->global_identifier : 0,
file, line, orig_reason, reason);
+ tor_trace(TR_SUBSYS(circuit), TR_EV(mark_for_close), circ);
}
/** Called immediately before freeing a marked circuit <b>circ</b> from
@@ -2419,7 +2437,6 @@ single_conn_free_bytes(connection_t *conn)
if (conn->outbuf) {
result += buf_allocation(conn->outbuf);
buf_clear(conn->outbuf);
- conn->outbuf_flushlen = 0;
}
if (conn->type == CONN_TYPE_DIR) {
dir_connection_t *dir_conn = TO_DIR_CONN(conn);
diff --git a/src/core/or/circuitlist.h b/src/core/or/circuitlist.h
index fd7e22e4c0..bd4a117e26 100644
--- a/src/core/or/circuitlist.h
+++ b/src/core/or/circuitlist.h
@@ -114,9 +114,12 @@
#define CIRCUIT_PURPOSE_S_HSDIR_POST 20
#define CIRCUIT_PURPOSE_S_HS_MAX_ 20
-/** A testing circuit; not meant to be used for actual traffic. */
+/** A testing circuit; not meant to be used for actual traffic. It is used for
+ * bandwidth measurement, reachability test and address discovery from an
+ * authority using the NETINFO cell. */
#define CIRCUIT_PURPOSE_TESTING 21
-/** A controller made this circuit and Tor should not use it. */
+/** A controller made this circuit and Tor should not cannibalize it or attach
+ * streams to it without explicitly being told. */
#define CIRCUIT_PURPOSE_CONTROLLER 22
/** This circuit is used for path bias probing only */
#define CIRCUIT_PURPOSE_PATH_BIAS_TESTING 23
diff --git a/src/core/or/circuitmux.h b/src/core/or/circuitmux.h
index 191ca12e30..5e41ccc6ca 100644
--- a/src/core/or/circuitmux.h
+++ b/src/core/or/circuitmux.h
@@ -127,7 +127,7 @@ MOCK_DECL(unsigned int, circuitmux_num_cells, (circuitmux_t *cmux));
unsigned int circuitmux_num_circuits(circuitmux_t *cmux);
unsigned int circuitmux_num_active_circuits(circuitmux_t *cmux);
-/* Debuging interface - slow. */
+/* Debugging interface - slow. */
int64_t circuitmux_count_queued_destroy_cells(const channel_t *chan,
const circuitmux_t *cmux);
diff --git a/src/core/or/circuitpadding.c b/src/core/or/circuitpadding.c
index 43f4a31624..6dfe94de01 100644
--- a/src/core/or/circuitpadding.c
+++ b/src/core/or/circuitpadding.c
@@ -266,18 +266,31 @@ circpad_marked_circuit_for_padding(circuit_t *circ, int reason)
/**
* Free all the machineinfos in <b>circ</b> that match <b>machine_num</b>.
*
+ * If machine_ctr is non-zero, also make sure it matches the padding_info's
+ * machine counter before freeing.
+ *
* Returns true if any machineinfos with that number were freed.
* False otherwise. */
static int
-free_circ_machineinfos_with_machine_num(circuit_t *circ, int machine_num)
+free_circ_machineinfos_with_machine_num(circuit_t *circ, int machine_num,
+ uint32_t machine_ctr)
{
int found = 0;
FOR_EACH_CIRCUIT_MACHINE_BEGIN(i) {
if (circ->padding_machine[i] &&
circ->padding_machine[i]->machine_num == machine_num) {
- circpad_circuit_machineinfo_free_idx(circ, i);
- circ->padding_machine[i] = NULL;
- found = 1;
+ /* If machine_ctr is non-zero, make sure it matches too. This
+ * is to ensure that old STOP messages don't shutdown newer machines. */
+ if (machine_ctr && circ->padding_info[i] &&
+ circ->padding_info[i]->machine_ctr != machine_ctr) {
+ log_info(LD_CIRC,
+ "Padding shutdown for wrong (old?) machine ctr: %u vs %u",
+ machine_ctr, circ->padding_info[i]->machine_ctr);
+ } else {
+ circpad_circuit_machineinfo_free_idx(circ, i);
+ circ->padding_machine[i] = NULL;
+ found = 1;
+ }
}
} FOR_EACH_CIRCUIT_MACHINE_END;
@@ -306,6 +319,7 @@ circpad_circuit_machineinfo_new(circuit_t *on_circ, int machine_index)
mi->machine_index = machine_index;
mi->on_circ = on_circ;
mi->last_cell_time_sec = approx_time();
+ mi->machine_ctr = on_circ->padding_machine_ctr;
return mi;
}
@@ -1212,6 +1226,7 @@ circpad_send_padding_cell_for_callback(circpad_machine_runtime_t *mi)
circuit_t *circ = mi->on_circ;
int machine_idx = mi->machine_index;
mi->padding_scheduled_at_usec = 0;
+ mi->is_padding_timer_scheduled = 0;
circpad_statenum_t state = mi->current_state;
/* Make sure circuit didn't close on us */
@@ -1521,7 +1536,7 @@ circpad_machine_schedule_padding,(circpad_machine_runtime_t *mi))
/**
* If the machine transitioned to the END state, we need
* to check to see if it wants us to shut it down immediately.
- * If it does, then we need to send the appropiate negotiation commands
+ * If it does, then we need to send the appropriate negotiation commands
* depending on which side it is.
*
* After this function is called, mi may point to freed memory. Do
@@ -1556,19 +1571,23 @@ circpad_machine_spec_transitioned_to_end(circpad_machine_runtime_t *mi)
/* We free the machine info here so that we can be replaced
* by a different machine. But we must leave the padding_machine
* in place to wait for the negotiated response */
+ uint32_t machine_ctr = mi->machine_ctr;
circpad_circuit_machineinfo_free_idx(on_circ,
machine->machine_index);
circpad_negotiate_padding(TO_ORIGIN_CIRCUIT(on_circ),
machine->machine_num,
machine->target_hopnum,
- CIRCPAD_COMMAND_STOP);
+ CIRCPAD_COMMAND_STOP,
+ machine_ctr);
} else {
+ uint32_t machine_ctr = mi->machine_ctr;
circpad_circuit_machineinfo_free_idx(on_circ,
machine->machine_index);
circpad_padding_negotiated(on_circ,
machine->machine_num,
CIRCPAD_COMMAND_STOP,
- CIRCPAD_RESPONSE_OK);
+ CIRCPAD_RESPONSE_OK,
+ machine_ctr);
on_circ->padding_machine[machine->machine_index] = NULL;
}
}
@@ -1990,7 +2009,7 @@ circpad_internal_event_state_length_up(circpad_machine_runtime_t *mi)
* Returns true if the circuit matches the conditions.
*/
static inline bool
-circpad_machine_conditions_met(origin_circuit_t *circ,
+circpad_machine_conditions_apply(origin_circuit_t *circ,
const circpad_machine_spec_t *machine)
{
/* If padding is disabled, no machines should match/apply. This has
@@ -2007,7 +2026,7 @@ circpad_machine_conditions_met(origin_circuit_t *circ,
}
if (!(circpad_circ_purpose_to_mask(TO_CIRCUIT(circ)->purpose)
- & machine->conditions.purpose_mask))
+ & machine->conditions.apply_purpose_mask))
return 0;
if (machine->conditions.requires_vanguards) {
@@ -2023,7 +2042,7 @@ circpad_machine_conditions_met(origin_circuit_t *circ,
* "I want to apply to circuits with either streams or no streams"; OR
* "I only want to apply to circuits with streams"; OR
* "I only want to apply to circuits without streams". */
- if (!(circpad_circuit_state(circ) & machine->conditions.state_mask))
+ if (!(circpad_circuit_state(circ) & machine->conditions.apply_state_mask))
return 0;
if (circuit_get_cpath_opened_len(circ) < machine->conditions.min_hops)
@@ -2033,11 +2052,31 @@ circpad_machine_conditions_met(origin_circuit_t *circ,
}
/**
+ * Check to see if any of the keep conditions still apply to this circuit.
+ *
+ * These conditions keep the machines active if they match, but do not
+ * cause new machines to start up.
+ */
+static inline bool
+circpad_machine_conditions_keep(origin_circuit_t *circ,
+ const circpad_machine_spec_t *machine)
+{
+ if ((circpad_circ_purpose_to_mask(TO_CIRCUIT(circ)->purpose)
+ & machine->conditions.keep_purpose_mask))
+ return 1;
+
+ if ((circpad_circuit_state(circ) & machine->conditions.keep_state_mask))
+ return 1;
+
+ return 0;
+}
+
+/**
* Returns a minimized representation of the circuit state.
*
* The padding code only cares if the circuit is building,
* opened, used for streams, and/or still has relay early cells.
- * This returns a bitmask of all state properities that apply to
+ * This returns a bitmask of all state properties that apply to
* this circuit.
*/
static inline
@@ -2097,15 +2136,22 @@ circpad_shutdown_old_machines(origin_circuit_t *on_circ)
circuit_t *circ = TO_CIRCUIT(on_circ);
FOR_EACH_ACTIVE_CIRCUIT_MACHINE_BEGIN(i, circ) {
- if (!circpad_machine_conditions_met(on_circ,
+ /* We shut down a machine if neither the apply conditions
+ * nor the keep conditions match. If either set of conditions match,
+ * keep it around. */
+ if (!circpad_machine_conditions_apply(on_circ,
+ circ->padding_machine[i]) &&
+ !circpad_machine_conditions_keep(on_circ,
circ->padding_machine[i])) {
+ uint32_t machine_ctr = circ->padding_info[i]->machine_ctr;
// Clear machineinfo (frees timers)
circpad_circuit_machineinfo_free_idx(circ, i);
// Send padding negotiate stop
circpad_negotiate_padding(on_circ,
circ->padding_machine[i]->machine_num,
circ->padding_machine[i]->target_hopnum,
- CIRCPAD_COMMAND_STOP);
+ CIRCPAD_COMMAND_STOP,
+ machine_ctr);
}
} FOR_EACH_ACTIVE_CIRCUIT_MACHINE_END;
}
@@ -2154,7 +2200,7 @@ circpad_add_matching_machines(origin_circuit_t *on_circ,
* machines installed on a circuit. Make sure we only
* add this machine if its target machine index is free. */
if (machine->machine_index == i &&
- circpad_machine_conditions_met(on_circ, machine)) {
+ circpad_machine_conditions_apply(on_circ, machine)) {
// We can only replace this machine if the target hopnum
// is the same, otherwise we'll get invalid data
@@ -2172,7 +2218,8 @@ circpad_add_matching_machines(origin_circuit_t *on_circ,
circpad_setup_machine_on_circ(circ, machine);
if (circpad_negotiate_padding(on_circ, machine->machine_num,
machine->target_hopnum,
- CIRCPAD_COMMAND_START) < 0) {
+ CIRCPAD_COMMAND_START,
+ circ->padding_machine_ctr) < 0) {
log_info(LD_CIRC,
"Padding not negotiated. Cleaning machine from circuit %u",
CIRCUIT_IS_ORIGIN(circ) ?
@@ -2343,7 +2390,7 @@ circpad_deliver_unrecognized_cell_events(circuit_t *circ,
* Deliver circpad events for "recognized" relay cells.
*
* Recognized cells are destined for this hop, either client or middle.
- * Check if this is a padding cell or not, and send the appropiate
+ * Check if this is a padding cell or not, and send the appropriate
* received event.
*/
void
@@ -2463,6 +2510,17 @@ circpad_setup_machine_on_circ(circuit_t *on_circ,
machine->name, on_circ->purpose);
}
+ /* Padding machine ctr starts at 1, so we increment this ctr first.
+ * (machine ctr of 0 means "any machine").
+ *
+ * See https://bugs.tororject.org/30992. */
+ on_circ->padding_machine_ctr++;
+
+ /* uint32 wraparound check: 0 is special, just wrap to 1 */
+ if (on_circ->padding_machine_ctr == 0) {
+ on_circ->padding_machine_ctr = 1;
+ }
+
on_circ->padding_info[machine->machine_index] =
circpad_circuit_machineinfo_new(on_circ, machine->machine_index);
on_circ->padding_machine[machine->machine_index] = machine;
@@ -2555,9 +2613,9 @@ circpad_circ_client_machine_init(void)
= tor_malloc_zero(sizeof(circpad_machine_spec_t));
circ_client_machine->conditions.min_hops = 2;
- circ_client_machine->conditions.state_mask =
+ circ_client_machine->conditions.apply_state_mask =
CIRCPAD_CIRC_BUILDING|CIRCPAD_CIRC_OPENED|CIRCPAD_CIRC_HAS_RELAY_EARLY;
- circ_client_machine->conditions.purpose_mask = CIRCPAD_PURPOSE_ALL;
+ circ_client_machine->conditions.apply_purpose_mask = CIRCPAD_PURPOSE_ALL;
circ_client_machine->conditions.reduced_padding_ok = 1;
circ_client_machine->target_hopnum = 2;
@@ -2624,7 +2682,7 @@ circpad_circ_responder_machine_init(void)
serialize this into the consensus or the torrc */
/* We transition to the burst state on padding receive and on non-padding
- * recieve */
+ * receive */
circ_responder_machine->states[CIRCPAD_STATE_START].
next_state[CIRCPAD_EVENT_PADDING_RECV] = CIRCPAD_STATE_BURST;
circ_responder_machine->states[CIRCPAD_STATE_START].
@@ -2653,7 +2711,7 @@ circpad_circ_responder_machine_init(void)
/* During burst state we wait forever for padding to arrive.
We are waiting for a padding cell from the client to come in, so that we
- respond, and we immitate how extend looks like */
+ respond, and we imitate how extend looks like */
circ_responder_machine->states[CIRCPAD_STATE_BURST].histogram[0] = 0;
// Only infinity bin:
circ_responder_machine->states[CIRCPAD_STATE_BURST].histogram[1] = 1;
@@ -2816,7 +2874,8 @@ signed_error_t
circpad_negotiate_padding(origin_circuit_t *circ,
circpad_machine_num_t machine,
uint8_t target_hopnum,
- uint8_t command)
+ uint8_t command,
+ uint32_t machine_ctr)
{
circpad_negotiate_t type;
cell_t cell;
@@ -2838,14 +2897,16 @@ circpad_negotiate_padding(origin_circuit_t *circ,
circpad_negotiate_set_command(&type, command);
circpad_negotiate_set_version(&type, 0);
circpad_negotiate_set_machine_type(&type, machine);
+ circpad_negotiate_set_machine_ctr(&type, machine_ctr);
if ((len = circpad_negotiate_encode(cell.payload, CELL_PAYLOAD_SIZE,
&type)) < 0)
return -1;
log_fn(LOG_INFO,LD_CIRC,
- "Negotiating padding on circuit %u (%d), command %d",
- circ->global_identifier, TO_CIRCUIT(circ)->purpose, command);
+ "Negotiating padding on circuit %u (%d), command %d, for ctr %u",
+ circ->global_identifier, TO_CIRCUIT(circ)->purpose, command,
+ machine_ctr);
return circpad_send_command_to_hop(circ, target_hopnum,
RELAY_COMMAND_PADDING_NEGOTIATE,
@@ -2861,7 +2922,8 @@ bool
circpad_padding_negotiated(circuit_t *circ,
circpad_machine_num_t machine,
uint8_t command,
- uint8_t response)
+ uint8_t response,
+ uint32_t machine_ctr)
{
circpad_negotiated_t type;
cell_t cell;
@@ -2878,6 +2940,7 @@ circpad_padding_negotiated(circuit_t *circ,
circpad_negotiated_set_response(&type, response);
circpad_negotiated_set_version(&type, 0);
circpad_negotiated_set_machine_type(&type, machine);
+ circpad_negotiated_set_machine_ctr(&type, machine_ctr);
if ((len = circpad_negotiated_encode(cell.payload, CELL_PAYLOAD_SIZE,
&type)) < 0)
@@ -2923,19 +2986,33 @@ circpad_handle_padding_negotiate(circuit_t *circ, cell_t *cell)
if (negotiate->command == CIRCPAD_COMMAND_STOP) {
/* Free the machine corresponding to this machine type */
if (free_circ_machineinfos_with_machine_num(circ,
- negotiate->machine_type)) {
- log_info(LD_CIRC, "Received STOP command for machine %u",
- negotiate->machine_type);
+ negotiate->machine_type,
+ negotiate->machine_ctr)) {
+ log_info(LD_CIRC, "Received STOP command for machine %u, ctr %u",
+ negotiate->machine_type, negotiate->machine_ctr);
goto done;
}
- log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
- "Received circuit padding stop command for unknown machine.");
- goto err;
- } else if (negotiate->command == CIRCPAD_COMMAND_START) {
+ if (negotiate->machine_ctr <= circ->padding_machine_ctr) {
+ log_info(LD_CIRC, "Received STOP command for old machine %u, ctr %u",
+ negotiate->machine_type, negotiate->machine_ctr);
+ goto done;
+
+ } else {
+ log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
+ "Received circuit padding stop command for unknown machine.");
+ goto err;
+ }
+ } else if (negotiate->command == CIRCPAD_COMMAND_START) {
SMARTLIST_FOREACH_BEGIN(relay_padding_machines,
const circpad_machine_spec_t *, m) {
if (m->machine_num == negotiate->machine_type) {
circpad_setup_machine_on_circ(circ, m);
+ if (negotiate->machine_ctr &&
+ circ->padding_machine_ctr != negotiate->machine_ctr) {
+ log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
+ "Client and relay have different counts for padding machines: "
+ "%u vs %u", circ->padding_machine_ctr, negotiate->machine_ctr);
+ }
circpad_cell_event_nonpadding_received(circ);
goto done;
}
@@ -2948,7 +3025,8 @@ circpad_handle_padding_negotiate(circuit_t *circ, cell_t *cell)
done:
circpad_padding_negotiated(circ, negotiate->machine_type,
negotiate->command,
- (retval == 0) ? CIRCPAD_RESPONSE_OK : CIRCPAD_RESPONSE_ERR);
+ (retval == 0) ? CIRCPAD_RESPONSE_OK : CIRCPAD_RESPONSE_ERR,
+ negotiate->machine_ctr);
circpad_negotiate_free(negotiate);
return retval;
@@ -2999,17 +3077,22 @@ circpad_handle_padding_negotiated(circuit_t *circ, cell_t *cell,
* circpad_add_matching_matchines() added a new machine,
* there may be a padding_machine for a different machine num
* than this response. */
- free_circ_machineinfos_with_machine_num(circ, negotiated->machine_type);
+ free_circ_machineinfos_with_machine_num(circ, negotiated->machine_type,
+ negotiated->machine_ctr);
} else if (negotiated->command == CIRCPAD_COMMAND_START &&
negotiated->response == CIRCPAD_RESPONSE_ERR) {
- // This can happen due to consensus drift.. free the machines
+ // This can still happen due to consensus drift.. free the machines
// and be sad
- free_circ_machineinfos_with_machine_num(circ, negotiated->machine_type);
- TO_ORIGIN_CIRCUIT(circ)->padding_negotiation_failed = 1;
- log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
- "Middle node did not accept our padding request on circuit %u (%d)",
- TO_ORIGIN_CIRCUIT(circ)->global_identifier,
- circ->purpose);
+ if (free_circ_machineinfos_with_machine_num(circ, negotiated->machine_type,
+ negotiated->machine_ctr)) {
+ // Only fail if a machine was there and matched the error cell
+ TO_ORIGIN_CIRCUIT(circ)->padding_negotiation_failed = 1;
+ log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
+ "Middle node did not accept our padding request on circuit "
+ "%u (%d)",
+ TO_ORIGIN_CIRCUIT(circ)->global_identifier,
+ circ->purpose);
+ }
}
circpad_negotiated_free(negotiated);
diff --git a/src/core/or/circuitpadding.h b/src/core/or/circuitpadding.h
index 74b69a1c7a..3d2929cf74 100644
--- a/src/core/or/circuitpadding.h
+++ b/src/core/or/circuitpadding.h
@@ -173,11 +173,21 @@ typedef struct circpad_machine_conditions_t {
/** Only apply the machine *if* the circuit's state matches any of
* the bits set in this bitmask. */
- circpad_circuit_state_t state_mask;
+ circpad_circuit_state_t apply_state_mask;
/** Only apply a machine *if* the circuit's purpose matches one
* of the bits set in this bitmask */
- circpad_purpose_mask_t purpose_mask;
+ circpad_purpose_mask_t apply_purpose_mask;
+
+ /** Keep a machine if any of the circuits's state machine's match
+ * the bits set in this bitmask, but don't apply new machines if
+ * they match this mask. */
+ circpad_circuit_state_t keep_state_mask;
+
+ /** Keep a machine if any of the circuits's state machine's match
+ * the bits set in this bitmask, but don't apply new machines if
+ * they match this mask. */
+ circpad_purpose_mask_t keep_purpose_mask;
} circpad_machine_conditions_t;
@@ -565,6 +575,13 @@ typedef struct circpad_machine_runtime_t {
/** What state is this machine in? */
circpad_statenum_t current_state;
+ /** Machine counter, for shutdown sync.
+ *
+ * Set from circuit_t.padding_machine_ctr, which is incremented each
+ * padding machine instantiation.
+ */
+ uint32_t machine_ctr;
+
/**
* True if we have scheduled a timer for padding.
*
@@ -726,11 +743,13 @@ signed_error_t circpad_handle_padding_negotiated(struct circuit_t *circ,
signed_error_t circpad_negotiate_padding(struct origin_circuit_t *circ,
circpad_machine_num_t machine,
uint8_t target_hopnum,
- uint8_t command);
+ uint8_t command,
+ uint32_t machine_ctr);
bool circpad_padding_negotiated(struct circuit_t *circ,
circpad_machine_num_t machine,
uint8_t command,
- uint8_t response);
+ uint8_t response,
+ uint32_t machine_ctr);
circpad_purpose_mask_t circpad_circ_purpose_to_mask(uint8_t circ_purpose);
diff --git a/src/core/or/circuitpadding_machines.c b/src/core/or/circuitpadding_machines.c
index 98767f9e8f..f29a9be455 100644
--- a/src/core/or/circuitpadding_machines.c
+++ b/src/core/or/circuitpadding_machines.c
@@ -25,7 +25,7 @@
* Client-side introduction circuit hiding machine:
*
* This machine hides client-side introduction circuits by making their
- * circuit consruction sequence look like normal general circuits that
+ * circuit construction sequence look like normal general circuits that
* download directory information. Furthermore, the circuits are kept open
* until all the padding has been sent, since intro circuits are usually
* very short lived and this act as a distinguisher. For more info see
@@ -67,7 +67,7 @@ circpad_machine_client_hide_intro_circuits(smartlist_t *machines_sl)
client_machine->name = "client_ip_circ";
- client_machine->conditions.state_mask = CIRCPAD_CIRC_OPENED;
+ client_machine->conditions.apply_state_mask = CIRCPAD_CIRC_OPENED;
client_machine->target_hopnum = 2;
/* This is a client machine */
@@ -102,9 +102,18 @@ circpad_machine_client_hide_intro_circuits(smartlist_t *machines_sl)
* INTRO_MACHINE_MAXIMUM_PADDING cells, to match the "...(inbound data cells
* continue)" portion of the trace (aka the rest of an HTTPS response body).
*/
- client_machine->conditions.purpose_mask =
- circpad_circ_purpose_to_mask(CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT)|
- circpad_circ_purpose_to_mask(CIRCUIT_PURPOSE_C_INTRODUCE_ACKED)|
+
+ /* Start the machine on fresh intro circs. */
+ client_machine->conditions.apply_purpose_mask =
+ circpad_circ_purpose_to_mask(CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT);
+
+ /* If the client purpose changes back to CIRCUIT_PURPOSE_C_INTRODUCING,
+ * or transitions to CIRCUIT_PURPOSE_C_INTRODUCE_ACKED, keep the machine
+ * alive, but do not launch new machines for these purposes. Also
+ * keep the machine around if it is in the CIRCUIT_PADDING purpose
+ * (but do not try to take over other machines in that purpose). */
+ client_machine->conditions.keep_purpose_mask =
+ circpad_circ_purpose_to_mask(CIRCUIT_PURPOSE_C_INTRODUCE_ACKED) |
circpad_circ_purpose_to_mask(CIRCUIT_PURPOSE_C_CIRCUIT_PADDING);
/* Keep the circuit alive even after the introduction has been finished,
@@ -152,7 +161,7 @@ circpad_machine_relay_hide_intro_circuits(smartlist_t *machines_sl)
relay_machine->name = "relay_ip_circ";
- relay_machine->conditions.state_mask = CIRCPAD_CIRC_OPENED;
+ relay_machine->conditions.apply_state_mask = CIRCPAD_CIRC_OPENED;
/* This is a relay-side machine */
relay_machine->is_origin_side = 0;
@@ -263,7 +272,7 @@ circpad_machine_client_hide_rend_circuits(smartlist_t *machines_sl)
client_machine->name = "client_rp_circ";
/* Only pad after the circuit has been built and pad to the middle */
- client_machine->conditions.state_mask = CIRCPAD_CIRC_OPENED;
+ client_machine->conditions.apply_state_mask = CIRCPAD_CIRC_OPENED;
client_machine->target_hopnum = 2;
/* This is a client machine */
@@ -299,7 +308,7 @@ circpad_machine_client_hide_rend_circuits(smartlist_t *machines_sl)
*
* Hence this way we make rendezvous circuits look like general circuits up
* till the end of the circuit setup. */
- client_machine->conditions.purpose_mask =
+ client_machine->conditions.apply_purpose_mask =
circpad_circ_purpose_to_mask(CIRCUIT_PURPOSE_C_REND_JOINED)|
circpad_circ_purpose_to_mask(CIRCUIT_PURPOSE_C_REND_READY)|
circpad_circ_purpose_to_mask(CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED);
@@ -383,7 +392,7 @@ circpad_machine_relay_hide_rend_circuits(smartlist_t *machines_sl)
/* Only pad after the circuit has been built and pad to the middle */
relay_machine->conditions.min_hops = 2;
- relay_machine->conditions.state_mask = CIRCPAD_CIRC_OPENED;
+ relay_machine->conditions.apply_state_mask = CIRCPAD_CIRC_OPENED;
/* This is a relay-side machine */
relay_machine->is_origin_side = 0;
diff --git a/src/core/or/circuitstats.c b/src/core/or/circuitstats.c
index 5875627b93..51bd9e1208 100644
--- a/src/core/or/circuitstats.c
+++ b/src/core/or/circuitstats.c
@@ -53,9 +53,6 @@
#undef log
#include <math.h>
-static void cbt_control_event_buildtimeout_set(
- const circuit_build_times_t *cbt,
- buildtimeout_set_event_t type);
static void circuit_build_times_scale_circ_counts(circuit_build_times_t *cbt);
#define CBT_BIN_TO_MS(bin) ((bin)*CBT_BIN_WIDTH + (CBT_BIN_WIDTH/2))
@@ -402,7 +399,7 @@ circuit_build_times_initial_timeout(void)
* and learn a new timeout.
*/
static int32_t
-circuit_build_times_recent_circuit_count(networkstatus_t *ns)
+circuit_build_times_recent_circuit_count(const networkstatus_t *ns)
{
int32_t num;
num = networkstatus_get_param(ns, "cbtrecentcount",
@@ -428,7 +425,7 @@ circuit_build_times_recent_circuit_count(networkstatus_t *ns)
*/
void
circuit_build_times_new_consensus_params(circuit_build_times_t *cbt,
- networkstatus_t *ns)
+ const networkstatus_t *ns)
{
int32_t num;
@@ -545,7 +542,7 @@ circuit_build_times_get_initial_timeout(void)
* Leave estimated parameters, timeout and network liveness intact
* for future use.
*/
-STATIC void
+void
circuit_build_times_reset(circuit_build_times_t *cbt)
{
memset(cbt->circuit_build_times, 0, sizeof(cbt->circuit_build_times));
@@ -1893,61 +1890,3 @@ circuit_build_times_update_last_circ(circuit_build_times_t *cbt)
{
cbt->last_circ_at = approx_time();
}
-
-static void
-cbt_control_event_buildtimeout_set(const circuit_build_times_t *cbt,
- buildtimeout_set_event_t type)
-{
- char *args = NULL;
- double qnt;
- double timeout_rate = 0.0;
- double close_rate = 0.0;
-
- switch (type) {
- case BUILDTIMEOUT_SET_EVENT_RESET:
- case BUILDTIMEOUT_SET_EVENT_SUSPENDED:
- case BUILDTIMEOUT_SET_EVENT_DISCARD:
- qnt = 1.0;
- break;
- case BUILDTIMEOUT_SET_EVENT_COMPUTED:
- case BUILDTIMEOUT_SET_EVENT_RESUME:
- default:
- qnt = circuit_build_times_quantile_cutoff();
- break;
- }
-
- /* The timeout rate is the ratio of the timeout count over
- * the total number of circuits attempted. The total number of
- * circuits is (timeouts+succeeded), since every circuit
- * either succeeds, or times out. "Closed" circuits are
- * MEASURE_TIMEOUT circuits whose measurement period expired.
- * All MEASURE_TIMEOUT circuits are counted in the timeouts stat
- * before transitioning to MEASURE_TIMEOUT (in
- * circuit_build_times_mark_circ_as_measurement_only()).
- * MEASURE_TIMEOUT circuits that succeed are *not* counted as
- * "succeeded". See circuit_build_times_handle_completed_hop().
- *
- * We cast the denominator
- * to promote it to double before the addition, to avoid int32
- * overflow. */
- const double total_circuits =
- ((double)cbt->num_circ_timeouts) + cbt->num_circ_succeeded;
- if (total_circuits >= 1.0) {
- timeout_rate = cbt->num_circ_timeouts / total_circuits;
- close_rate = cbt->num_circ_closed / total_circuits;
- }
-
- tor_asprintf(&args, "TOTAL_TIMES=%lu "
- "TIMEOUT_MS=%lu XM=%lu ALPHA=%f CUTOFF_QUANTILE=%f "
- "TIMEOUT_RATE=%f CLOSE_MS=%lu CLOSE_RATE=%f",
- (unsigned long)cbt->total_build_times,
- (unsigned long)cbt->timeout_ms,
- (unsigned long)cbt->Xm, cbt->alpha, qnt,
- timeout_rate,
- (unsigned long)cbt->close_ms,
- close_rate);
-
- control_event_buildtimeout_set(type, args);
-
- tor_free(args);
-}
diff --git a/src/core/or/circuitstats.h b/src/core/or/circuitstats.h
index 52c9100f53..930e0a9ba3 100644
--- a/src/core/or/circuitstats.h
+++ b/src/core/or/circuitstats.h
@@ -43,12 +43,13 @@ int circuit_build_times_needs_circuits_now(const circuit_build_times_t *cbt);
void circuit_build_times_init(circuit_build_times_t *cbt);
void circuit_build_times_free_timeouts(circuit_build_times_t *cbt);
void circuit_build_times_new_consensus_params(circuit_build_times_t *cbt,
- networkstatus_t *ns);
+ const networkstatus_t *ns);
double circuit_build_times_timeout_rate(const circuit_build_times_t *cbt);
double circuit_build_times_close_rate(const circuit_build_times_t *cbt);
void circuit_build_times_update_last_circ(circuit_build_times_t *cbt);
void circuit_build_times_mark_circ_as_measurement_only(origin_circuit_t *circ);
+void circuit_build_times_reset(circuit_build_times_t *cbt);
/** Total size of the circuit timeout history to accumulate.
* 1000 is approx 2.5 days worth of continual-use circuits. */
@@ -137,7 +138,6 @@ int32_t circuit_build_times_initial_timeout(void);
STATIC double circuit_build_times_calculate_timeout(circuit_build_times_t *cbt,
double quantile);
STATIC int circuit_build_times_update_alpha(circuit_build_times_t *cbt);
-STATIC void circuit_build_times_reset(circuit_build_times_t *cbt);
/* Network liveness functions */
STATIC int circuit_build_times_network_check_changed(
@@ -158,7 +158,6 @@ void circuit_build_times_network_is_live(circuit_build_times_t *cbt);
int circuit_build_times_network_check_live(const circuit_build_times_t *cbt);
void circuit_build_times_network_circ_success(circuit_build_times_t *cbt);
-#ifdef CIRCUITSTATS_PRIVATE
/** Information about the state of our local network connection */
typedef struct {
/** The timestamp we last completed a TLS handshake or received a cell */
@@ -208,6 +207,5 @@ struct circuit_build_times_t {
uint32_t num_circ_closed;
};
-#endif /* defined(CIRCUITSTATS_PRIVATE) */
#endif /* !defined(TOR_CIRCUITSTATS_H) */
diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c
index e2c4df25d0..0f3fc29361 100644
--- a/src/core/or/circuituse.c
+++ b/src/core/or/circuituse.c
@@ -37,7 +37,9 @@
#include "core/or/circuituse.h"
#include "core/or/circuitpadding.h"
#include "core/or/connection_edge.h"
+#include "core/or/extendinfo.h"
#include "core/or/policies.h"
+#include "core/or/trace_probes_circuit.h"
#include "feature/client/addressmap.h"
#include "feature/client/bridges.h"
#include "feature/client/circpathbias.h"
@@ -62,6 +64,7 @@
#include "feature/stats/predict_ports.h"
#include "lib/math/fp.h"
#include "lib/time/tvdiff.h"
+#include "lib/trace/events.h"
#include "core/or/cpath_build_state_st.h"
#include "feature/dircommon/dir_connection_st.h"
@@ -202,8 +205,8 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ,
const int family = tor_addr_parse(&addr,
conn->socks_request->address);
if (family < 0 ||
- !tor_addr_eq(&build_state->chosen_exit->addr, &addr) ||
- build_state->chosen_exit->port != conn->socks_request->port)
+ !extend_info_has_orport(build_state->chosen_exit, &addr,
+ conn->socks_request->port))
return 0;
}
}
@@ -816,7 +819,7 @@ circuit_expire_building(void)
log_info(LD_CIRC,
"Abandoning circ %u %s:%u (state %d,%d:%s, purpose %d, "
"len %d)", TO_ORIGIN_CIRCUIT(victim)->global_identifier,
- channel_get_canonical_remote_descr(victim->n_chan),
+ channel_describe_peer(victim->n_chan),
(unsigned)victim->n_circ_id,
TO_ORIGIN_CIRCUIT(victim)->has_opened,
victim->state, circuit_state_to_string(victim->state),
@@ -837,6 +840,7 @@ circuit_expire_building(void)
-1);
circuit_log_path(LOG_INFO,LD_CIRC,TO_ORIGIN_CIRCUIT(victim));
+ tor_trace(TR_SUBSYS(circuit), TR_EV(timeout), TO_ORIGIN_CIRCUIT(victim));
if (victim->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT)
circuit_mark_for_close(victim, END_CIRC_REASON_MEASUREMENT_EXPIRED);
else
@@ -1500,8 +1504,11 @@ circuit_expire_old_circuits_clientside(void)
circ->purpose);
/* Don't do this magic for testing circuits. Their death is governed
* by circuit_expire_building */
- if (circ->purpose != CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+ if (circ->purpose != CIRCUIT_PURPOSE_PATH_BIAS_TESTING) {
+ tor_trace(TR_SUBSYS(circuit), TR_EV(idle_timeout),
+ TO_ORIGIN_CIRCUIT(circ));
circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
+ }
} else if (!circ->timestamp_dirty && circ->state == CIRCUIT_STATE_OPEN) {
if (timercmp(&circ->timestamp_began, &cutoff, OP_LT)) {
if (circ->purpose == CIRCUIT_PURPOSE_C_GENERAL ||
@@ -1520,6 +1527,8 @@ circuit_expire_old_circuits_clientside(void)
" that has been unused for %ld msec.",
TO_ORIGIN_CIRCUIT(circ)->global_identifier,
tv_mdiff(&circ->timestamp_began, &now));
+ tor_trace(TR_SUBSYS(circuit), TR_EV(idle_timeout),
+ TO_ORIGIN_CIRCUIT(circ));
circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
} else if (!TO_ORIGIN_CIRCUIT(circ)->is_ancient) {
/* Server-side rend joined circuits can end up really old, because
@@ -1642,11 +1651,12 @@ static void
circuit_testing_opened(origin_circuit_t *circ)
{
if (have_performed_bandwidth_test ||
- !check_whether_orport_reachable(get_options())) {
+ !router_orport_seems_reachable(get_options(), AF_INET)) {
/* either we've already done everything we want with testing circuits,
- * or this testing circuit became open due to a fluke, e.g. we picked
- * a last hop where we already had the connection open due to an
- * outgoing local circuit. */
+ * OR this IPv4 testing circuit became open due to a fluke, e.g. we picked
+ * a last hop where we already had the connection open due to a
+ * outgoing local circuit, OR this is an IPv6 self-test circuit, not
+ * a bandwidth test circuit. */
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
} else if (circuit_enough_testing_circs()) {
router_perform_bandwidth_test(NUM_PARALLEL_TESTING_CIRCS, time(NULL));
@@ -1660,7 +1670,8 @@ static void
circuit_testing_failed(origin_circuit_t *circ, int at_last_hop)
{
const or_options_t *options = get_options();
- if (server_mode(options) && check_whether_orport_reachable(options))
+ if (server_mode(options) &&
+ router_all_orports_seem_reachable(options))
return;
log_info(LD_GENERAL,
@@ -1681,6 +1692,7 @@ circuit_testing_failed(origin_circuit_t *circ, int at_last_hop)
void
circuit_has_opened(origin_circuit_t *circ)
{
+ tor_trace(TR_SUBSYS(circuit), TR_EV(opened), circ);
circuit_event_status(circ, CIRC_EVENT_BUILT, 0);
/* Remember that this circuit has finished building. Now if we start
@@ -1846,7 +1858,7 @@ circuit_build_failed(origin_circuit_t *circ)
"from the first hop (%s). I'm going to try to rotate to a "
"better connection.",
TO_CIRCUIT(circ)->n_circ_id, circ->global_identifier,
- channel_get_canonical_remote_descr(n_chan));
+ channel_describe_peer(n_chan));
n_chan->is_bad_for_new_circs = 1;
} else {
log_info(LD_OR,
@@ -1979,7 +1991,7 @@ circuit_purpose_is_hidden_service(uint8_t purpose)
return 0;
}
-/** Retrun true iff the given circuit is an HS client circuit. */
+/** Return true iff the given circuit is an HS client circuit. */
bool
circuit_purpose_is_hs_client(const uint8_t purpose)
{
@@ -1987,7 +1999,7 @@ circuit_purpose_is_hs_client(const uint8_t purpose)
purpose <= CIRCUIT_PURPOSE_C_HS_MAX_);
}
-/** Retrun true iff the given circuit is an HS service circuit. */
+/** Return true iff the given circuit is an HS service circuit. */
bool
circuit_purpose_is_hs_service(const uint8_t purpose)
{
@@ -1995,14 +2007,14 @@ circuit_purpose_is_hs_service(const uint8_t purpose)
purpose <= CIRCUIT_PURPOSE_S_HS_MAX_);
}
-/** Retrun true iff the given circuit is an HS Vanguards circuit. */
+/** Return 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. */
+/** Return true iff the given circuit is an HS v2 circuit. */
bool
circuit_is_hs_v2(const circuit_t *circ)
{
@@ -2010,7 +2022,7 @@ circuit_is_hs_v2(const circuit_t *circ)
(CONST_TO_ORIGIN_CIRCUIT(circ)->rend_data != NULL));
}
-/** Retrun true iff the given circuit is an HS v3 circuit. */
+/** Return true iff the given circuit is an HS v3 circuit. */
bool
circuit_is_hs_v3(const circuit_t *circ)
{
@@ -2092,11 +2104,18 @@ circuit_should_cannibalize_to_build(uint8_t purpose_to_build,
}
/** Launch a new circuit with purpose <b>purpose</b> and exit node
- * <b>extend_info</b> (or NULL to select a random exit node). If flags
- * contains CIRCLAUNCH_NEED_UPTIME, choose among routers with high uptime. If
- * CIRCLAUNCH_NEED_CAPACITY is set, choose among routers with high bandwidth.
- * If CIRCLAUNCH_IS_INTERNAL is true, the last hop need not be an exit node.
- * If CIRCLAUNCH_ONEHOP_TUNNEL is set, the circuit will have only one hop.
+ * <b>extend_info</b> (or NULL to select a random exit node).
+ *
+ * If flags contains:
+ * - CIRCLAUNCH_ONEHOP_TUNNEL: the circuit will have only one hop;
+ * - CIRCLAUNCH_NEED_UPTIME: choose routers with high uptime;
+ * - CIRCLAUNCH_NEED_CAPACITY: choose routers with high bandwidth;
+ * - CIRCLAUNCH_IS_IPV6_SELFTEST: the second-last hop must support IPv6
+ * extends;
+ * - CIRCLAUNCH_IS_INTERNAL: the last hop need not be an exit node;
+ * - CIRCLAUNCH_IS_V3_RP: the last hop must support v3 onion service
+ * rendezvous.
+ *
* Return the newly allocated circuit on success, or NULL on failure. */
origin_circuit_t *
circuit_launch_by_extend_info(uint8_t purpose,
@@ -2195,6 +2214,8 @@ circuit_launch_by_extend_info(uint8_t purpose,
tor_fragile_assert();
return NULL;
}
+
+ tor_trace(TR_SUBSYS(circuit), TR_EV(cannibalized), circ);
return circ;
}
}
@@ -2611,22 +2632,6 @@ cpath_is_on_circuit(origin_circuit_t *circ, crypt_path_t *crypt_path)
return 0;
}
-/** Return true iff client-side optimistic data is supported. */
-static int
-optimistic_data_enabled(void)
-{
- const or_options_t *options = get_options();
- if (options->OptimisticData < 0) {
- /* Note: this default was 0 before #18815 was merged. We can't take the
- * parameter out of the consensus until versions before that are all
- * obsolete. */
- const int32_t enabled =
- networkstatus_get_param(NULL, "UseOptimisticData", /*default*/ 1, 0, 1);
- return (int)enabled;
- }
- return options->OptimisticData;
-}
-
/** Attach the AP stream <b>apconn</b> to circ's linked list of
* p_streams. Also set apconn's cpath_layer to <b>cpath</b>, or to the last
* hop in circ's cpath if <b>cpath</b> is NULL.
@@ -2679,17 +2684,17 @@ link_apconn_to_circ(entry_connection_t *apconn, origin_circuit_t *circ,
exitnode = node_get_by_id(cpath->extend_info->identity_digest);
/* See if we can use optimistic data on this circuit */
- if (optimistic_data_enabled() &&
- (circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL ||
- circ->base_.purpose == CIRCUIT_PURPOSE_C_HSDIR_GET ||
- circ->base_.purpose == CIRCUIT_PURPOSE_S_HSDIR_POST ||
- circ->base_.purpose == CIRCUIT_PURPOSE_C_REND_JOINED))
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL ||
+ circ->base_.purpose == CIRCUIT_PURPOSE_C_HSDIR_GET ||
+ circ->base_.purpose == CIRCUIT_PURPOSE_S_HSDIR_POST ||
+ circ->base_.purpose == CIRCUIT_PURPOSE_C_REND_JOINED)
apconn->may_use_optimistic_data = 1;
else
apconn->may_use_optimistic_data = 0;
log_info(LD_APP, "Looks like completed circuit to %s %s allow "
"optimistic data for connection to %s",
- circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL ?
+ (circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL ||
+ circ->base_.purpose == CIRCUIT_PURPOSE_CONTROLLER) ?
/* node_describe() does the right thing if exitnode is NULL */
safe_str_client(node_describe(exitnode)) :
"hidden service",
@@ -3126,6 +3131,8 @@ circuit_change_purpose(circuit_t *circ, uint8_t new_purpose)
old_purpose = circ->purpose;
circ->purpose = new_purpose;
+ tor_trace(TR_SUBSYS(circuit), TR_EV(change_purpose), circ, old_purpose,
+ new_purpose);
if (CIRCUIT_IS_ORIGIN(circ)) {
control_event_circuit_purpose_changed(TO_ORIGIN_CIRCUIT(circ),
diff --git a/src/core/or/circuituse.h b/src/core/or/circuituse.h
index 95d36d6474..028fe4aa48 100644
--- a/src/core/or/circuituse.h
+++ b/src/core/or/circuituse.h
@@ -36,17 +36,23 @@ void circuit_try_attaching_streams(origin_circuit_t *circ);
void circuit_build_failed(origin_circuit_t *circ);
/** Flag to set when a circuit should have only a single hop. */
-#define CIRCLAUNCH_ONEHOP_TUNNEL (1<<0)
+#define CIRCLAUNCH_ONEHOP_TUNNEL (1<<0)
/** Flag to set when a circuit needs to be built of high-uptime nodes */
-#define CIRCLAUNCH_NEED_UPTIME (1<<1)
+#define CIRCLAUNCH_NEED_UPTIME (1<<1)
/** Flag to set when a circuit needs to be built of high-capacity nodes */
-#define CIRCLAUNCH_NEED_CAPACITY (1<<2)
+#define CIRCLAUNCH_NEED_CAPACITY (1<<2)
/** Flag to set when the last hop of a circuit doesn't need to be an
* exit node. */
-#define CIRCLAUNCH_IS_INTERNAL (1<<3)
+#define CIRCLAUNCH_IS_INTERNAL (1<<3)
/** Flag to set when we are trying to launch a v3 rendezvous circuit. We need
* to apply some additional filters on the node picked. */
-#define CIRCLAUNCH_IS_V3_RP (1<<4)
+#define CIRCLAUNCH_IS_V3_RP (1<<4)
+/** Flag to set when we are trying to launch a self-testing circuit to our
+ * IPv6 ORPort. We need to apply some additional filters on the second-last
+ * node in the circuit. (We are both the client and the last node in the
+ * circuit.) */
+#define CIRCLAUNCH_IS_IPV6_SELFTEST (1<<5)
+
origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
extend_info_t *info,
int flags);
diff --git a/src/core/or/command.c b/src/core/or/command.c
index 8a1d2066cc..9226309ff7 100644
--- a/src/core/or/command.c
+++ b/src/core/or/command.c
@@ -252,7 +252,7 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Received a create cell (type %d) from %s with zero circID; "
" ignoring.", (int)cell->command,
- channel_get_actual_remote_descr(chan));
+ channel_describe_peer(chan));
return;
}
@@ -295,7 +295,7 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
"Received create cell (type %d) from %s, but we're connected "
"to it as a client. "
"Sending back a destroy.",
- (int)cell->command, channel_get_canonical_remote_descr(chan));
+ (int)cell->command, channel_describe_peer(chan));
channel_send_destroy(cell->circ_id, chan,
END_CIRC_REASON_TORPROTOCOL);
return;
@@ -475,7 +475,7 @@ command_process_relay_cell(cell_t *cell, channel_t *chan)
log_debug(LD_OR,
"unknown circuit %u on connection from %s. Dropping.",
(unsigned)cell->circ_id,
- channel_get_canonical_remote_descr(chan));
+ channel_describe_peer(chan));
return;
}
@@ -536,7 +536,7 @@ command_process_relay_cell(cell_t *cell, channel_t *chan)
control_event_circ_bandwidth_used_for_circ(TO_ORIGIN_CIRCUIT(circ));
} else if (circ->n_chan) {
log_warn(LD_OR, " upstream=%s",
- channel_get_actual_remote_descr(circ->n_chan));
+ channel_describe_peer(circ->n_chan));
}
circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
return;
@@ -547,7 +547,7 @@ command_process_relay_cell(cell_t *cell, channel_t *chan)
"Received too many RELAY_EARLY cells on circ %u from %s."
" Closing circuit.",
(unsigned)cell->circ_id,
- safe_str(channel_get_canonical_remote_descr(chan)));
+ safe_str(channel_describe_peer(chan)));
circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
return;
}
@@ -618,7 +618,7 @@ command_process_destroy_cell(cell_t *cell, channel_t *chan)
if (!circ) {
log_info(LD_OR,"unknown circuit %u on connection from %s. Dropping.",
(unsigned)cell->circ_id,
- channel_get_canonical_remote_descr(chan));
+ channel_describe_peer(chan));
return;
}
log_debug(LD_OR,"Received for circID %u.",(unsigned)cell->circ_id);
diff --git a/src/core/or/connection_edge.c b/src/core/or/connection_edge.c
index 1394a41c73..7f260ba185 100644
--- a/src/core/or/connection_edge.c
+++ b/src/core/or/connection_edge.c
@@ -19,7 +19,7 @@
* TCP application socket that has arrived via (e.g.) a SOCKS request, or an
* exit connection.
*
- * Not every instance of edge_connection_t truly represents an edge connction,
+ * Not every instance of edge_connection_t truly represents an edge connection,
* however. (Sorry!) We also create edge_connection_t objects for streams that
* we will not be handling with TCP. The types of these streams are:
* <ul>
@@ -70,6 +70,7 @@
#include "core/or/circuitpadding.h"
#include "core/or/connection_edge.h"
#include "core/or/connection_or.h"
+#include "core/or/extendinfo.h"
#include "core/or/policies.h"
#include "core/or/reasons.h"
#include "core/or/relay.h"
@@ -165,8 +166,12 @@ static int connection_exit_connect_dir(edge_connection_t *exitconn);
static int consider_plaintext_ports(entry_connection_t *conn, uint16_t port);
static int connection_ap_supports_optimistic_data(const entry_connection_t *);
-/** Convert a connection_t* to an edge_connection_t*; assert if the cast is
- * invalid. */
+/**
+ * Cast a `connection_t *` to an `edge_connection_t *`.
+ *
+ * Exit with an assertion failure if the input is not an
+ * `edge_connection_t`.
+ **/
edge_connection_t *
TO_EDGE_CONN(connection_t *c)
{
@@ -175,6 +180,24 @@ TO_EDGE_CONN(connection_t *c)
return DOWNCAST(edge_connection_t, c);
}
+/**
+ * Cast a `const connection_t *` to a `const edge_connection_t *`.
+ *
+ * Exit with an assertion failure if the input is not an
+ * `edge_connection_t`.
+ **/
+const edge_connection_t *
+CONST_TO_EDGE_CONN(const connection_t *c)
+{
+ return TO_EDGE_CONN((connection_t *)c);
+}
+
+/**
+ * Cast a `connection_t *` to an `entry_connection_t *`.
+ *
+ * Exit with an assertion failure if the input is not an
+ * `entry_connection_t`.
+ **/
entry_connection_t *
TO_ENTRY_CONN(connection_t *c)
{
@@ -182,6 +205,24 @@ TO_ENTRY_CONN(connection_t *c)
return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, edge_.base_);
}
+/**
+ * Cast a `const connection_t *` to a `const entry_connection_t *`.
+ *
+ * Exit with an assertion failure if the input is not an
+ * `entry_connection_t`.
+ **/
+const entry_connection_t *
+CONST_TO_ENTRY_CONN(const connection_t *c)
+{
+ return TO_ENTRY_CONN((connection_t*) c);
+}
+
+/**
+ * Cast an `edge_connection_t *` to an `entry_connection_t *`.
+ *
+ * Exit with an assertion failure if the input is not an
+ * `entry_connection_t`.
+ **/
entry_connection_t *
EDGE_TO_ENTRY_CONN(edge_connection_t *c)
{
@@ -189,6 +230,18 @@ EDGE_TO_ENTRY_CONN(edge_connection_t *c)
return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, edge_);
}
+/**
+ * Cast a `const edge_connection_t *` to a `const entry_connection_t *`.
+ *
+ * Exit with an assertion failure if the input is not an
+ * `entry_connection_t`.
+ **/
+const entry_connection_t *
+CONST_EDGE_TO_ENTRY_CONN(const edge_connection_t *c)
+{
+ return EDGE_TO_ENTRY_CONN((edge_connection_t*)c);
+}
+
/** An AP stream has failed/finished. If it hasn't already sent back
* a socks reply, send one now (based on endreason). Also set
* has_sent_end to 1, and mark the conn.
@@ -423,9 +476,7 @@ warn_if_hs_unreachable(const edge_connection_t *conn, uint8_t reason)
char *m;
if ((m = rate_limit_log(&warn_limit, approx_time()))) {
log_warn(LD_EDGE, "Onion service connection to %s failed (%s)",
- (conn->base_.socket_family == AF_UNIX) ?
- safe_str(conn->base_.address) :
- safe_str(fmt_addrport(&conn->base_.addr, conn->base_.port)),
+ connection_describe_peer(TO_CONN(conn)),
stream_end_reason_to_string(reason));
tor_free(m);
}
@@ -527,8 +578,8 @@ connection_edge_end(edge_connection_t *conn, uint8_t reason)
/**
* Helper function for bsearch.
*
- * As per smartlist_bsearch, return < 0 if key preceeds member,
- * > 0 if member preceeds key, and 0 if they are equal.
+ * As per smartlist_bsearch, return < 0 if key precedes member,
+ * > 0 if member precedes key, and 0 if they are equal.
*
* This is equivalent to subtraction of the values of key - member
* (why does no one ever say that explicitly?).
@@ -921,9 +972,8 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn)
conn = TO_CONN(edge_conn);
tor_assert(conn->state == EXIT_CONN_STATE_CONNECTING);
- log_info(LD_EXIT,"Exit connection to %s:%u (%s) established.",
- escaped_safe_str(conn->address), conn->port,
- safe_str(fmt_and_decorate_addr(&conn->addr)));
+ log_info(LD_EXIT,"%s established.",
+ connection_describe(conn));
rep_hist_note_exit_stream_opened(conn->port);
@@ -1155,6 +1205,7 @@ connection_ap_expire_beginning(void)
}
if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL &&
+ circ->purpose != CIRCUIT_PURPOSE_CONTROLLER &&
circ->purpose != CIRCUIT_PURPOSE_C_HSDIR_GET &&
circ->purpose != CIRCUIT_PURPOSE_S_HSDIR_POST &&
circ->purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT &&
@@ -1444,8 +1495,8 @@ connection_ap_fail_onehop(const char *failed_digest,
continue;
}
if (tor_addr_parse(&addr, entry_conn->socks_request->address)<0 ||
- !tor_addr_eq(&build_state->chosen_exit->addr, &addr) ||
- build_state->chosen_exit->port != entry_conn->socks_request->port)
+ !extend_info_has_orport(build_state->chosen_exit, &addr,
+ entry_conn->socks_request->port))
continue;
}
log_info(LD_APP, "Closing one-hop stream to '%s/%s' because the OR conn "
@@ -1503,6 +1554,16 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info)
} SMARTLIST_FOREACH_END(conn);
}
+/** Set the connection state to CONTROLLER_WAIT and send an control port event.
+ */
+void
+connection_entry_set_controller_wait(entry_connection_t *conn)
+{
+ CONNECTION_AP_EXPECT_NONPENDING(conn);
+ ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CONTROLLER_WAIT;
+ control_event_stream_status(conn, STREAM_EVENT_CONTROLLER_WAIT, 0);
+}
+
/** The AP connection <b>conn</b> has just failed while attaching or
* sending a BEGIN or resolving on <b>circ</b>, but another circuit
* might work. Detach the circuit, and either reattach it, launch a
@@ -1534,8 +1595,7 @@ connection_ap_detach_retriable(entry_connection_t *conn,
circuit_detach_stream(TO_CIRCUIT(circ),ENTRY_TO_EDGE_CONN(conn));
connection_ap_mark_as_pending_circuit(conn);
} else {
- CONNECTION_AP_EXPECT_NONPENDING(conn);
- ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CONTROLLER_WAIT;
+ connection_entry_set_controller_wait(conn);
circuit_detach_stream(TO_CIRCUIT(circ),ENTRY_TO_EDGE_CONN(conn));
}
return 0;
@@ -1688,8 +1748,7 @@ connection_ap_rewrite_and_attach_if_allowed,(entry_connection_t *conn,
const or_options_t *options = get_options();
if (options->LeaveStreamsUnattached) {
- CONNECTION_AP_EXPECT_NONPENDING(conn);
- ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CONTROLLER_WAIT;
+ connection_entry_set_controller_wait(conn);
return 0;
}
return connection_ap_handshake_rewrite_and_attach(conn, circ, cpath);
@@ -2007,7 +2066,7 @@ connection_ap_handle_onion(entry_connection_t *conn,
log_info(LD_GENERAL, "Found %s descriptor in cache for %s. %s.",
(descriptor_is_usable) ? "usable" : "unusable",
safe_str_client(onion_address),
- (descriptor_is_usable) ? "Not fetching." : "Refecting.");
+ (descriptor_is_usable) ? "Not fetching." : "Refetching.");
} else {
rend_cache_lookup_result = -ENOENT;
}
@@ -2523,6 +2582,16 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
tor_assert(addresstype == ONION_V2_HOSTNAME ||
addresstype == ONION_V3_HOSTNAME);
tor_assert(!automap);
+
+ if (addresstype == ONION_V2_HOSTNAME) {
+ log_warn(LD_PROTOCOL,
+ "Warning! You've just connected to a v2 onion address. These "
+ "addresses are deprecated for security reasons, and are no "
+ "longer supported in Tor. Please encourage the site operator "
+ "to upgrade. For more information see "
+ "https://blog.torproject.org/v2-deprecation-timeline");
+ }
+
return connection_ap_handle_onion(conn, socks, circ, addresstype);
}
@@ -2596,8 +2665,8 @@ destination_from_socket(entry_connection_t *conn, socks_request_t *req)
break;
#endif /* defined(TRANS_NETFILTER_IPV6) */
default:
- log_warn(LD_BUG,
- "Received transparent data from an unsuported socket family %d",
+ log_warn(LD_BUG, "Received transparent data from an unsupported "
+ "socket family %d",
ENTRY_TO_CONN(conn)->socket_family);
return -1;
}
@@ -3208,7 +3277,8 @@ connection_ap_handshake_send_begin,(entry_connection_t *ap_conn))
edge_conn->begincell_flags = connection_ap_get_begincell_flags(ap_conn);
tor_snprintf(payload,RELAY_PAYLOAD_SIZE, "%s:%d",
- (circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL) ?
+ (circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL ||
+ circ->base_.purpose == CIRCUIT_PURPOSE_CONTROLLER) ?
ap_conn->socks_request->address : "",
ap_conn->socks_request->port);
payload_len = (int)strlen(payload)+1;
@@ -3839,8 +3909,8 @@ handle_hs_exit_conn(circuit_t *circ, edge_connection_t *conn)
return -1;
}
if (ret < 0) {
- log_info(LD_REND, "Didn't find rendezvous service (addr%s, port %d)",
- fmt_addr(&TO_CONN(conn)->addr), TO_CONN(conn)->port);
+ log_info(LD_REND, "Didn't find rendezvous service at %s",
+ connection_describe_peer(TO_CONN(conn)));
/* Send back reason DONE because we want to make hidden service port
* scanning harder thus instead of returning that the exit policy
* didn't match, which makes it obvious that the port is closed,
@@ -3975,7 +4045,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
* proxies. */
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Attempt by %s to open a stream %s. Closing.",
- safe_str(channel_get_canonical_remote_descr(or_circ->p_chan)),
+ safe_str(channel_describe_peer(or_circ->p_chan)),
client_chan ? "on first hop of circuit" :
"from unknown relay");
relay_send_end_cell_from_edge(rh.stream_id, circ,
@@ -3998,10 +4068,13 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
* caller might want to know whether the remote IP address has changed,
* and we might already have corrected base_.addr[ess] for the relay's
* canonical IP address. */
- if (or_circ && or_circ->p_chan)
- address = tor_strdup(channel_get_actual_remote_address(or_circ->p_chan));
- else
+ tor_addr_t chan_addr;
+ if (or_circ && or_circ->p_chan &&
+ channel_get_addr_if_possible(or_circ->p_chan, &chan_addr)) {
+ address = tor_addr_to_str_dup(&chan_addr);
+ } else {
address = tor_strdup("127.0.0.1");
+ }
port = 1; /* XXXX This value is never actually used anywhere, and there
* isn't "really" a connection here. But we
* need to set it to something nonzero. */
@@ -4200,8 +4273,8 @@ connection_exit_connect(edge_connection_t *edge_conn)
&why_failed_exit_policy)) {
if (BUG(!why_failed_exit_policy))
why_failed_exit_policy = "";
- log_info(LD_EXIT,"%s:%d failed exit policy%s. Closing.",
- escaped_safe_str_client(conn->address), conn->port,
+ log_info(LD_EXIT,"%s failed exit policy%s. Closing.",
+ connection_describe(conn),
why_failed_exit_policy);
connection_edge_end(edge_conn, END_STREAM_REASON_EXITPOLICY);
circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn);
@@ -4228,9 +4301,8 @@ connection_exit_connect(edge_connection_t *edge_conn)
if (!connection_edge_is_rendezvous_stream(edge_conn) &&
!network_reentry_is_allowed() &&
nodelist_reentry_contains(&conn->addr, conn->port)) {
- log_info(LD_EXIT, "%s:%d tried to connect back to a known relay address. "
- "Closing.", escaped_safe_str_client(conn->address),
- conn->port);
+ log_info(LD_EXIT, "%s tried to connect back to a known relay address. "
+ "Closing.", connection_describe(conn));
connection_edge_end(edge_conn, END_STREAM_REASON_CONNECTREFUSED);
circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn);
connection_free(conn);
diff --git a/src/core/or/connection_edge.h b/src/core/or/connection_edge.h
index 8c06af5664..c9433adade 100644
--- a/src/core/or/connection_edge.h
+++ b/src/core/or/connection_edge.h
@@ -20,6 +20,10 @@ edge_connection_t *TO_EDGE_CONN(connection_t *);
entry_connection_t *TO_ENTRY_CONN(connection_t *);
entry_connection_t *EDGE_TO_ENTRY_CONN(edge_connection_t *);
+const edge_connection_t *CONST_TO_EDGE_CONN(const connection_t *);
+const entry_connection_t *CONST_TO_ENTRY_CONN(const connection_t *);
+const entry_connection_t *CONST_EDGE_TO_ENTRY_CONN(const edge_connection_t *);
+
#define EXIT_CONN_STATE_MIN_ 1
/** State for an exit connection: waiting for response from DNS farm. */
#define EXIT_CONN_STATE_RESOLVING 1
@@ -94,6 +98,8 @@ int connection_edge_flushed_some(edge_connection_t *conn);
int connection_edge_finished_flushing(edge_connection_t *conn);
int connection_edge_finished_connecting(edge_connection_t *conn);
+void connection_entry_set_controller_wait(entry_connection_t *conn);
+
void connection_ap_about_to_close(entry_connection_t *edge_conn);
void connection_exit_about_to_close(edge_connection_t *edge_conn);
diff --git a/src/core/or/connection_or.c b/src/core/or/connection_or.c
index b88d1b6afb..e3e81ed9cb 100644
--- a/src/core/or/connection_or.c
+++ b/src/core/or/connection_or.c
@@ -99,8 +99,11 @@ static void connection_or_check_canonicity(or_connection_t *conn,
/**************************************************************/
-/** Convert a connection_t* to an or_connection_t*; assert if the cast is
- * invalid. */
+/**
+ * Cast a `connection_t *` to an `or_connection_t *`.
+ *
+ * Exit with an assertion failure if the input is not an `or_connnection_t`.
+ **/
or_connection_t *
TO_OR_CONN(connection_t *c)
{
@@ -108,6 +111,17 @@ TO_OR_CONN(connection_t *c)
return DOWNCAST(or_connection_t, c);
}
+/**
+ * Cast a `const connection_t *` to a `const or_connection_t *`.
+ *
+ * Exit with an assertion failure if the input is not an `or_connnection_t`.
+ **/
+const or_connection_t *
+CONST_TO_OR_CONN(const connection_t *c)
+{
+ return TO_OR_CONN((connection_t *)c);
+}
+
/** Clear clear conn->identity_digest and update other data
* structures as appropriate.*/
void
@@ -151,9 +165,9 @@ connection_or_set_identity_digest(or_connection_t *conn,
if (conn->chan)
chan = TLS_CHAN_TO_BASE(conn->chan);
- log_info(LD_HANDSHAKE, "Set identity digest for %p (%s): %s %s.",
+ log_info(LD_HANDSHAKE, "Set identity digest for %s at %p: %s %s.",
+ connection_describe(TO_CONN(conn)),
conn,
- escaped_safe_str(conn->base_.address),
hex_str(rsa_digest, DIGEST_LEN),
ed25519_fmt(ed_id));
log_info(LD_HANDSHAKE, " (Previously: %s %s)",
@@ -193,6 +207,26 @@ connection_or_set_identity_digest(or_connection_t *conn,
channel_set_identity_digest(chan, rsa_digest, ed_id);
}
+/**
+ * Return the Ed25519 identity of the peer for this connection (if any).
+ *
+ * Note that this ID may not be the _actual_ identity for the peer if
+ * authentication is not complete.
+ **/
+const struct ed25519_public_key_t *
+connection_or_get_alleged_ed25519_id(const or_connection_t *conn)
+{
+ if (conn && conn->chan) {
+ const channel_t *chan = NULL;
+ chan = TLS_CHAN_TO_BASE(conn->chan);
+ if (!ed25519_public_key_is_zero(&chan->ed25519_identity)) {
+ return &chan->ed25519_identity;
+ }
+ }
+
+ return NULL;
+}
+
/**************************************************************/
/** Map from a string describing what a non-open OR connection was doing when
@@ -380,7 +414,7 @@ connection_or_state_publish(const or_connection_t *conn, uint8_t state)
* be notified.
*/
-MOCK_IMPL(STATIC void,
+MOCK_IMPL(void,
connection_or_change_state,(or_connection_t *conn, uint8_t state))
{
tor_assert(conn);
@@ -532,11 +566,6 @@ connection_or_reached_eof(or_connection_t *conn)
int
connection_or_process_inbuf(or_connection_t *conn)
{
- /** Don't let the inbuf of a nonopen OR connection grow beyond this many
- * bytes: it's either a broken client, a non-Tor client, or a DOS
- * attempt. */
-#define MAX_OR_INBUF_WHEN_NONOPEN 0
-
int ret = 0;
tor_assert(conn);
@@ -547,6 +576,15 @@ connection_or_process_inbuf(or_connection_t *conn)
/* start TLS after handshake completion, or deal with error */
if (ret == 1) {
tor_assert(TO_CONN(conn)->proxy_state == PROXY_CONNECTED);
+ if (buf_datalen(conn->base_.inbuf) != 0) {
+ log_fn(LOG_PROTOCOL_WARN, LD_NET, "Found leftover (%d bytes) "
+ "when transitioning from PROXY_HANDSHAKING state on %s: "
+ "closing.",
+ (int)buf_datalen(conn->base_.inbuf),
+ connection_describe(TO_CONN(conn)));
+ connection_or_close_for_error(conn, 0);
+ return -1;
+ }
if (connection_tls_start_handshake(conn, 0) < 0)
ret = -1;
/* Touch the channel's active timestamp if there is one */
@@ -567,19 +605,15 @@ connection_or_process_inbuf(or_connection_t *conn)
break; /* don't do anything */
}
- /* This check was necessary with 0.2.2, when the TLS_SERVER_RENEGOTIATING
- * check would otherwise just let data accumulate. It serves no purpose
- * in 0.2.3.
- *
- * XXXX Remove this check once we verify that the above paragraph is
- * 100% true. */
- if (buf_datalen(conn->base_.inbuf) > MAX_OR_INBUF_WHEN_NONOPEN) {
- log_fn(LOG_PROTOCOL_WARN, LD_NET, "Accumulated too much data (%d bytes) "
- "on nonopen OR connection %s %s:%u in state %s; closing.",
+ /* This check makes sure that we don't have any data on the inbuf if we're
+ * doing our TLS handshake: if we did, they were probably put there by a
+ * SOCKS proxy trying to trick us into accepting unauthenticated data.
+ */
+ if (buf_datalen(conn->base_.inbuf) != 0) {
+ log_fn(LOG_PROTOCOL_WARN, LD_NET, "Accumulated data (%d bytes) "
+ "on non-open %s; closing.",
(int)buf_datalen(conn->base_.inbuf),
- connection_or_nonopen_was_started_here(conn) ? "to" : "from",
- conn->base_.address, conn->base_.port,
- conn_state_to_string(conn->base_.type, conn->base_.state));
+ connection_describe(TO_CONN(conn)));
connection_or_close_for_error(conn, 0);
ret = -1;
}
@@ -691,8 +725,8 @@ connection_or_finished_connecting(or_connection_t *or_conn)
conn = TO_CONN(or_conn);
tor_assert(conn->state == OR_CONN_STATE_CONNECTING);
- log_debug(LD_HANDSHAKE,"OR connect() to router at %s:%u finished.",
- conn->address,conn->port);
+ log_debug(LD_HANDSHAKE,"connect finished for %s",
+ connection_describe(conn));
if (proxy_type != PROXY_NONE) {
/* start proxy handshake */
@@ -881,7 +915,9 @@ connection_or_init_conn_from_address(or_connection_t *conn,
conn->base_.port = port;
tor_addr_copy(&conn->base_.addr, addr);
- tor_addr_copy(&conn->real_addr, addr);
+ if (! conn->base_.address) {
+ conn->base_.address = tor_strdup(fmt_addr(addr));
+ }
connection_or_check_canonicity(conn, started_here);
}
@@ -893,9 +929,10 @@ connection_or_init_conn_from_address(or_connection_t *conn,
static void
connection_or_check_canonicity(or_connection_t *conn, int started_here)
{
+ (void) started_here;
+
const char *id_digest = conn->identity_digest;
const ed25519_public_key_t *ed_id = NULL;
- const tor_addr_t *addr = &conn->real_addr;
if (conn->chan)
ed_id = & TLS_CHAN_TO_BASE(conn->chan)->ed25519_identity;
@@ -924,34 +961,17 @@ connection_or_check_canonicity(or_connection_t *conn, int started_here)
} else {
node_ap = &node_ipv6_ap;
}
- if (!started_here) {
- /* Override the addr/port, so our log messages will make sense.
- * This is dangerous, since if we ever try looking up a conn by
- * its actual addr/port, we won't remember. Careful! */
- /* XXXX arma: this is stupid, and it's the reason we need real_addr
- * to track is_canonical properly. What requires it? */
- /* XXXX <arma> i believe the reason we did this, originally, is because
- * we wanted to log what OR a connection was to, and if we logged the
- * right IP address and port 56244, that wouldn't be as helpful. now we
- * log the "right" port too, so we know if it's moria1 or moria2.
- */
- /* See #33898 for a ticket that resolves this technical debt. */
- tor_addr_copy(&conn->base_.addr, &node_ap->addr);
- conn->base_.port = node_ap->port;
- }
+ /* Remember the canonical addr/port so our log messages will make
+ sense. */
+ tor_addr_port_copy(&conn->canonical_orport, node_ap);
tor_free(conn->nickname);
conn->nickname = tor_strdup(node_get_nickname(r));
- tor_free(conn->base_.address);
- conn->base_.address = tor_addr_to_str_dup(&node_ap->addr);
} else {
tor_free(conn->nickname);
conn->nickname = tor_malloc(HEX_DIGEST_LEN+2);
conn->nickname[0] = '$';
base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1,
conn->identity_digest, DIGEST_LEN);
-
- tor_free(conn->base_.address);
- conn->base_.address = tor_addr_to_str_dup(addr);
}
/*
@@ -1010,9 +1030,10 @@ connection_or_single_set_badness_(time_t now,
or_conn->base_.timestamp_created + TIME_BEFORE_OR_CONN_IS_TOO_OLD
< now) {
log_info(LD_OR,
- "Marking OR conn to %s:%d as too old for new circuits "
+ "Marking %s as too old for new circuits "
"(fd "TOR_SOCKET_T_FORMAT", %d secs old).",
- or_conn->base_.address, or_conn->base_.port, or_conn->base_.s,
+ connection_describe(TO_CONN(or_conn)),
+ or_conn->base_.s,
(int)(now - or_conn->base_.timestamp_created));
connection_or_mark_bad_for_new_circs(or_conn);
}
@@ -1077,10 +1098,11 @@ connection_or_group_set_badness_(smartlist_t *group, int force)
/* We have at least one open canonical connection to this router,
* and this one is open but not canonical. Mark it bad. */
log_info(LD_OR,
- "Marking OR conn to %s:%d as unsuitable for new circuits: "
+ "Marking %s unsuitable for new circuits: "
"(fd "TOR_SOCKET_T_FORMAT", %d secs old). It is not "
"canonical, and we have another connection to that OR that is.",
- or_conn->base_.address, or_conn->base_.port, or_conn->base_.s,
+ connection_describe(TO_CONN(or_conn)),
+ or_conn->base_.s,
(int)(now - or_conn->base_.timestamp_created));
connection_or_mark_bad_for_new_circs(or_conn);
continue;
@@ -1121,22 +1143,24 @@ connection_or_group_set_badness_(smartlist_t *group, int force)
/* This isn't the best conn, _and_ the best conn is better than it */
if (best->is_canonical) {
log_info(LD_OR,
- "Marking OR conn to %s:%d as unsuitable for new circuits: "
+ "Marking %s as unsuitable for new circuits: "
"(fd "TOR_SOCKET_T_FORMAT", %d secs old). "
"We have a better canonical one "
"(fd "TOR_SOCKET_T_FORMAT"; %d secs old).",
- or_conn->base_.address, or_conn->base_.port, or_conn->base_.s,
+ connection_describe(TO_CONN(or_conn)),
+ or_conn->base_.s,
(int)(now - or_conn->base_.timestamp_created),
best->base_.s, (int)(now - best->base_.timestamp_created));
connection_or_mark_bad_for_new_circs(or_conn);
- } else if (!tor_addr_compare(&or_conn->real_addr,
- &best->real_addr, CMP_EXACT)) {
+ } else if (tor_addr_eq(&TO_CONN(or_conn)->addr,
+ &TO_CONN(best)->addr)) {
log_info(LD_OR,
- "Marking OR conn to %s:%d as unsuitable for new circuits: "
+ "Marking %s unsuitable for new circuits: "
"(fd "TOR_SOCKET_T_FORMAT", %d secs old). We have a better "
"one with the "
"same address (fd "TOR_SOCKET_T_FORMAT"; %d secs old).",
- or_conn->base_.address, or_conn->base_.port, or_conn->base_.s,
+ connection_describe(TO_CONN(or_conn)),
+ or_conn->base_.s,
(int)(now - or_conn->base_.timestamp_created),
best->base_.s, (int)(now - best->base_.timestamp_created));
connection_or_mark_bad_for_new_circs(or_conn);
@@ -1160,7 +1184,7 @@ static time_t or_connect_failure_map_next_cleanup_ts = 0;
* port.
*
* We need to identify a connection failure with these three values because we
- * want to avoid to wrongfully blacklist a relay if someone is trying to
+ * want to avoid to wrongfully block a relay if someone is trying to
* extend to a known identity digest but with the wrong IP/port. For instance,
* it can happen if a relay changed its port but the client still has an old
* descriptor with the old port. We want to stop connecting to that
@@ -1259,7 +1283,7 @@ static or_connect_failure_entry_t *
or_connect_failure_new(const or_connection_t *or_conn)
{
or_connect_failure_entry_t *ocf = tor_malloc_zero(sizeof(*ocf));
- or_connect_failure_init(or_conn->identity_digest, &or_conn->real_addr,
+ or_connect_failure_init(or_conn->identity_digest, &TO_CONN(or_conn)->addr,
TO_CONN(or_conn)->port, ocf);
return ocf;
}
@@ -1464,10 +1488,9 @@ connection_or_connect, (const tor_addr_t *_addr, uint16_t port,
* that is we haven't had a failure earlier. This is to avoid to try to
* constantly connect to relays that we think are not reachable. */
if (!should_connect_to_relay(conn)) {
- log_info(LD_GENERAL, "Can't connect to identity %s at %s:%u because we "
+ log_info(LD_GENERAL, "Can't connect to %s because we "
"failed earlier. Refusing.",
- hex_str(id_digest, DIGEST_LEN), fmt_addr(&TO_CONN(conn)->addr),
- TO_CONN(conn)->port);
+ connection_describe_peer(TO_CONN(conn)));
connection_free_(TO_CONN(conn));
return NULL;
}
@@ -1507,7 +1530,7 @@ connection_or_connect, (const tor_addr_t *_addr, uint16_t port,
"transport proxy supporting '%s'. This can happen if you "
"haven't provided a ClientTransportPlugin line, or if "
"your pluggable transport proxy stopped running.",
- fmt_addrport(&TO_CONN(conn)->addr, TO_CONN(conn)->port),
+ connection_describe_peer(TO_CONN(conn)),
transport_name, transport_name);
control_event_bootstrap_prob_or(
@@ -1516,9 +1539,9 @@ connection_or_connect, (const tor_addr_t *_addr, uint16_t port,
conn);
} else {
- log_warn(LD_GENERAL, "Tried to connect to '%s' through a proxy, but "
+ log_warn(LD_GENERAL, "Tried to connect to %s through a proxy, but "
"the proxy address could not be found.",
- fmt_addrport(&TO_CONN(conn)->addr, TO_CONN(conn)->port));
+ connection_describe_peer(TO_CONN(conn)));
}
connection_free_(TO_CONN(conn));
@@ -1638,8 +1661,8 @@ connection_tls_start_handshake,(or_connection_t *conn, int receiving))
log_warn(LD_BUG,"tor_tls_new failed. Closing.");
return -1;
}
- tor_tls_set_logged_address(conn->tls, // XXX client and relay?
- escaped_safe_str(conn->base_.address));
+ tor_tls_set_logged_address(conn->tls,
+ connection_describe_peer(TO_CONN(conn)));
connection_start_reading(TO_CONN(conn));
log_debug(LD_HANDSHAKE,"starting TLS handshake on fd "TOR_SOCKET_T_FORMAT,
@@ -1786,18 +1809,15 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
crypto_pk_t *identity_rcvd=NULL;
const or_options_t *options = get_options();
int severity = server_mode(options) ? LOG_PROTOCOL_WARN : LOG_WARN;
- const char *safe_address =
- started_here ? conn->base_.address :
- safe_str_client(conn->base_.address);
const char *conn_type = started_here ? "outgoing" : "incoming";
int has_cert = 0;
check_no_tls_errors();
has_cert = tor_tls_peer_has_cert(conn->tls);
if (started_here && !has_cert) {
- log_info(LD_HANDSHAKE,"Tried connecting to router at %s:%d, but it didn't "
+ log_info(LD_HANDSHAKE,"Tried connecting to router at %s, but it didn't "
"send a cert! Closing.",
- safe_address, conn->base_.port);
+ connection_describe_peer(TO_CONN(conn)));
return -1;
} else if (!has_cert) {
log_debug(LD_HANDSHAKE,"Got incoming connection with no certificate. "
@@ -1809,9 +1829,9 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
int v = tor_tls_verify(started_here?severity:LOG_INFO,
conn->tls, &identity_rcvd);
if (started_here && v<0) {
- log_fn(severity,LD_HANDSHAKE,"Tried connecting to router at %s:%d: It"
+ log_fn(severity,LD_HANDSHAKE,"Tried connecting to router at %s: It"
" has a cert but it's invalid. Closing.",
- safe_address, conn->base_.port);
+ connection_describe_peer(TO_CONN(conn)));
return -1;
} else if (v<0) {
log_info(LD_HANDSHAKE,"Incoming connection gave us an invalid cert "
@@ -1819,7 +1839,8 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
} else {
log_debug(LD_HANDSHAKE,
"The certificate seems to be valid on %s connection "
- "with %s:%d", conn_type, safe_address, conn->base_.port);
+ "with %s", conn_type,
+ connection_describe_peer(TO_CONN(conn)));
}
check_no_tls_errors();
}
@@ -1891,9 +1912,9 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
const int expected_ed_key =
! ed25519_public_key_is_zero(&chan->ed25519_identity);
- log_info(LD_HANDSHAKE, "learned peer id for %p (%s): %s, %s",
+ log_info(LD_HANDSHAKE, "learned peer id for %s at %p: %s, %s",
+ connection_describe(TO_CONN(conn)),
conn,
- safe_str_client(conn->base_.address),
hex_str((const char*)rsa_peer_id, DIGEST_LEN),
ed25519_fmt(ed_peer_id));
@@ -1907,9 +1928,9 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
conn->nickname[0] = '$';
base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1,
conn->identity_digest, DIGEST_LEN);
- log_info(LD_HANDSHAKE, "Connected to router %s at %s:%d without knowing "
- "its key. Hoping for the best.",
- conn->nickname, conn->base_.address, conn->base_.port);
+ log_info(LD_HANDSHAKE, "Connected to router at %s without knowing "
+ "its key. Hoping for the best.",
+ connection_describe_peer(TO_CONN(conn)));
/* if it's a bridge and we didn't know its identity fingerprint, now
* we do -- remember it for future attempts. */
learned_router_identity(&conn->base_.addr, conn->base_.port,
@@ -1983,9 +2004,9 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
}
log_fn(severity, LD_HANDSHAKE,
- "Tried connecting to router at %s:%d, but RSA + ed25519 identity "
+ "Tried connecting to router at %s, but RSA + ed25519 identity "
"keys were not as expected: wanted %s + %s but got %s + %s.%s",
- conn->base_.address, conn->base_.port,
+ connection_describe_peer(TO_CONN(conn)),
expected_rsa, expected_ed, seen_rsa, seen_ed, extra_log);
/* Tell the new guard API about the channel failure */
@@ -2012,9 +2033,14 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
/* If we learned an identity for this connection, then we might have
* just discovered it to be canonical. */
connection_or_check_canonicity(conn, conn->handshake_state->started_here);
+ if (conn->tls)
+ tor_tls_set_logged_address(conn->tls,
+ connection_describe_peer(TO_CONN(conn)));
}
if (authdir_mode_tests_reachability(options)) {
+ // We don't want to use canonical_orport here -- we want the address
+ // that we really used.
dirserv_orconn_tls_done(&conn->base_.addr, conn->base_.port,
(const char*)rsa_peer_id, ed_peer_id);
}
@@ -2057,11 +2083,10 @@ connection_tls_finish_handshake(or_connection_t *conn)
tor_assert(!started_here);
- log_debug(LD_HANDSHAKE,"%s tls handshake on %p with %s done, using "
+ log_debug(LD_HANDSHAKE,"%s tls handshake on %s done, using "
"ciphersuite %s. verifying.",
started_here?"outgoing":"incoming",
- conn,
- safe_str_client(conn->base_.address),
+ connection_describe_peer(TO_CONN(conn)),
tor_tls_get_ciphersuite_name(conn->tls));
if (connection_or_check_valid_tls_handshake(conn, started_here,
@@ -2493,11 +2518,9 @@ connection_or_send_netinfo,(or_connection_t *conn))
netinfo_cell_set_timestamp(netinfo_cell, (uint32_t)now);
/* Their address. */
- const tor_addr_t *remote_tor_addr =
- !tor_addr_is_null(&conn->real_addr) ? &conn->real_addr : &conn->base_.addr;
- /* We use &conn->real_addr below, unless it hasn't yet been set. If it
- * hasn't yet been set, we know that base_.addr hasn't been tampered with
- * yet either. */
+ const tor_addr_t *remote_tor_addr = &TO_CONN(conn)->addr;
+ /* We can safely use TO_CONN(conn)->addr here, since we no longer replace
+ * it with a canonical address. */
netinfo_addr_t *their_addr = netinfo_addr_from_tor_addr(remote_tor_addr);
netinfo_cell_set_other_addr(netinfo_cell, their_addr);
@@ -2507,14 +2530,11 @@ connection_or_send_netinfo,(or_connection_t *conn))
* is an outgoing connection, act like a normal client and omit it. */
if ((public_server_mode(get_options()) || !conn->is_outgoing) &&
(me = router_get_my_routerinfo())) {
- tor_addr_t my_addr;
- tor_addr_from_ipv4h(&my_addr, me->addr);
-
uint8_t n_my_addrs = 1 + !tor_addr_is_null(&me->ipv6_addr);
netinfo_cell_set_n_my_addrs(netinfo_cell, n_my_addrs);
netinfo_cell_add_my_addrs(netinfo_cell,
- netinfo_addr_from_tor_addr(&my_addr));
+ netinfo_addr_from_tor_addr(&me->ipv4_addr));
if (!tor_addr_is_null(&me->ipv6_addr)) {
netinfo_cell_add_my_addrs(netinfo_cell,
diff --git a/src/core/or/connection_or.h b/src/core/or/connection_or.h
index e9ace56ab4..8cbe8c028b 100644
--- a/src/core/or/connection_or.h
+++ b/src/core/or/connection_or.h
@@ -16,6 +16,7 @@ struct ed25519_public_key_t;
struct ed25519_keypair_t;
or_connection_t *TO_OR_CONN(connection_t *);
+const or_connection_t *CONST_TO_OR_CONN(const connection_t *);
#include "core/or/orconn_event.h"
@@ -72,6 +73,8 @@ void connection_or_init_conn_from_address(or_connection_t *conn,
int connection_or_client_learned_peer_id(or_connection_t *conn,
const uint8_t *rsa_peer_id,
const struct ed25519_public_key_t *ed_peer_id);
+const struct ed25519_public_key_t *connection_or_get_alleged_ed25519_id(
+ const or_connection_t *conn);
time_t connection_or_client_used(or_connection_t *conn);
MOCK_DECL(int, connection_or_get_num_circuits, (or_connection_t *conn));
void or_handshake_state_free_(or_handshake_state_t *state);
@@ -117,14 +120,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 /* defined(CONNECTION_OR_PRIVATE) */
/*
* Call this when changing connection state, so notifications to the owning
* channel can be handled.
*/
-MOCK_DECL(STATIC void,connection_or_change_state,
+MOCK_DECL(void, connection_or_change_state,
(or_connection_t *conn, uint8_t state));
-#endif /* defined(CONNECTION_OR_PRIVATE) */
#ifdef TOR_UNIT_TESTS
extern int testing__connection_or_pretend_TLSSECRET_is_supported;
diff --git a/src/core/or/connection_st.h b/src/core/or/connection_st.h
index 685c9f89f4..082420c4bc 100644
--- a/src/core/or/connection_st.h
+++ b/src/core/or/connection_st.h
@@ -101,8 +101,6 @@ struct connection_t {
struct buf_t *inbuf; /**< Buffer holding data read over this connection. */
struct buf_t *outbuf; /**< Buffer holding data to write over this
* connection. */
- size_t outbuf_flushlen; /**< How much data should we try to flush from the
- * outbuf? */
time_t timestamp_last_read_allowed; /**< When was the last time libevent said
* we could read? */
time_t timestamp_last_write_allowed; /**< When was the last time libevent
@@ -112,10 +110,39 @@ struct connection_t {
int socket_family; /**< Address family of this connection's socket. Usually
* AF_INET, but it can also be AF_UNIX, or AF_INET6 */
- tor_addr_t addr; /**< IP that socket "s" is directly connected to;
- * may be the IP address for a proxy or pluggable transport,
- * see "address" for the address of the final destination.
- */
+ /**
+ * IP address on the internet of this connection's peer, usually.
+ *
+ * This address may come from several sources. If this is an outbound
+ * connection, it is the address we are trying to connect to--either
+ * directly through `s`, or via a proxy. (If we used a proxy, then
+ * `getpeername(s)` will not give this address.)
+ *
+ * For incoming connections, this field is the address we got from
+ * getpeername() or accept(), as updated by any proxy that we
+ * are using (for example, an ExtORPort proxy).
+ *
+ * For listeners, this is the address we are trying to bind to.
+ *
+ * If this connection is using a unix socket, then this address is a null
+ * address, and the real address is in the `address` field.
+ *
+ * If this connection represents a request made somewhere other than via
+ * TCP (for example, a UDP dns request, or a controller resolve request),
+ * then this address is the address that originated the request.
+ *
+ * TECHNICAL DEBT:
+ *
+ * There are a few places in the code that modify this address,
+ * or use it in other ways that we don't currently like. Please don't add
+ * any more!
+ *
+ * The misuses of this field include:
+ * * Setting it on linked connections, possibly.
+ * * Updating it based on the Forwarded-For header-- Forwarded-For is
+ * set by a proxy, but not a local trusted proxy.
+ **/
+ tor_addr_t addr;
uint16_t port; /**< If non-zero, port that socket "s" is directly connected
* to; may be the port for a proxy or pluggable transport,
* see "address" for the port at the final destination. */
@@ -125,12 +152,18 @@ struct connection_t {
* marked.) */
const char *marked_for_close_file; /**< For debugging: in which file were
* we marked for close? */
- char *address; /**< FQDN (or IP) and port of the final destination for this
- * connection; this is always the remote address, it is
- * passed to a proxy or pluggable transport if one in use.
- * See "addr" and "port" for the address that socket "s" is
- * directly connected to.
- * strdup into this, because free_connection() frees it. */
+ /**
+ * String address of the peer of this connection.
+ *
+ * TECHNICAL DEBT:
+ *
+ * This field serves many purposes, and they're not all pretty. In addition
+ * to describing the peer we're connected to, it can also hold:
+ *
+ * * An address we're trying to resolve (as an exit).
+ * * A unix address we're trying to bind to (as a listener).
+ **/
+ char *address;
/** Another connection that's connected to this one in lieu of a socket. */
struct connection_t *linked_conn;
diff --git a/src/core/or/cpath_build_state_st.h b/src/core/or/cpath_build_state_st.h
index ee9a0d972c..eb8e97edc5 100644
--- a/src/core/or/cpath_build_state_st.h
+++ b/src/core/or/cpath_build_state_st.h
@@ -24,6 +24,8 @@ struct cpath_build_state_t {
unsigned int need_capacity : 1;
/** Whether the last hop was picked with exiting in mind. */
unsigned int is_internal : 1;
+ /** Is this an IPv6 ORPort self-testing circuit? */
+ unsigned int is_ipv6_selftest : 1;
/** Did we pick this as a one-hop tunnel (not safe for other streams)?
* These are for encrypted dir conns that exit to this router, not
* for arbitrary exits from the circuit. */
diff --git a/src/core/or/crypt_path.c b/src/core/or/crypt_path.c
index 8f41540848..e1bbd81251 100644
--- a/src/core/or/crypt_path.c
+++ b/src/core/or/crypt_path.c
@@ -30,6 +30,7 @@
#include "core/crypto/onion_crypto.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
+#include "core/or/extendinfo.h"
#include "lib/crypt_ops/crypto_dh.h"
#include "lib/crypt_ops/crypto_util.h"
@@ -259,4 +260,3 @@ cpath_get_n_hops(crypt_path_t **head_ptr)
}
#endif /* defined(TOR_UNIT_TESTS) */
-
diff --git a/src/core/or/dos.c b/src/core/or/dos.c
index 5f99280030..41bf303ffe 100644
--- a/src/core/or/dos.c
+++ b/src/core/or/dos.c
@@ -584,7 +584,7 @@ dos_geoip_entry_about_to_free(const clientmap_entry_t *geoip_ent)
SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
if (conn->type == CONN_TYPE_OR) {
or_connection_t *or_conn = TO_OR_CONN(conn);
- if (!tor_addr_compare(&geoip_ent->addr, &or_conn->real_addr,
+ if (!tor_addr_compare(&geoip_ent->addr, &TO_CONN(or_conn)->addr,
CMP_EXACT)) {
or_conn->tracked_for_dos_mitigation = 0;
}
@@ -696,12 +696,12 @@ dos_new_client_conn(or_connection_t *or_conn, const char *transport_name)
* reason to do so is because network reentry is possible where a client
* connection comes from an Exit node. Even when we'll fix reentry, this is
* a robust defense to keep in place. */
- if (nodelist_probably_contains_address(&or_conn->real_addr)) {
+ if (nodelist_probably_contains_address(&TO_CONN(or_conn)->addr)) {
goto end;
}
/* We are only interested in client connection from the geoip cache. */
- entry = geoip_lookup_client(&or_conn->real_addr, transport_name,
+ entry = geoip_lookup_client(&TO_CONN(or_conn)->addr, transport_name,
GEOIP_CLIENT_CONNECT);
if (BUG(entry == NULL)) {
/* Should never happen because we note down the address in the geoip
@@ -712,7 +712,7 @@ dos_new_client_conn(or_connection_t *or_conn, const char *transport_name)
entry->dos_stats.concurrent_count++;
or_conn->tracked_for_dos_mitigation = 1;
log_debug(LD_DOS, "Client address %s has now %u concurrent connections.",
- fmt_addr(&or_conn->real_addr),
+ fmt_addr(&TO_CONN(or_conn)->addr),
entry->dos_stats.concurrent_count);
end:
@@ -735,7 +735,7 @@ dos_close_client_conn(const or_connection_t *or_conn)
}
/* We are only interested in client connection from the geoip cache. */
- entry = geoip_lookup_client(&or_conn->real_addr, NULL,
+ entry = geoip_lookup_client(&TO_CONN(or_conn)->addr, NULL,
GEOIP_CLIENT_CONNECT);
if (entry == NULL) {
/* This can happen because we can close a connection before the channel
@@ -753,7 +753,7 @@ dos_close_client_conn(const or_connection_t *or_conn)
entry->dos_stats.concurrent_count--;
log_debug(LD_DOS, "Client address %s has lost a connection. Concurrent "
"connections are now at %u",
- fmt_addr(&or_conn->real_addr),
+ fmt_addr(&TO_CONN(or_conn)->addr),
entry->dos_stats.concurrent_count);
end:
diff --git a/src/core/or/extend_info_st.h b/src/core/or/extend_info_st.h
index a66ce24cfa..757c6a1771 100644
--- a/src/core/or/extend_info_st.h
+++ b/src/core/or/extend_info_st.h
@@ -15,9 +15,14 @@
#include "lib/crypt_ops/crypto_curve25519.h"
#include "lib/crypt_ops/crypto_ed25519.h"
+/** Largest number of addresses we handle in an extend_info.
+ *
+ * More are permitted in an EXTEND cell, but we won't handle them. */
+#define EXTEND_INFO_MAX_ADDRS 2
+
/** Information on router used when extending a circuit. We don't need a
* full routerinfo_t to extend: we only need addr:port:keyid to build an OR
- * connection, and onion_key to create the onionskin. Note that for onehop
+ * connection, and onion_key to create the onionskin. Note that for one-hop
* general-purpose tunnels, the onion_key is NULL. */
struct extend_info_t {
char nickname[MAX_HEX_NICKNAME_LEN+1]; /**< This router's nickname for
@@ -26,9 +31,12 @@ struct extend_info_t {
char identity_digest[DIGEST_LEN];
/** Ed25519 identity for this router, if any. */
ed25519_public_key_t ed_identity;
- uint16_t port; /**< OR port. */
- tor_addr_t addr; /**< IP address. */
- crypto_pk_t *onion_key; /**< Current onionskin key. */
+ /** IP/Port values for this hop's ORPort(s). Any unused values are set
+ * to a null address. */
+ tor_addr_port_t orports[EXTEND_INFO_MAX_ADDRS];
+ /** TAP onion key for this hop. */
+ crypto_pk_t *onion_key;
+ /** Ntor onion key for this hop. */
curve25519_public_key_t curve25519_onion_key;
};
diff --git a/src/core/or/extendinfo.c b/src/core/or/extendinfo.c
new file mode 100644
index 0000000000..22e5b664bb
--- /dev/null
+++ b/src/core/or/extendinfo.c
@@ -0,0 +1,330 @@
+/* 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 extendinfo.c
+ * @brief Functions for creating and using extend_info_t objects.
+ *
+ * An extend_info_t is the information we hold about a relay in order to
+ * extend a circuit to it.
+ **/
+
+#include "core/or/or.h"
+#include "core/or/extendinfo.h"
+
+#include "app/config/config.h"
+#include "core/or/policies.h"
+#include "feature/nodelist/describe.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
+#include "lib/crypt_ops/crypto_rand.h"
+
+#include "core/or/extend_info_st.h"
+#include "feature/nodelist/node_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerstatus_st.h"
+
+/** Allocate a new extend_info object based on the various arguments. */
+extend_info_t *
+extend_info_new(const char *nickname,
+ const char *rsa_id_digest,
+ const ed25519_public_key_t *ed_id,
+ crypto_pk_t *onion_key,
+ const curve25519_public_key_t *ntor_key,
+ const tor_addr_t *addr, uint16_t port)
+{
+ extend_info_t *info = tor_malloc_zero(sizeof(extend_info_t));
+ if (rsa_id_digest)
+ memcpy(info->identity_digest, rsa_id_digest, DIGEST_LEN);
+ if (ed_id && !ed25519_public_key_is_zero(ed_id))
+ memcpy(&info->ed_identity, ed_id, sizeof(ed25519_public_key_t));
+ if (nickname)
+ strlcpy(info->nickname, nickname, sizeof(info->nickname));
+ if (onion_key)
+ info->onion_key = crypto_pk_dup_key(onion_key);
+ if (ntor_key)
+ memcpy(&info->curve25519_onion_key, ntor_key,
+ sizeof(curve25519_public_key_t));
+ for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
+ tor_addr_make_unspec(&info->orports[i].addr);
+ }
+
+ if (addr) {
+ extend_info_add_orport(info, addr, port);
+ }
+ return info;
+}
+
+/**
+ * Add another address:port pair to a given extend_info_t, if there is
+ * room. Return 0 on success, -1 on failure.
+ **/
+int
+extend_info_add_orport(extend_info_t *ei,
+ const tor_addr_t *addr,
+ uint16_t port)
+{
+ for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
+ if (tor_addr_is_unspec(&ei->orports[i].addr)) {
+ tor_addr_copy(&ei->orports[i].addr, addr);
+ ei->orports[i].port = port;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+/** Allocate and return a new extend_info that can be used to build a
+ * circuit to or through the node <b>node</b>. Use the primary address
+ * of the node (i.e. its IPv4 address) unless
+ * <b>for_direct_connect</b> is true, in which case the preferred
+ * address is used instead. May return NULL if there is not enough
+ * info about <b>node</b> to extend to it--for example, if the preferred
+ * routerinfo_t or microdesc_t is missing, or if for_direct_connect is
+ * true and none of the node's addresses is allowed by tor's firewall
+ * and IP version config.
+ **/
+extend_info_t *
+extend_info_from_node(const node_t *node, int for_direct_connect)
+{
+ crypto_pk_t *rsa_pubkey = NULL;
+ extend_info_t *info = NULL;
+ tor_addr_port_t ap;
+ int valid_addr = 0;
+
+ if (!node_has_preferred_descriptor(node, for_direct_connect)) {
+ return NULL;
+ }
+
+ /* Choose a preferred address first, but fall back to an allowed address. */
+ if (for_direct_connect)
+ reachable_addr_choose_from_node(node, FIREWALL_OR_CONNECTION, 0, &ap);
+ else {
+ node_get_prim_orport(node, &ap);
+ }
+ valid_addr = tor_addr_port_is_valid_ap(&ap, 0);
+
+ if (valid_addr)
+ log_debug(LD_CIRC, "using %s for %s",
+ fmt_addrport(&ap.addr, ap.port),
+ node->ri ? node->ri->nickname : node->rs->nickname);
+ else
+ log_warn(LD_CIRC, "Could not choose valid address for %s",
+ node->ri ? node->ri->nickname : node->rs->nickname);
+
+ /* Every node we connect or extend to must support ntor */
+ if (!node_has_curve25519_onion_key(node)) {
+ log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
+ "Attempted to create extend_info for a node that does not support "
+ "ntor: %s", node_describe(node));
+ return NULL;
+ }
+
+ const ed25519_public_key_t *ed_pubkey = NULL;
+
+ /* Don't send the ed25519 pubkey unless the target node actually supports
+ * authenticating with it. */
+ if (node_supports_ed25519_link_authentication(node, 0)) {
+ log_info(LD_CIRC, "Including Ed25519 ID for %s", node_describe(node));
+ ed_pubkey = node_get_ed25519_id(node);
+ } else if (node_get_ed25519_id(node)) {
+ log_info(LD_CIRC, "Not including the ed25519 ID for %s, since it won't "
+ "be able to authenticate it.",
+ node_describe(node));
+ }
+
+ /* Retrieve the curve25519 pubkey. */
+ const curve25519_public_key_t *curve_pubkey =
+ node_get_curve25519_onion_key(node);
+ rsa_pubkey = node_get_rsa_onion_key(node);
+
+ if (valid_addr && node->ri) {
+ info = extend_info_new(node->ri->nickname,
+ node->identity,
+ ed_pubkey,
+ rsa_pubkey,
+ curve_pubkey,
+ &ap.addr,
+ ap.port);
+ } else if (valid_addr && node->rs && node->md) {
+ info = extend_info_new(node->rs->nickname,
+ node->identity,
+ ed_pubkey,
+ rsa_pubkey,
+ curve_pubkey,
+ &ap.addr,
+ ap.port);
+ }
+
+ crypto_pk_free(rsa_pubkey);
+ return info;
+}
+
+/** Release storage held by an extend_info_t struct. */
+void
+extend_info_free_(extend_info_t *info)
+{
+ if (!info)
+ return;
+ crypto_pk_free(info->onion_key);
+ tor_free(info);
+}
+
+/** Allocate and return a new extend_info_t with the same contents as
+ * <b>info</b>. */
+extend_info_t *
+extend_info_dup(extend_info_t *info)
+{
+ extend_info_t *newinfo;
+ tor_assert(info);
+ newinfo = tor_malloc(sizeof(extend_info_t));
+ memcpy(newinfo, info, sizeof(extend_info_t));
+ if (info->onion_key)
+ newinfo->onion_key = crypto_pk_dup_key(info->onion_key);
+ else
+ newinfo->onion_key = NULL;
+ return newinfo;
+}
+
+/* Does ei have a valid TAP key? */
+int
+extend_info_supports_tap(const extend_info_t* ei)
+{
+ tor_assert(ei);
+ /* Valid TAP keys are not NULL */
+ return ei->onion_key != NULL;
+}
+
+/* Does ei have a valid ntor key? */
+int
+extend_info_supports_ntor(const extend_info_t* ei)
+{
+ tor_assert(ei);
+ /* Valid ntor keys have at least one non-zero byte */
+ return !fast_mem_is_zero(
+ (const char*)ei->curve25519_onion_key.public_key,
+ CURVE25519_PUBKEY_LEN);
+}
+
+/* Does ei have an onion key which it would prefer to use?
+ * Currently, we prefer ntor keys*/
+int
+extend_info_has_preferred_onion_key(const extend_info_t* ei)
+{
+ tor_assert(ei);
+ return extend_info_supports_ntor(ei);
+}
+
+/** Return true iff the given address can be used to extend to. */
+int
+extend_info_addr_is_allowed(const tor_addr_t *addr)
+{
+ tor_assert(addr);
+
+ /* Check if we have a private address and if we can extend to it. */
+ if ((tor_addr_is_internal(addr, 0) || tor_addr_is_multicast(addr)) &&
+ !get_options()->ExtendAllowPrivateAddresses) {
+ goto disallow;
+ }
+ /* Allowed! */
+ return 1;
+ disallow:
+ return 0;
+}
+
+/**
+ * Return true if @a addr : @a port is a listed ORPort in @a ei.
+ **/
+bool
+extend_info_has_orport(const extend_info_t *ei,
+ const tor_addr_t *addr, uint16_t port)
+{
+ IF_BUG_ONCE(ei == NULL) {
+ return false;
+ }
+
+ for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
+ const tor_addr_port_t *ei_ap = &ei->orports[i];
+ if (tor_addr_eq(&ei_ap->addr, addr) && ei_ap->port == port)
+ return true;
+ }
+ return false;
+}
+
+/**
+ * If the extend_info @a ei has an orport of the chosen family, then return
+ * that orport. Otherwise, return NULL.
+ **/
+const tor_addr_port_t *
+extend_info_get_orport(const extend_info_t *ei, int family)
+{
+ for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
+ if (tor_addr_is_unspec(&ei->orports[i].addr))
+ continue;
+ if (tor_addr_family(&ei->orports[i].addr) == family)
+ return &ei->orports[i];
+ }
+ return NULL;
+}
+
+/**
+ * Chose an addr_port_t within @a ei to connect to.
+ **/
+const tor_addr_port_t *
+extend_info_pick_orport(const extend_info_t *ei)
+{
+ IF_BUG_ONCE(!ei) {
+ return NULL;
+ }
+ const or_options_t *options = get_options();
+ if (!server_mode(options)) {
+ // If we aren't a server, just pick the first address we built into
+ // this extendinfo.
+ return &ei->orports[0];
+ }
+
+ const bool ipv6_ok = router_can_extend_over_ipv6(options);
+
+ // Use 'usable' to collect the usable orports, then pick one.
+ const tor_addr_port_t *usable[EXTEND_INFO_MAX_ADDRS];
+ int n_usable = 0;
+ for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
+ const tor_addr_port_t *a = &ei->orports[i];
+ const int family = tor_addr_family(&a->addr);
+ if (family == AF_INET || (ipv6_ok && family == AF_INET6)) {
+ usable[n_usable++] = a;
+ }
+ }
+
+ if (n_usable == 0) {
+ // Need to bail out early, since nothing will work.
+ return NULL;
+ }
+
+ crypto_fast_rng_t *rng = get_thread_fast_rng();
+ const int idx = crypto_fast_rng_get_uint(rng, n_usable);
+
+ return usable[idx];
+}
+
+/**
+ * Return true if any orport address in @a ei is an internal address.
+ **/
+bool
+extend_info_any_orport_addr_is_internal(const extend_info_t *ei)
+{
+ IF_BUG_ONCE(ei == NULL) {
+ return false;
+ }
+
+ for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
+ if (! tor_addr_is_unspec(&ei->orports[i].addr) &&
+ tor_addr_is_internal(&ei->orports[i].addr, 0))
+ return true;
+ }
+ return false;
+}
diff --git a/src/core/or/extendinfo.h b/src/core/or/extendinfo.h
new file mode 100644
index 0000000000..0049dd0189
--- /dev/null
+++ b/src/core/or/extendinfo.h
@@ -0,0 +1,40 @@
+/* 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 extendinfo.h
+ * @brief Header for core/or/extendinfo.c
+ **/
+
+#ifndef TOR_CORE_OR_EXTENDINFO_H
+#define TOR_CORE_OR_EXTENDINFO_H
+
+extend_info_t *extend_info_new(const char *nickname,
+ const char *rsa_id_digest,
+ const struct ed25519_public_key_t *ed_id,
+ crypto_pk_t *onion_key,
+ const struct curve25519_public_key_t *ntor_key,
+ const tor_addr_t *addr, uint16_t port);
+extend_info_t *extend_info_from_node(const node_t *r, int for_direct_connect);
+extend_info_t *extend_info_dup(extend_info_t *info);
+void extend_info_free_(extend_info_t *info);
+#define extend_info_free(info) \
+ FREE_AND_NULL(extend_info_t, extend_info_free_, (info))
+int extend_info_addr_is_allowed(const tor_addr_t *addr);
+int extend_info_supports_tap(const extend_info_t* ei);
+int extend_info_supports_ntor(const extend_info_t* ei);
+int extend_info_has_preferred_onion_key(const extend_info_t* ei);
+bool extend_info_has_orport(const extend_info_t *ei,
+ const tor_addr_t *addr, uint16_t port);
+int extend_info_add_orport(extend_info_t *ei,
+ const tor_addr_t *addr,
+ uint16_t port);
+const tor_addr_port_t *extend_info_get_orport(const extend_info_t *ei,
+ int family);
+const tor_addr_port_t *extend_info_pick_orport(const extend_info_t *ei);
+bool extend_info_any_orport_addr_is_internal(const extend_info_t *ei);
+
+#endif /* !defined(TOR_CORE_OR_EXTENDINFO_H) */
diff --git a/src/core/or/include.am b/src/core/or/include.am
index 3626e76bed..7c42268c46 100644
--- a/src/core/or/include.am
+++ b/src/core/or/include.am
@@ -18,6 +18,7 @@ LIBTOR_APP_A_SOURCES += \
src/core/or/connection_edge.c \
src/core/or/connection_or.c \
src/core/or/dos.c \
+ src/core/or/extendinfo.c \
src/core/or/onion.c \
src/core/or/ocirc_event.c \
src/core/or/or_periodic.c \
@@ -64,11 +65,13 @@ noinst_HEADERS += \
src/core/or/destroy_cell_queue_st.h \
src/core/or/dos.h \
src/core/or/edge_connection_st.h \
+ src/core/or/extendinfo.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/lttng_circuit.inc \
src/core/or/onion.h \
src/core/or/or.h \
src/core/or/or_periodic.h \
@@ -94,3 +97,10 @@ noinst_HEADERS += \
src/core/or/tor_version_st.h \
src/core/or/var_cell_st.h \
src/core/or/versions.h
+
+if USE_TRACING_INSTRUMENTATION_LTTNG
+LIBTOR_APP_A_SOURCES += \
+ src/core/or/trace_probes_circuit.c
+noinst_HEADERS += \
+ src/core/or/trace_probes_circuit.h
+endif
diff --git a/src/core/or/lttng_circuit.inc b/src/core/or/lttng_circuit.inc
new file mode 100644
index 0000000000..0ed29f8aaf
--- /dev/null
+++ b/src/core/or/lttng_circuit.inc
@@ -0,0 +1,322 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file lttng_circuit.inc
+ * \brief LTTng tracing probe declaration for the circuit subsystem. It is in
+* this .inc file due to the non C standard syntax and the way we guard
+* the header with the LTTng specific TRACEPOINT_HEADER_MULTI_READ.
+ **/
+
+#include "orconfig.h"
+
+/* We only build the following if LTTng instrumentation has been enabled. */
+#ifdef USE_TRACING_INSTRUMENTATION_LTTNG
+
+/* The following defines are LTTng-UST specific. */
+#undef TRACEPOINT_PROVIDER
+#define TRACEPOINT_PROVIDER tor_circuit
+
+#undef TRACEPOINT_INCLUDE
+#define TRACEPOINT_INCLUDE "./src/core/or/lttng_circuit.inc"
+
+#if !defined(LTTNG_CIRCUIT_INC) || defined(TRACEPOINT_HEADER_MULTI_READ)
+#define LTTNG_CIRCUIT_INC
+
+#include <lttng/tracepoint.h>
+
+/*
+ * Circuit Purposes
+ *
+ * The following defines an enumeration of all possible circuit purposes so
+ * they appear in the trace with the define name (first parameter of
+ * ctf_enum_value) instead of the numerical value.
+ */
+TRACEPOINT_ENUM(tor_circuit, purpose,
+ TP_ENUM_VALUES(
+ /* Initializing. */
+ ctf_enum_value("<UNSET>", 0)
+
+ /* OR Side. */
+ ctf_enum_value("OR", CIRCUIT_PURPOSE_OR)
+ ctf_enum_value("OR_INTRO_POINT", CIRCUIT_PURPOSE_INTRO_POINT)
+ ctf_enum_value("OR_REND_POINT_WAITING",
+ CIRCUIT_PURPOSE_REND_POINT_WAITING)
+ ctf_enum_value("OR_REND_ESTABLISHED", CIRCUIT_PURPOSE_REND_ESTABLISHED)
+
+ /* Client Side. */
+ ctf_enum_value("C_GENERAL", CIRCUIT_PURPOSE_C_GENERAL)
+ ctf_enum_value("C_INTRODUCING", CIRCUIT_PURPOSE_C_INTRODUCING)
+ ctf_enum_value("C_INTRODUCE_ACK_WAIT",
+ CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT)
+ ctf_enum_value("C_INTRODUCE_ACKED", CIRCUIT_PURPOSE_C_INTRODUCE_ACKED)
+ ctf_enum_value("C_ESTABLISH_REND", CIRCUIT_PURPOSE_C_ESTABLISH_REND)
+ ctf_enum_value("C_REND_READY", CIRCUIT_PURPOSE_C_REND_READY)
+ ctf_enum_value("C_REND_READY_INTRO_ACKED",
+ CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED)
+ ctf_enum_value("C_REND_JOINED", CIRCUIT_PURPOSE_C_REND_JOINED)
+ ctf_enum_value("C_HSDIR_GET", CIRCUIT_PURPOSE_C_HSDIR_GET)
+
+ /* CBT and Padding. */
+ ctf_enum_value("C_MEASURE_TIMEOUT", CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT)
+ ctf_enum_value("C_CIRCUIT_PADDING", CIRCUIT_PURPOSE_C_CIRCUIT_PADDING)
+
+ /* Service Side. */
+ ctf_enum_value("S_ESTABLISH_INTRO", CIRCUIT_PURPOSE_S_ESTABLISH_INTRO)
+ ctf_enum_value("S_INTRO", CIRCUIT_PURPOSE_S_INTRO)
+ ctf_enum_value("S_CONNECT_REND", CIRCUIT_PURPOSE_S_CONNECT_REND)
+ ctf_enum_value("S_REND_JOINED", CIRCUIT_PURPOSE_S_REND_JOINED)
+ ctf_enum_value("S_HSDIR_POST", CIRCUIT_PURPOSE_S_HSDIR_POST)
+
+ /* Misc. */
+ ctf_enum_value("TESTING", CIRCUIT_PURPOSE_TESTING)
+ ctf_enum_value("CONTROLLER", CIRCUIT_PURPOSE_CONTROLLER)
+ ctf_enum_value("PATH_BIAS_TESTING", CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
+
+ /* VanGuard */
+ ctf_enum_value("HS_VANGUARDS", CIRCUIT_PURPOSE_HS_VANGUARDS)
+ )
+)
+
+/*
+ * Circuit End Reasons
+ *
+ * The following defines an enumeration of all possible circuit end reasons so
+ * they appear in the trace with the define name (first parameter of
+ * ctf_enum_value) instead of the numerical value.
+ */
+TRACEPOINT_ENUM(tor_circuit, end_reason,
+ TP_ENUM_VALUES(
+ /* Local reasons. */
+ ctf_enum_value("IP_NOW_REDUNDANT", END_CIRC_REASON_IP_NOW_REDUNDANT)
+ ctf_enum_value("MEASUREMENT_EXPIRED", END_CIRC_REASON_MEASUREMENT_EXPIRED)
+ ctf_enum_value("REASON_NOPATH", END_CIRC_REASON_NOPATH)
+ ctf_enum_value("AT_ORIGIN", END_CIRC_AT_ORIGIN)
+ ctf_enum_value("NONE", END_CIRC_REASON_NONE)
+ ctf_enum_value("TORPROTOCOL", END_CIRC_REASON_TORPROTOCOL)
+ ctf_enum_value("INTERNAL", END_CIRC_REASON_INTERNAL)
+ ctf_enum_value("REQUESTED", END_CIRC_REASON_REQUESTED)
+ ctf_enum_value("HIBERNATING", END_CIRC_REASON_HIBERNATING)
+ ctf_enum_value("RESOURCELIMIT", END_CIRC_REASON_RESOURCELIMIT)
+ ctf_enum_value("CONNECTFAILED", END_CIRC_REASON_CONNECTFAILED)
+ ctf_enum_value("OR_IDENTITY", END_CIRC_REASON_OR_IDENTITY)
+ ctf_enum_value("CHANNEL_CLOSED", END_CIRC_REASON_CHANNEL_CLOSED)
+ ctf_enum_value("FINISHED", END_CIRC_REASON_FINISHED)
+ ctf_enum_value("TIMEOUT", END_CIRC_REASON_TIMEOUT)
+ ctf_enum_value("DESTROYED", END_CIRC_REASON_DESTROYED)
+ ctf_enum_value("NOSUCHSERVICE", END_CIRC_REASON_NOSUCHSERVICE)
+
+ /* Remote reasons. */
+ ctf_enum_value("FLAG_REMOTE", END_CIRC_REASON_FLAG_REMOTE)
+ ctf_enum_value("REMOTE_TORPROTOCOL",
+ END_CIRC_REASON_FLAG_REMOTE | END_CIRC_REASON_TORPROTOCOL)
+ ctf_enum_value("REMOTE_INTERNAL",
+ END_CIRC_REASON_FLAG_REMOTE | END_CIRC_REASON_INTERNAL)
+ ctf_enum_value("REMOTE_REQUESTED",
+ END_CIRC_REASON_FLAG_REMOTE | END_CIRC_REASON_REQUESTED)
+ ctf_enum_value("REMOTE_HIBERNATING",
+ END_CIRC_REASON_FLAG_REMOTE | END_CIRC_REASON_HIBERNATING)
+ ctf_enum_value("REMOTE_RESOURCELIMIT",
+ END_CIRC_REASON_FLAG_REMOTE | END_CIRC_REASON_RESOURCELIMIT)
+ ctf_enum_value("REMOTE_CONNECTFAILED",
+ END_CIRC_REASON_FLAG_REMOTE | END_CIRC_REASON_CONNECTFAILED)
+ ctf_enum_value("REMOTE_OR_IDENTITY",
+ END_CIRC_REASON_FLAG_REMOTE | END_CIRC_REASON_OR_IDENTITY)
+ ctf_enum_value("REMOTE_CHANNEL_CLOSED",
+ END_CIRC_REASON_FLAG_REMOTE | END_CIRC_REASON_CHANNEL_CLOSED)
+ ctf_enum_value("REMOTE_FINISHED",
+ END_CIRC_REASON_FLAG_REMOTE | END_CIRC_REASON_FINISHED)
+ ctf_enum_value("REMOTE_TIMEOUT",
+ END_CIRC_REASON_FLAG_REMOTE | END_CIRC_REASON_TIMEOUT)
+ ctf_enum_value("REMOTE_DESTROYED",
+ END_CIRC_REASON_FLAG_REMOTE | END_CIRC_REASON_DESTROYED)
+ ctf_enum_value("REMOTE_NOSUCHSERVICE",
+ END_CIRC_REASON_FLAG_REMOTE | END_CIRC_REASON_NOSUCHSERVICE)
+ )
+)
+
+/*
+ * Circuit State
+ *
+ * The following defines an enumeration of all possible circuit state so they
+ * appear in the trace with the define name (first parameter of
+ * ctf_enum_value) instead of the numerical value.
+ */
+TRACEPOINT_ENUM(tor_circuit, state,
+ TP_ENUM_VALUES(
+ ctf_enum_value("BUILDING", CIRCUIT_STATE_BUILDING)
+ ctf_enum_value("ONIONSKIN_PENDING", CIRCUIT_STATE_ONIONSKIN_PENDING)
+ ctf_enum_value("CHAN_WAIT", CIRCUIT_STATE_CHAN_WAIT)
+ ctf_enum_value("GUARD_WAIT", CIRCUIT_STATE_GUARD_WAIT)
+ ctf_enum_value("OPEN", CIRCUIT_STATE_OPEN)
+ )
+)
+
+/*
+ * Event Class
+ *
+ * A tracepoint class is a class of tracepoints which share the same output
+ * event field definitions. They are then used by the
+ * TRACEPOINT_EVENT_INSTANCE() macro as a base field definition.
+ */
+
+/* Class for origin circuit. */
+TRACEPOINT_EVENT_CLASS(tor_circuit, origin_circuit_t_class,
+ TP_ARGS(const origin_circuit_t *, circ),
+ TP_FIELDS(
+ ctf_integer(uint32_t, circ_id, circ->global_identifier)
+ ctf_enum(tor_circuit, purpose, int, purpose, TO_CIRCUIT(circ)->purpose)
+ ctf_enum(tor_circuit, state, int, state, TO_CIRCUIT(circ)->state)
+ )
+)
+
+/* Class for or circuit. */
+TRACEPOINT_EVENT_CLASS(tor_circuit, or_circuit_t_class,
+ TP_ARGS(const or_circuit_t *, circ),
+ TP_FIELDS(
+ ctf_enum(tor_circuit, purpose, int, purpose, TO_CIRCUIT(circ)->purpose)
+ ctf_enum(tor_circuit, state, int, state, TO_CIRCUIT(circ)->state)
+ )
+)
+
+/*
+ * Origin circuit events.
+ *
+ * Tracepoint use the origin_circuit_t object.
+ */
+
+/* Tracepoint emitted when a new origin circuit has been created. */
+TRACEPOINT_EVENT_INSTANCE(tor_circuit, origin_circuit_t_class, new_origin,
+ TP_ARGS(const origin_circuit_t *, circ)
+)
+
+/* Tracepoint emitted when an origin circuit has opened. */
+TRACEPOINT_EVENT_INSTANCE(tor_circuit, origin_circuit_t_class, opened,
+ TP_ARGS(const origin_circuit_t *, circ)
+)
+
+/* Tracepoint emitted when an origin circuit has established. */
+TRACEPOINT_EVENT_INSTANCE(tor_circuit, origin_circuit_t_class, establish,
+ TP_ARGS(const origin_circuit_t *, circ)
+)
+
+/* Tracepoint emitted when an origin circuit has been cannibalized. */
+TRACEPOINT_EVENT_INSTANCE(tor_circuit, origin_circuit_t_class, cannibalized,
+ TP_ARGS(const origin_circuit_t *, circ)
+)
+
+/* Tracepoint emitted when an origin circuit has timed out. This is called
+ * when circuit_expire_building() as selected the circuit and is about to
+ * close it for timeout. */
+TRACEPOINT_EVENT_INSTANCE(tor_circuit, origin_circuit_t_class, timeout,
+ TP_ARGS(const origin_circuit_t *, circ)
+)
+
+/* Tracepoint emitted when an origin circuit has timed out due to idleness.
+ * This is when the circuit is closed after MaxCircuitDirtiness. */
+TRACEPOINT_EVENT_INSTANCE(tor_circuit, origin_circuit_t_class, idle_timeout,
+ TP_ARGS(const origin_circuit_t *, circ)
+)
+
+/* Tracepoint emitted when an origin circuit sends out its first onion skin. */
+TRACEPOINT_EVENT(tor_circuit, first_onion_skin,
+ TP_ARGS(const origin_circuit_t *, circ, const crypt_path_t *, hop),
+ TP_FIELDS(
+ ctf_integer(uint32_t, circ_id, circ->global_identifier)
+ ctf_enum(tor_circuit, purpose, int, purpose, TO_CIRCUIT(circ)->purpose)
+ ctf_enum(tor_circuit, state, int, state, TO_CIRCUIT(circ)->state)
+ ctf_array_hex(char, fingerprint, hop->extend_info->identity_digest,
+ DIGEST_LEN)
+ )
+)
+
+/* Tracepoint emitted when an origin circuit sends out an intermediate onion
+ * skin. */
+TRACEPOINT_EVENT(tor_circuit, intermediate_onion_skin,
+ TP_ARGS(const origin_circuit_t *, circ, const crypt_path_t *, hop),
+ TP_FIELDS(
+ ctf_integer(uint32_t, circ_id, circ->global_identifier)
+ ctf_enum(tor_circuit, purpose, int, purpose, TO_CIRCUIT(circ)->purpose)
+ ctf_enum(tor_circuit, state, int, state, TO_CIRCUIT(circ)->state)
+ ctf_array_hex(char, fingerprint, hop->extend_info->identity_digest,
+ DIGEST_LEN)
+ )
+)
+
+/*
+ * OR circuit events.
+ *
+ * Tracepoint use the or_circuit_t object.
+ */
+
+/* Tracepoint emitted when a new or circuit has been created. */
+TRACEPOINT_EVENT_INSTANCE(tor_circuit, or_circuit_t_class, new_or,
+ TP_ARGS(const or_circuit_t *, circ)
+)
+
+/*
+ * General circuit events.
+ *
+ * Tracepoint use the circuit_t object.
+ */
+
+/* Tracepoint emitted when a circuit is freed. */
+TRACEPOINT_EVENT(tor_circuit, free,
+ TP_ARGS(const circuit_t *, circ),
+ TP_FIELDS(
+ ctf_integer(uint32_t, circ_id,
+ (CIRCUIT_IS_ORIGIN(circ) ?
+ TO_ORIGIN_CIRCUIT(circ)->global_identifier : 0))
+ ctf_enum(tor_circuit, purpose, int, purpose, circ->purpose)
+ ctf_enum(tor_circuit, state, int, state, circ->state)
+ )
+)
+
+/* Tracepoint emitted when a circuit is marked for close. */
+TRACEPOINT_EVENT(tor_circuit, mark_for_close,
+ TP_ARGS(const circuit_t *, circ),
+ TP_FIELDS(
+ ctf_integer(uint32_t, circ_id,
+ (CIRCUIT_IS_ORIGIN(circ) ?
+ TO_ORIGIN_CIRCUIT(circ)->global_identifier : 0))
+ ctf_enum(tor_circuit, purpose, int, purpose, circ->purpose)
+ ctf_enum(tor_circuit, state, int, state, circ->state)
+ ctf_enum(tor_circuit, end_reason, int, close_reason,
+ circ->marked_for_close_reason)
+ ctf_enum(tor_circuit, end_reason, int, orig_close_reason,
+ circ->marked_for_close_orig_reason)
+ )
+)
+
+/* Tracepoint emitted when a circuit changes purpose. */
+TRACEPOINT_EVENT(tor_circuit, change_purpose,
+ TP_ARGS(const circuit_t *, circ, int, old_purpose, int, new_purpose),
+ TP_FIELDS(
+ ctf_integer(uint32_t, circ_id,
+ (CIRCUIT_IS_ORIGIN(circ) ?
+ TO_ORIGIN_CIRCUIT(circ)->global_identifier : 0))
+ ctf_enum(tor_circuit, state, int, state, circ->state)
+ ctf_enum(tor_circuit, purpose, int, purpose, old_purpose)
+ ctf_enum(tor_circuit, purpose, int, new, new_purpose)
+ )
+)
+
+/* Tracepoint emitted when a circuit changes state. */
+TRACEPOINT_EVENT(tor_circuit, change_state,
+ TP_ARGS(const circuit_t *, circ, int, old_state, int, new_state),
+ TP_FIELDS(
+ ctf_integer(uint32_t, circ_id,
+ (CIRCUIT_IS_ORIGIN(circ) ?
+ TO_ORIGIN_CIRCUIT(circ)->global_identifier : 0))
+ ctf_enum(tor_circuit, purpose, int, purpose, circ->purpose)
+ ctf_enum(tor_circuit, state, int, old, old_state)
+ ctf_enum(tor_circuit, state, int, new, new_state)
+ )
+)
+
+#endif /* LTTNG_CIRCUIT_INC || TRACEPOINT_HEADER_MULTI_READ */
+
+/* Must be included after the probes declaration. */
+#include <lttng/tracepoint-event.h>
+
+#endif /* USE_TRACING_INSTRUMENTATION_LTTNG */
diff --git a/src/core/or/onion.h b/src/core/or/onion.h
index 256f0a3f31..0dac21ab6b 100644
--- a/src/core/or/onion.h
+++ b/src/core/or/onion.h
@@ -48,10 +48,9 @@ typedef struct extend_cell_t {
uint8_t cell_type;
/** An IPv4 address and port for the node we're connecting to. */
tor_addr_port_t orport_ipv4;
- /** An IPv6 address and port for the node we're connecting to. Not currently
- * used. */
+ /** An IPv6 address and port for the node we're connecting to. */
tor_addr_port_t orport_ipv6;
- /** Identity fingerprint of the node we're conecting to.*/
+ /** Identity fingerprint of the node we're connecting to.*/
uint8_t node_id[DIGEST_LEN];
/** Ed25519 public identity key. Zero if not set. */
struct ed25519_public_key_t ed_pubkey;
diff --git a/src/core/or/or.h b/src/core/or/or.h
index 8758a2ec6f..d80c41371e 100644
--- a/src/core/or/or.h
+++ b/src/core/or/or.h
@@ -816,6 +816,18 @@ typedef struct protover_summary_flags_t {
* accept EXTEND2 cells. This requires Relay=2. */
unsigned int supports_extend2_cells:1;
+ /** True iff this router has a version or protocol list that allows it to
+ * accept IPv6 connections. This requires Relay=2 or Relay=3. */
+ unsigned int supports_accepting_ipv6_extends:1;
+
+ /** True iff this router has a version or protocol list that allows it to
+ * initiate IPv6 connections. This requires Relay=3. */
+ unsigned int supports_initiating_ipv6_extends:1;
+
+ /** True iff this router has a version or protocol list that allows it to
+ * consider IPv6 connections canonical. This requires Relay=3. */
+ unsigned int supports_canonical_ipv6_conns:1;
+
/** True iff this router has a protocol list that allows it to negotiate
* ed25519 identity keys on a link handshake with us. This
* requires LinkAuth=3. */
@@ -831,6 +843,10 @@ typedef struct protover_summary_flags_t {
* the v3 protocol detailed in proposal 224. This requires HSIntro=4. */
unsigned int supports_ed25519_hs_intro : 1;
+ /** True iff this router has a protocol list that allows it to support the
+ * ESTABLISH_INTRO DoS cell extension. Requires HSIntro=5. */
+ unsigned int supports_establish_intro_dos_extension : 1;
+
/** True iff this router has a protocol list that allows it to be an hidden
* service directory supporting version 3 as seen in proposal 224. This
* requires HSDir=2. */
@@ -842,12 +858,9 @@ typedef struct protover_summary_flags_t {
unsigned int supports_v3_rendezvous_point: 1;
/** True iff this router has a protocol list that allows clients to
- * negotiate hs circuit setup padding. Requires Padding>=2. */
+ * negotiate hs circuit setup padding. Requires Padding=2. */
unsigned int supports_hs_setup_padding : 1;
- /** True iff this router has a protocol list that allows it to support the
- * ESTABLISH_INTRO DoS cell extension. Requires HSIntro>=5. */
- unsigned int supports_establish_intro_dos_extension : 1;
} protover_summary_flags_t;
typedef struct routerinfo_t routerinfo_t;
diff --git a/src/core/or/or_connection_st.h b/src/core/or/or_connection_st.h
index 92956c2847..d99aaaefad 100644
--- a/src/core/or/or_connection_st.h
+++ b/src/core/or/or_connection_st.h
@@ -31,7 +31,7 @@ struct or_connection_t {
/** This is the ClientHash value we expect to receive from the
* client during the Extended ORPort authentication protocol. We
* compute it upon receiving the ClientNoce from the client, and we
- * compare it with the acual ClientHash value sent by the
+ * compare it with the actual ClientHash value sent by the
* client. */
char *ext_or_auth_correct_client_hash;
/** String carrying the name of the pluggable transport
@@ -49,10 +49,19 @@ struct or_connection_t {
/* Channel using this connection */
channel_tls_t *chan;
- tor_addr_t real_addr; /**< The actual address that this connection came from
- * or went to. The <b>addr</b> field is prone to
- * getting overridden by the address from the router
- * descriptor matching <b>identity_digest</b>. */
+ /**
+ * The "canonical" address and port for this relay's ORPort, if this is
+ * a known relay.
+ *
+ * An ORPort is "canonical" in this sense only if it is the same ORPort
+ * that is listed for this identity in the consensus we have.
+ *
+ * This field may be set on outbound connections for _any_ relay, and on
+ * inbound connections after authentication. If we don't know the relay's
+ * identity, or if we don't have the relay's identity in our consensus, we
+ * leave this address as UNSPEC.
+ **/
+ tor_addr_port_t canonical_orport;
/** Should this connection be used for extending circuits to the server
* matching the <b>identity_digest</b> field? Set to true if we're pretty
@@ -65,6 +74,11 @@ struct or_connection_t {
unsigned int is_outgoing:1;
unsigned int proxy_type:3; /**< One of PROXY_NONE...PROXY_HAPROXY */
unsigned int wide_circ_ids:1;
+ /** True iff a failure on this connection indicates a possible
+ * bootstrapping problem. We set this as true if we notice that this
+ * connection could handle a pending origin circuit, or if we launch it to
+ * handle an origin circuit. */
+ unsigned int potentially_used_for_bootstrapping:1;
/** True iff this connection has had its bootstrap failure logged with
* control_event_bootstrap_problem. */
unsigned int have_noted_bootstrap_problem:1;
diff --git a/src/core/or/origin_circuit_st.h b/src/core/or/origin_circuit_st.h
index 79e250cd59..c40e84aed8 100644
--- a/src/core/or/origin_circuit_st.h
+++ b/src/core/or/origin_circuit_st.h
@@ -54,7 +54,7 @@ enum path_state_t {
/** Did any SOCKS streams or hidserv introductions actually succeed on
* this circuit?
*
- * If any streams detatch/fail from this circuit, the code transitions
+ * If any streams detach/fail from this circuit, the code transitions
* the circuit back to PATH_STATE_USE_ATTEMPTED to ensure we probe. See
* pathbias_mark_use_rollback() for that.
*/
@@ -171,6 +171,18 @@ struct origin_circuit_t {
unsigned padding_negotiation_failed : 1;
/**
+ * If this flag is set, then a controller chose the first hop of this
+ * circuit's path, and it's okay to ignore checks that we'd usually do
+ * on this circuit's first hop.
+ *
+ * This flag is distinct from the CIRCUIT_PURPOSE_CONTROLLER purpose: the
+ * purpose indicates _what tor can use the circuit for_. Controller-created
+ * circuits can still have the CIRCUIT_PURPOSE_GENERAL purpose if Tor is
+ * allowed to attach streams to them.
+ */
+ unsigned first_hop_from_controller : 1;
+
+ /**
* Tristate variable to guard against pathbias miscounting
* due to circuit purpose transitions changing the decision
* of pathbias_should_count(). This variable is informational
diff --git a/src/core/or/policies.c b/src/core/or/policies.c
index 2bf2dc7005..5f578d9b1a 100644
--- a/src/core/or/policies.c
+++ b/src/core/or/policies.c
@@ -48,6 +48,8 @@
static smartlist_t *socks_policy = NULL;
/** Policy that addresses for incoming directory connections must match. */
static smartlist_t *dir_policy = NULL;
+/** Policy for incoming MetricsPort connections that must match. */
+static smartlist_t *metrics_policy = NULL;
/** Policy that addresses for incoming router descriptors must match in order
* to be published by us. */
static smartlist_t *authdir_reject_policy = NULL;
@@ -311,7 +313,7 @@ parse_reachable_addresses(void)
"ReachableAddresses, ReachableORAddresses, or "
"ReachableDirAddresses reject all IPv4 addresses. "
"Tor will not connect using IPv4.");
- } else if (fascist_firewall_use_ipv6(options)
+ } else if (reachable_addr_use_ipv6(options)
&& (policy_is_reject_star(reachable_or_addr_policy, AF_INET6, 0)
|| policy_is_reject_star(reachable_dir_addr_policy, AF_INET6, 0))) {
log_warn(LD_CONFIG, "You have configured tor to use or prefer IPv6 "
@@ -389,19 +391,6 @@ addr_policy_permits_tor_addr(const tor_addr_t *addr, uint16_t port,
}
}
-/** Return true iff <b> policy</b> (possibly NULL) will allow a connection to
- * <b>addr</b>:<b>port</b>. <b>addr</b> is an IPv4 address given in host
- * order. */
-/* XXXX deprecate when possible. */
-static int
-addr_policy_permits_address(uint32_t addr, uint16_t port,
- smartlist_t *policy)
-{
- tor_addr_t a;
- tor_addr_from_ipv4h(&a, addr);
- return addr_policy_permits_tor_addr(&a, port, policy);
-}
-
/** Return true iff we think our firewall will let us make a connection to
* addr:port.
*
@@ -412,12 +401,12 @@ addr_policy_permits_address(uint32_t addr, uint16_t port,
* - if ClientUseIPv4 is 0, or
* if pref_only and pref_ipv6 are both true;
* - return false for all IPv6 addresses:
- * - if fascist_firewall_use_ipv6() is 0, or
+ * - if reachable_addr_use_ipv6() is 0, or
* - if pref_only is true and pref_ipv6 is false.
*
* Return false if addr is NULL or tor_addr_is_null(), or if port is 0. */
STATIC int
-fascist_firewall_allows_address(const tor_addr_t *addr,
+reachable_addr_allows(const tor_addr_t *addr,
uint16_t port,
smartlist_t *firewall_policy,
int pref_only, int pref_ipv6)
@@ -440,7 +429,7 @@ fascist_firewall_allows_address(const tor_addr_t *addr,
/* Clients and Servers won't use IPv6 unless it's enabled (and in most
* cases, IPv6 must also be preferred before it will be used). */
if (tor_addr_family(addr) == AF_INET6 &&
- (!fascist_firewall_use_ipv6(options) || (pref_only && !pref_ipv6))) {
+ (!reachable_addr_use_ipv6(options) || (pref_only && !pref_ipv6))) {
return 0;
}
@@ -456,7 +445,7 @@ fascist_firewall_allows_address(const tor_addr_t *addr,
* port: it supports bridge client per-node IPv6 preferences.
*/
int
-fascist_firewall_use_ipv6(const or_options_t *options)
+reachable_addr_use_ipv6(const or_options_t *options)
{
/* Clients use IPv6 if it's set, or they use bridges, or they don't use
* IPv4, or they prefer it.
@@ -471,7 +460,7 @@ fascist_firewall_use_ipv6(const or_options_t *options)
* If we're unsure, return -1, otherwise, return 1 for IPv6 and 0 for IPv4.
*/
static int
-fascist_firewall_prefer_ipv6_impl(const or_options_t *options)
+reachable_addr_prefer_ipv6_impl(const or_options_t *options)
{
/*
Cheap implementation of config options ClientUseIPv4 & ClientUseIPv6 --
@@ -479,7 +468,7 @@ fascist_firewall_prefer_ipv6_impl(const or_options_t *options)
If IPv4 is disabled, use IPv6.
*/
- if (server_mode(options) || !fascist_firewall_use_ipv6(options)) {
+ if (server_mode(options) || !reachable_addr_use_ipv6(options)) {
return 0;
}
@@ -495,9 +484,9 @@ fascist_firewall_prefer_ipv6_impl(const or_options_t *options)
* per-node IPv6 preferences.
*/
int
-fascist_firewall_prefer_ipv6_orport(const or_options_t *options)
+reachable_addr_prefer_ipv6_orport(const or_options_t *options)
{
- int pref_ipv6 = fascist_firewall_prefer_ipv6_impl(options);
+ int pref_ipv6 = reachable_addr_prefer_ipv6_impl(options);
if (pref_ipv6 >= 0) {
return pref_ipv6;
@@ -517,9 +506,9 @@ fascist_firewall_prefer_ipv6_orport(const or_options_t *options)
* preferences. There's no reason to use it instead of this function.)
*/
int
-fascist_firewall_prefer_ipv6_dirport(const or_options_t *options)
+reachable_addr_prefer_ipv6_dirport(const or_options_t *options)
{
- int pref_ipv6 = fascist_firewall_prefer_ipv6_impl(options);
+ int pref_ipv6 = reachable_addr_prefer_ipv6_impl(options);
if (pref_ipv6 >= 0) {
return pref_ipv6;
@@ -541,16 +530,16 @@ fascist_firewall_prefer_ipv6_dirport(const or_options_t *options)
* If pref_only is false, ignore pref_ipv6, and return true if addr is allowed.
*/
int
-fascist_firewall_allows_address_addr(const tor_addr_t *addr, uint16_t port,
+reachable_addr_allows_addr(const tor_addr_t *addr, uint16_t port,
firewall_connection_t fw_connection,
int pref_only, int pref_ipv6)
{
if (fw_connection == FIREWALL_OR_CONNECTION) {
- return fascist_firewall_allows_address(addr, port,
+ return reachable_addr_allows(addr, port,
reachable_or_addr_policy,
pref_only, pref_ipv6);
} else if (fw_connection == FIREWALL_DIR_CONNECTION) {
- return fascist_firewall_allows_address(addr, port,
+ return reachable_addr_allows(addr, port,
reachable_dir_addr_policy,
pref_only, pref_ipv6);
} else {
@@ -563,34 +552,15 @@ fascist_firewall_allows_address_addr(const tor_addr_t *addr, uint16_t port,
/** Return true iff we think our firewall will let us make a connection to
* addr:port (ap). Uses ReachableORAddresses or ReachableDirAddresses based on
* fw_connection.
- * pref_only and pref_ipv6 work as in fascist_firewall_allows_address_addr().
+ * pref_only and pref_ipv6 work as in reachable_addr_allows_addr().
*/
static int
-fascist_firewall_allows_address_ap(const tor_addr_port_t *ap,
+reachable_addr_allows_ap(const tor_addr_port_t *ap,
firewall_connection_t fw_connection,
int pref_only, int pref_ipv6)
{
tor_assert(ap);
- return fascist_firewall_allows_address_addr(&ap->addr, ap->port,
- fw_connection, pref_only,
- pref_ipv6);
-}
-
-/* Return true iff we think our firewall will let us make a connection to
- * ipv4h_or_addr:ipv4_or_port. ipv4h_or_addr is interpreted in host order.
- * Uses ReachableORAddresses or ReachableDirAddresses based on
- * fw_connection.
- * pref_only and pref_ipv6 work as in fascist_firewall_allows_address_addr().
- */
-static int
-fascist_firewall_allows_address_ipv4h(uint32_t ipv4h_or_addr,
- uint16_t ipv4_or_port,
- firewall_connection_t fw_connection,
- int pref_only, int pref_ipv6)
-{
- tor_addr_t ipv4_or_addr;
- tor_addr_from_ipv4h(&ipv4_or_addr, ipv4h_or_addr);
- return fascist_firewall_allows_address_addr(&ipv4_or_addr, ipv4_or_port,
+ return reachable_addr_allows_addr(&ap->addr, ap->port,
fw_connection, pref_only,
pref_ipv6);
}
@@ -599,17 +569,17 @@ fascist_firewall_allows_address_ipv4h(uint32_t ipv4h_or_addr,
* ipv4h_addr/ipv6_addr. Uses ipv4_orport/ipv6_orport/ReachableORAddresses or
* ipv4_dirport/ipv6_dirport/ReachableDirAddresses based on IPv4/IPv6 and
* <b>fw_connection</b>.
- * pref_only and pref_ipv6 work as in fascist_firewall_allows_address_addr().
+ * pref_only and pref_ipv6 work as in reachable_addr_allows_addr().
*/
static int
-fascist_firewall_allows_base(uint32_t ipv4h_addr, uint16_t ipv4_orport,
+reachable_addr_allows_base(const tor_addr_t *ipv4_addr, uint16_t ipv4_orport,
uint16_t ipv4_dirport,
const tor_addr_t *ipv6_addr, uint16_t ipv6_orport,
uint16_t ipv6_dirport,
firewall_connection_t fw_connection,
int pref_only, int pref_ipv6)
{
- if (fascist_firewall_allows_address_ipv4h(ipv4h_addr,
+ if (reachable_addr_allows_addr(ipv4_addr,
(fw_connection == FIREWALL_OR_CONNECTION
? ipv4_orport
: ipv4_dirport),
@@ -618,7 +588,7 @@ fascist_firewall_allows_base(uint32_t ipv4h_addr, uint16_t ipv4_orport,
return 1;
}
- if (fascist_firewall_allows_address_addr(ipv6_addr,
+ if (reachable_addr_allows_addr(ipv6_addr,
(fw_connection == FIREWALL_OR_CONNECTION
? ipv6_orport
: ipv6_dirport),
@@ -630,9 +600,9 @@ fascist_firewall_allows_base(uint32_t ipv4h_addr, uint16_t ipv4_orport,
return 0;
}
-/** Like fascist_firewall_allows_base(), but takes ri. */
+/** Like reachable_addr_allows_base(), but takes ri. */
static int
-fascist_firewall_allows_ri_impl(const routerinfo_t *ri,
+reachable_addr_allows_ri_impl(const routerinfo_t *ri,
firewall_connection_t fw_connection,
int pref_only, int pref_ipv6)
{
@@ -641,15 +611,15 @@ fascist_firewall_allows_ri_impl(const routerinfo_t *ri,
}
/* Assume IPv4 and IPv6 DirPorts are the same */
- return fascist_firewall_allows_base(ri->addr, ri->or_port, ri->dir_port,
- &ri->ipv6_addr, ri->ipv6_orport,
- ri->dir_port, fw_connection, pref_only,
- pref_ipv6);
+ return reachable_addr_allows_base(&ri->ipv4_addr, ri->ipv4_orport,
+ ri->ipv4_dirport, &ri->ipv6_addr,
+ ri->ipv6_orport, ri->ipv4_dirport,
+ fw_connection, pref_only, pref_ipv6);
}
-/** Like fascist_firewall_allows_rs, but takes pref_ipv6. */
+/** Like reachable_addr_allows_rs, but takes pref_ipv6. */
static int
-fascist_firewall_allows_rs_impl(const routerstatus_t *rs,
+reachable_addr_allows_rs_impl(const routerstatus_t *rs,
firewall_connection_t fw_connection,
int pref_only, int pref_ipv6)
{
@@ -658,20 +628,20 @@ fascist_firewall_allows_rs_impl(const routerstatus_t *rs,
}
/* Assume IPv4 and IPv6 DirPorts are the same */
- return fascist_firewall_allows_base(rs->addr, rs->or_port, rs->dir_port,
- &rs->ipv6_addr, rs->ipv6_orport,
- rs->dir_port, fw_connection, pref_only,
- pref_ipv6);
+ return reachable_addr_allows_base(&rs->ipv4_addr, rs->ipv4_orport,
+ rs->ipv4_dirport, &rs->ipv6_addr,
+ rs->ipv6_orport, rs->ipv4_dirport,
+ fw_connection, pref_only, pref_ipv6);
}
-/** Like fascist_firewall_allows_base(), but takes rs.
+/** Like reachable_addr_allows_base(), but takes rs.
* When rs is a fake_status from a dir_server_t, it can have a reachable
* address, even when the corresponding node does not.
* nodes can be missing addresses when there's no consensus (IPv4 and IPv6),
* or when there is a microdescriptor consensus, but no microdescriptors
* (microdescriptors have IPv6, the microdesc consensus does not). */
int
-fascist_firewall_allows_rs(const routerstatus_t *rs,
+reachable_addr_allows_rs(const routerstatus_t *rs,
firewall_connection_t fw_connection, int pref_only)
{
if (!rs) {
@@ -682,20 +652,20 @@ fascist_firewall_allows_rs(const routerstatus_t *rs,
* generic IPv6 preference instead. */
const or_options_t *options = get_options();
int pref_ipv6 = (fw_connection == FIREWALL_OR_CONNECTION
- ? fascist_firewall_prefer_ipv6_orport(options)
- : fascist_firewall_prefer_ipv6_dirport(options));
+ ? reachable_addr_prefer_ipv6_orport(options)
+ : reachable_addr_prefer_ipv6_dirport(options));
- return fascist_firewall_allows_rs_impl(rs, fw_connection, pref_only,
+ return reachable_addr_allows_rs_impl(rs, fw_connection, pref_only,
pref_ipv6);
}
/** Return true iff we think our firewall will let us make a connection to
* ipv6_addr:ipv6_orport based on ReachableORAddresses.
* If <b>fw_connection</b> is FIREWALL_DIR_CONNECTION, returns 0.
- * pref_only and pref_ipv6 work as in fascist_firewall_allows_address_addr().
+ * pref_only and pref_ipv6 work as in reachable_addr_allows_addr().
*/
static int
-fascist_firewall_allows_md_impl(const microdesc_t *md,
+reachable_addr_allows_md_impl(const microdesc_t *md,
firewall_connection_t fw_connection,
int pref_only, int pref_ipv6)
{
@@ -709,15 +679,15 @@ fascist_firewall_allows_md_impl(const microdesc_t *md,
}
/* Also can't check IPv4, doesn't have that either */
- return fascist_firewall_allows_address_addr(&md->ipv6_addr, md->ipv6_orport,
+ return reachable_addr_allows_addr(&md->ipv6_addr, md->ipv6_orport,
fw_connection, pref_only,
pref_ipv6);
}
-/** Like fascist_firewall_allows_base(), but takes node, and looks up pref_ipv6
+/** Like reachable_addr_allows_base(), but takes node, and looks up pref_ipv6
* from node_ipv6_or/dir_preferred(). */
int
-fascist_firewall_allows_node(const node_t *node,
+reachable_addr_allows_node(const node_t *node,
firewall_connection_t fw_connection,
int pref_only)
{
@@ -733,15 +703,15 @@ fascist_firewall_allows_node(const node_t *node,
/* Sometimes, the rs is missing the IPv6 address info, and we need to go
* all the way to the md */
- if (node->ri && fascist_firewall_allows_ri_impl(node->ri, fw_connection,
+ if (node->ri && reachable_addr_allows_ri_impl(node->ri, fw_connection,
pref_only, pref_ipv6)) {
return 1;
- } else if (node->rs && fascist_firewall_allows_rs_impl(node->rs,
+ } else if (node->rs && reachable_addr_allows_rs_impl(node->rs,
fw_connection,
pref_only,
pref_ipv6)) {
return 1;
- } else if (node->md && fascist_firewall_allows_md_impl(node->md,
+ } else if (node->md && reachable_addr_allows_md_impl(node->md,
fw_connection,
pref_only,
pref_ipv6)) {
@@ -753,9 +723,9 @@ fascist_firewall_allows_node(const node_t *node,
}
}
-/** Like fascist_firewall_allows_rs(), but takes ds. */
+/** Like reachable_addr_allows_rs(), but takes ds. */
int
-fascist_firewall_allows_dir_server(const dir_server_t *ds,
+reachable_addr_allows_dir_server(const dir_server_t *ds,
firewall_connection_t fw_connection,
int pref_only)
{
@@ -766,8 +736,8 @@ fascist_firewall_allows_dir_server(const dir_server_t *ds,
/* A dir_server_t always has a fake_status. As long as it has the same
* addresses/ports in both fake_status and dir_server_t, this works fine.
* (See #17867.)
- * fascist_firewall_allows_rs only checks the addresses in fake_status. */
- return fascist_firewall_allows_rs(&ds->fake_status, fw_connection,
+ * reachable_addr_allows_rs only checks the addresses in fake_status. */
+ return reachable_addr_allows_rs(&ds->fake_status, fw_connection,
pref_only);
}
@@ -775,10 +745,10 @@ fascist_firewall_allows_dir_server(const dir_server_t *ds,
* choose one based on want_a and return it.
* Otherwise, return whichever is allowed.
* Otherwise, return NULL.
- * pref_only and pref_ipv6 work as in fascist_firewall_allows_address_addr().
+ * pref_only and pref_ipv6 work as in reachable_addr_allows_addr().
*/
static const tor_addr_port_t *
-fascist_firewall_choose_address_impl(const tor_addr_port_t *a,
+reachable_addr_choose_impl(const tor_addr_port_t *a,
const tor_addr_port_t *b,
int want_a,
firewall_connection_t fw_connection,
@@ -787,12 +757,12 @@ fascist_firewall_choose_address_impl(const tor_addr_port_t *a,
const tor_addr_port_t *use_a = NULL;
const tor_addr_port_t *use_b = NULL;
- if (fascist_firewall_allows_address_ap(a, fw_connection, pref_only,
+ if (reachable_addr_allows_ap(a, fw_connection, pref_only,
pref_ipv6)) {
use_a = a;
}
- if (fascist_firewall_allows_address_ap(b, fw_connection, pref_only,
+ if (reachable_addr_allows_ap(b, fw_connection, pref_only,
pref_ipv6)) {
use_b = b;
}
@@ -816,13 +786,13 @@ fascist_firewall_choose_address_impl(const tor_addr_port_t *a,
* - Otherwise, return whichever is preferred.
* Otherwise, return NULL. */
STATIC const tor_addr_port_t *
-fascist_firewall_choose_address(const tor_addr_port_t *a,
+reachable_addr_choose(const tor_addr_port_t *a,
const tor_addr_port_t *b,
int want_a,
firewall_connection_t fw_connection,
int pref_only, int pref_ipv6)
{
- const tor_addr_port_t *pref = fascist_firewall_choose_address_impl(
+ const tor_addr_port_t *pref = reachable_addr_choose_impl(
a, b, want_a,
fw_connection,
1, pref_ipv6);
@@ -834,7 +804,7 @@ fascist_firewall_choose_address(const tor_addr_port_t *a,
} else {
/* If there's no preferred address, and we can return addresses that are
* not preferred, use an address that's allowed */
- return fascist_firewall_choose_address_impl(a, b, want_a, fw_connection,
+ return reachable_addr_choose_impl(a, b, want_a, fw_connection,
0, pref_ipv6);
}
}
@@ -849,7 +819,7 @@ fascist_firewall_choose_address(const tor_addr_port_t *a,
* If both addresses could be chosen (they are both preferred or both allowed)
* choose IPv6 if pref_ipv6 is true, otherwise choose IPv4. */
static void
-fascist_firewall_choose_address_base(const tor_addr_t *ipv4_addr,
+reachable_addr_choose_base(const tor_addr_t *ipv4_addr,
uint16_t ipv4_orport,
uint16_t ipv4_dirport,
const tor_addr_t *ipv6_addr,
@@ -881,7 +851,7 @@ fascist_firewall_choose_address_base(const tor_addr_t *ipv4_addr,
? ipv6_orport
: ipv6_dirport);
- result = fascist_firewall_choose_address(&ipv4_ap, &ipv6_ap,
+ result = reachable_addr_choose(&ipv4_ap, &ipv6_ap,
want_ipv4,
fw_connection, pref_only,
pref_ipv6);
@@ -892,41 +862,13 @@ fascist_firewall_choose_address_base(const tor_addr_t *ipv4_addr,
}
}
-/** Like fascist_firewall_choose_address_base(), but takes a host-order IPv4
- * address as the first parameter. */
-static void
-fascist_firewall_choose_address_ipv4h(uint32_t ipv4h_addr,
- uint16_t ipv4_orport,
- uint16_t ipv4_dirport,
- const tor_addr_t *ipv6_addr,
- uint16_t ipv6_orport,
- uint16_t ipv6_dirport,
- firewall_connection_t fw_connection,
- int pref_only,
- int pref_ipv6,
- tor_addr_port_t* ap)
-{
- tor_addr_t ipv4_addr;
- tor_addr_from_ipv4h(&ipv4_addr, ipv4h_addr);
- tor_assert(ap);
-
- tor_addr_make_null(&ap->addr, AF_UNSPEC);
- ap->port = 0;
-
- fascist_firewall_choose_address_base(&ipv4_addr, ipv4_orport,
- ipv4_dirport, ipv6_addr,
- ipv6_orport, ipv6_dirport,
- fw_connection, pref_only,
- pref_ipv6, ap);
-}
-
-/** Like fascist_firewall_choose_address_base(), but takes <b>rs</b>.
+/** Like reachable_addr_choose_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
* correspond to a bridge client's bridge.
*/
void
-fascist_firewall_choose_address_rs(const routerstatus_t *rs,
+reachable_addr_choose_from_rs(const routerstatus_t *rs,
firewall_connection_t fw_connection,
int pref_only, tor_addr_port_t* ap)
{
@@ -943,30 +885,29 @@ fascist_firewall_choose_address_rs(const routerstatus_t *rs,
const node_t *node = node_get_by_id(rs->identity_digest);
if (node) {
- fascist_firewall_choose_address_node(node, fw_connection, pref_only, ap);
+ reachable_addr_choose_from_node(node, fw_connection, pref_only, ap);
} else {
/* There's no node-specific IPv6 preference, so use the generic IPv6
* preference instead. */
int pref_ipv6 = (fw_connection == FIREWALL_OR_CONNECTION
- ? fascist_firewall_prefer_ipv6_orport(options)
- : fascist_firewall_prefer_ipv6_dirport(options));
+ ? reachable_addr_prefer_ipv6_orport(options)
+ : reachable_addr_prefer_ipv6_dirport(options));
- /* Assume IPv4 and IPv6 DirPorts are the same.
- * Assume the IPv6 OR and Dir addresses are the same. */
- fascist_firewall_choose_address_ipv4h(rs->addr, rs->or_port, rs->dir_port,
- &rs->ipv6_addr, rs->ipv6_orport,
- rs->dir_port, fw_connection,
- pref_only, pref_ipv6, ap);
+ reachable_addr_choose_base(&rs->ipv4_addr, rs->ipv4_orport,
+ rs->ipv4_dirport, &rs->ipv6_addr,
+ rs->ipv6_orport, rs->ipv4_dirport,
+ fw_connection, pref_only, pref_ipv6,
+ ap);
}
}
-/** Like fascist_firewall_choose_address_base(), but takes in a smartlist
+/** Like reachable_addr_choose_base(), but takes in a smartlist
* <b>lspecs</b> consisting of one or more link specifiers. We assume
* fw_connection is FIREWALL_OR_CONNECTION as link specifiers cannot
* contain DirPorts.
*/
void
-fascist_firewall_choose_address_ls(const smartlist_t *lspecs,
+reachable_addr_choose_from_ls(const smartlist_t *lspecs,
int pref_only, tor_addr_port_t* ap)
{
int have_v4 = 0, have_v6 = 0;
@@ -1028,20 +969,20 @@ fascist_firewall_choose_address_ls(const smartlist_t *lspecs,
/* Here, don't check for DirPorts as link specifiers are only used for
* ORPorts. */
const or_options_t *options = get_options();
- int pref_ipv6 = fascist_firewall_prefer_ipv6_orport(options);
+ int pref_ipv6 = reachable_addr_prefer_ipv6_orport(options);
/* Assume that the DirPorts are zero as link specifiers only use ORPorts. */
- fascist_firewall_choose_address_base(&addr_v4, port_v4, 0,
+ reachable_addr_choose_base(&addr_v4, port_v4, 0,
&addr_v6, port_v6, 0,
FIREWALL_OR_CONNECTION,
pref_only, pref_ipv6,
ap);
}
-/** Like fascist_firewall_choose_address_base(), but takes <b>node</b>, and
+/** Like reachable_addr_choose_base(), but takes <b>node</b>, and
* looks up the node's IPv6 preference rather than taking an argument
* for pref_ipv6. */
void
-fascist_firewall_choose_address_node(const node_t *node,
+reachable_addr_choose_from_node(const node_t *node,
firewall_connection_t fw_connection,
int pref_only, tor_addr_port_t *ap)
{
@@ -1071,16 +1012,16 @@ fascist_firewall_choose_address_node(const node_t *node,
node_get_pref_ipv6_dirport(node, &ipv6_dir_ap);
/* Assume the IPv6 OR and Dir addresses are the same. */
- fascist_firewall_choose_address_base(&ipv4_or_ap.addr, ipv4_or_ap.port,
+ reachable_addr_choose_base(&ipv4_or_ap.addr, ipv4_or_ap.port,
ipv4_dir_ap.port, &ipv6_or_ap.addr,
ipv6_or_ap.port, ipv6_dir_ap.port,
fw_connection, pref_only,
pref_ipv6_node, ap);
}
-/** Like fascist_firewall_choose_address_rs(), but takes <b>ds</b>. */
+/** Like reachable_addr_choose_from_rs(), but takes <b>ds</b>. */
void
-fascist_firewall_choose_address_dir_server(const dir_server_t *ds,
+reachable_addr_choose_from_dir_server(const dir_server_t *ds,
firewall_connection_t fw_connection,
int pref_only,
tor_addr_port_t *ap)
@@ -1097,9 +1038,9 @@ fascist_firewall_choose_address_dir_server(const dir_server_t *ds,
/* A dir_server_t always has a fake_status. As long as it has the same
* addresses/ports in both fake_status and dir_server_t, this works fine.
* (See #17867.)
- * This function relies on fascist_firewall_choose_address_rs looking up the
+ * This function relies on reachable_addr_choose_from_rs looking up the
* node if it can, because that will get the latest info for the relay. */
- fascist_firewall_choose_address_rs(&ds->fake_status, fw_connection,
+ reachable_addr_choose_from_rs(&ds->fake_status, fw_connection,
pref_only, ap);
}
@@ -1121,20 +1062,26 @@ socks_policy_permits_address(const tor_addr_t *addr)
return addr_policy_permits_tor_addr(addr, 1, socks_policy);
}
+/** Return 1 if <b>addr</b> is permitted to connect to our metrics port,
+ * based on <b>socks_policy</b>. Else return 0.
+ */
+int
+metrics_policy_permits_address(const tor_addr_t *addr)
+{
+ return addr_policy_permits_tor_addr(addr, 1, metrics_policy);
+}
+
/** Return true iff the address <b>addr</b> is in a country listed in the
* case-insensitive list of country codes <b>cc_list</b>. */
static int
-addr_is_in_cc_list(uint32_t addr, const smartlist_t *cc_list)
+addr_is_in_cc_list(const tor_addr_t *addr, const smartlist_t *cc_list)
{
country_t country;
const char *name;
- tor_addr_t tar;
if (!cc_list)
return 0;
- /* XXXXipv6 */
- tor_addr_from_ipv4h(&tar, addr);
- country = geoip_get_country_by_addr(&tar);
+ country = geoip_get_country_by_addr(addr);
name = geoip_get_country_name(country);
return smartlist_contains_string_case(cc_list, name);
}
@@ -1143,9 +1090,9 @@ addr_is_in_cc_list(uint32_t addr, const smartlist_t *cc_list)
* directory, based on <b>authdir_reject_policy</b>. Else return 0.
*/
int
-authdir_policy_permits_address(uint32_t addr, uint16_t port)
+authdir_policy_permits_address(const tor_addr_t *addr, uint16_t port)
{
- if (! addr_policy_permits_address(addr, port, authdir_reject_policy))
+ if (!addr_policy_permits_tor_addr(addr, port, authdir_reject_policy))
return 0;
return !addr_is_in_cc_list(addr, get_options()->AuthDirRejectCCs);
}
@@ -1154,9 +1101,9 @@ authdir_policy_permits_address(uint32_t addr, uint16_t port)
* directory, based on <b>authdir_invalid_policy</b>. Else return 0.
*/
int
-authdir_policy_valid_address(uint32_t addr, uint16_t port)
+authdir_policy_valid_address(const tor_addr_t *addr, uint16_t port)
{
- if (! addr_policy_permits_address(addr, port, authdir_invalid_policy))
+ if (!addr_policy_permits_tor_addr(addr, port, authdir_invalid_policy))
return 0;
return !addr_is_in_cc_list(addr, get_options()->AuthDirInvalidCCs);
}
@@ -1165,9 +1112,9 @@ authdir_policy_valid_address(uint32_t addr, uint16_t port)
* based on <b>authdir_badexit_policy</b>. Else return 0.
*/
int
-authdir_policy_badexit_address(uint32_t addr, uint16_t port)
+authdir_policy_badexit_address(const tor_addr_t *addr, uint16_t port)
{
- if (! addr_policy_permits_address(addr, port, authdir_badexit_policy))
+ if (!addr_policy_permits_tor_addr(addr, port, authdir_badexit_policy))
return 1;
return addr_is_in_cc_list(addr, get_options()->AuthDirBadExitCCs);
}
@@ -1282,6 +1229,22 @@ load_policy_from_option(config_line_t *config, const char *option_name,
return 0;
}
+/** Helper: Parse the MetricsPortPolicy option into the metrics_policy and set
+ * the reject all by default.
+ *
+ * Return 0 on success else -1. */
+static int
+parse_metrics_port_policy(const or_options_t *options)
+{
+ if (load_policy_from_option(options->MetricsPortPolicy, "MetricsPortPolicy",
+ &metrics_policy, -1) < 0) {
+ return -1;
+ }
+ /* It is a reject all by default. */
+ append_exit_policy_string(&metrics_policy, "reject *:*");
+ return 0;
+}
+
/** Set all policies based on <b>options</b>, which should have been validated
* first by validate_addr_policies. */
int
@@ -1303,6 +1266,9 @@ policies_parse_from_options(const or_options_t *options)
if (load_policy_from_option(options->AuthDirBadExit, "AuthDirBadExit",
&authdir_badexit_policy, ADDR_POLICY_REJECT) < 0)
ret = -1;
+ if (parse_metrics_port_policy(options) < 0) {
+ ret = -1;
+ }
if (parse_reachable_addresses() < 0)
ret = -1;
return ret;
@@ -1883,7 +1849,7 @@ policies_log_first_redundant_entry(const smartlist_t *policy)
int found_ipv4_wildcard = 0, found_ipv6_wildcard = 0;
const int i = p_sl_idx;
- /* Look for accept/reject *[4|6|]:* entires */
+ /* Look for accept/reject *[4|6|]:* entries */
if (p->prt_min <= 1 && p->prt_max == 65535 && p->maskbits == 0) {
family = tor_addr_family(&p->addr);
/* accept/reject *:* may have already been expanded into
@@ -2086,22 +2052,6 @@ policies_copy_addr_to_smartlist(smartlist_t *addr_list, const tor_addr_t *addr)
}
}
-/** Helper function that adds ipv4h_addr to a smartlist as a tor_addr_t *,
- * as long as it is not tor_addr_is_null(), by converting it to a tor_addr_t
- * and passing it to policies_add_addr_to_smartlist.
- *
- * The caller is responsible for freeing all the tor_addr_t* in the smartlist.
- */
-static void
-policies_copy_ipv4h_to_smartlist(smartlist_t *addr_list, uint32_t ipv4h_addr)
-{
- if (ipv4h_addr) {
- tor_addr_t ipv4_tor_addr;
- tor_addr_from_ipv4h(&ipv4_tor_addr, ipv4h_addr);
- policies_copy_addr_to_smartlist(addr_list, &ipv4_tor_addr);
- }
-}
-
/** Helper function that adds copies of or_options->OutboundBindAddresses
* to a smartlist as tor_addr_t *, as long as or_options is non-NULL, and
* the addresses are not tor_addr_is_null(), by passing them to
@@ -2133,8 +2083,8 @@ policies_copy_outbound_addresses_to_smartlist(smartlist_t *addr_list,
* If <b>or_options->ExitPolicyRejectPrivate</b> is true:
* - prepend an entry that rejects all destinations in all netblocks reserved
* for private use.
- * - if local_address is non-zero, treat it as a host-order IPv4 address, and
- * add it to the list of configured addresses.
+ * - if ipv4_local_address is non-zero, treat it as a host-order IPv4 address,
+ * and add it to the list of configured addresses.
* - if ipv6_local_address is non-NULL, and not the null tor_addr_t, add it
* to the list of configured addresses.
* If <b>or_options->ExitPolicyRejectLocalInterfaces</b> is true:
@@ -2151,7 +2101,7 @@ policies_copy_outbound_addresses_to_smartlist(smartlist_t *addr_list,
*/
int
policies_parse_exit_policy_from_options(const or_options_t *or_options,
- uint32_t local_address,
+ const tor_addr_t *ipv4_local_address,
const tor_addr_t *ipv6_local_address,
smartlist_t **result)
{
@@ -2192,7 +2142,7 @@ policies_parse_exit_policy_from_options(const or_options_t *or_options,
/* Copy the configured addresses into the tor_addr_t* list */
if (or_options->ExitPolicyRejectPrivate) {
- policies_copy_ipv4h_to_smartlist(configured_addresses, local_address);
+ policies_copy_addr_to_smartlist(configured_addresses, ipv4_local_address);
policies_copy_addr_to_smartlist(configured_addresses, ipv6_local_address);
}
@@ -3062,7 +3012,7 @@ getinfo_helper_policies(control_connection_t *conn,
/* Copy the configured addresses into the tor_addr_t* list */
if (options->ExitPolicyRejectPrivate) {
- policies_copy_ipv4h_to_smartlist(configured_addresses, me->addr);
+ policies_copy_addr_to_smartlist(configured_addresses, &me->ipv4_addr);
policies_copy_addr_to_smartlist(configured_addresses, &me->ipv6_addr);
}
@@ -3154,6 +3104,8 @@ policies_free_all(void)
socks_policy = NULL;
addr_policy_list_free(dir_policy);
dir_policy = NULL;
+ addr_policy_list_free(metrics_policy);
+ metrics_policy = NULL;
addr_policy_list_free(authdir_reject_policy);
authdir_reject_policy = NULL;
addr_policy_list_free(authdir_invalid_policy);
diff --git a/src/core/or/policies.h b/src/core/or/policies.h
index 72a37d62b0..17bd7c869f 100644
--- a/src/core/or/policies.h
+++ b/src/core/or/policies.h
@@ -69,42 +69,43 @@ typedef struct short_policy_t {
int firewall_is_fascist_or(void);
int firewall_is_fascist_dir(void);
-int fascist_firewall_use_ipv6(const or_options_t *options);
-int fascist_firewall_prefer_ipv6_orport(const or_options_t *options);
-int fascist_firewall_prefer_ipv6_dirport(const or_options_t *options);
+int reachable_addr_use_ipv6(const or_options_t *options);
+int reachable_addr_prefer_ipv6_orport(const or_options_t *options);
+int reachable_addr_prefer_ipv6_dirport(const or_options_t *options);
-int fascist_firewall_allows_address_addr(const tor_addr_t *addr,
+int reachable_addr_allows_addr(const tor_addr_t *addr,
uint16_t port,
firewall_connection_t fw_connection,
int pref_only, int pref_ipv6);
-int fascist_firewall_allows_rs(const routerstatus_t *rs,
+int reachable_addr_allows_rs(const routerstatus_t *rs,
firewall_connection_t fw_connection,
int pref_only);
-int fascist_firewall_allows_node(const node_t *node,
+int reachable_addr_allows_node(const node_t *node,
firewall_connection_t fw_connection,
int pref_only);
-int fascist_firewall_allows_dir_server(const dir_server_t *ds,
+int reachable_addr_allows_dir_server(const dir_server_t *ds,
firewall_connection_t fw_connection,
int pref_only);
-void fascist_firewall_choose_address_rs(const routerstatus_t *rs,
+void reachable_addr_choose_from_rs(const routerstatus_t *rs,
firewall_connection_t fw_connection,
int pref_only, tor_addr_port_t* ap);
-void fascist_firewall_choose_address_ls(const smartlist_t *lspecs,
+void reachable_addr_choose_from_ls(const smartlist_t *lspecs,
int pref_only, tor_addr_port_t* ap);
-void fascist_firewall_choose_address_node(const node_t *node,
+void reachable_addr_choose_from_node(const node_t *node,
firewall_connection_t fw_connection,
int pref_only, tor_addr_port_t* ap);
-void fascist_firewall_choose_address_dir_server(const dir_server_t *ds,
+void reachable_addr_choose_from_dir_server(const dir_server_t *ds,
firewall_connection_t fw_connection,
int pref_only, tor_addr_port_t* ap);
int dir_policy_permits_address(const tor_addr_t *addr);
int socks_policy_permits_address(const tor_addr_t *addr);
-int authdir_policy_permits_address(uint32_t addr, uint16_t port);
-int authdir_policy_valid_address(uint32_t addr, uint16_t port);
-int authdir_policy_badexit_address(uint32_t addr, uint16_t port);
+int metrics_policy_permits_address(const tor_addr_t *addr);
+int authdir_policy_permits_address(const tor_addr_t *addr, uint16_t port);
+int authdir_policy_valid_address(const tor_addr_t *addr, uint16_t port);
+int authdir_policy_badexit_address(const tor_addr_t *addr, uint16_t port);
int validate_addr_policies(const or_options_t *options, char **msg);
void policy_expand_private(smartlist_t **policy);
@@ -120,7 +121,7 @@ addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr,
int policies_parse_exit_policy_from_options(
const or_options_t *or_options,
- uint32_t local_address,
+ const tor_addr_t *ipv4_local_address,
const tor_addr_t *ipv6_local_address,
smartlist_t **result);
struct config_line_t;
@@ -173,11 +174,11 @@ addr_policy_result_t compare_tor_addr_to_short_policy(
#ifdef POLICIES_PRIVATE
STATIC void append_exit_policy_string(smartlist_t **policy, const char *more);
-STATIC int fascist_firewall_allows_address(const tor_addr_t *addr,
+STATIC int reachable_addr_allows(const tor_addr_t *addr,
uint16_t port,
smartlist_t *firewall_policy,
int pref_only, int pref_ipv6);
-STATIC const tor_addr_port_t * fascist_firewall_choose_address(
+STATIC const tor_addr_port_t * reachable_addr_choose(
const tor_addr_port_t *a,
const tor_addr_port_t *b,
int want_a,
diff --git a/src/core/or/port_cfg_st.h b/src/core/or/port_cfg_st.h
index 064e679d78..f8ff6f8cc8 100644
--- a/src/core/or/port_cfg_st.h
+++ b/src/core/or/port_cfg_st.h
@@ -26,6 +26,8 @@ struct port_cfg_t {
unsigned is_group_writable : 1;
unsigned is_world_writable : 1;
unsigned relax_dirmode_check : 1;
+ unsigned explicit_addr : 1; /** Indicate if address was explicitly set or
+ * we are using the default address. */
entry_port_cfg_t entry_cfg;
diff --git a/src/core/or/protover.c b/src/core/or/protover.c
index 0d03e9a06b..aa96cafff9 100644
--- a/src/core/or/protover.c
+++ b/src/core/or/protover.c
@@ -33,6 +33,8 @@
static const smartlist_t *get_supported_protocol_list(void);
static int protocol_list_contains(const smartlist_t *protos,
protocol_type_t pr, uint32_t ver);
+static const proto_entry_t *find_entry_by_name(const smartlist_t *protos,
+ const char *name);
/** Mapping between protocol type string and protocol type. */
/// C_RUST_COUPLED: src/rust/protover/protover.rs `PROTOCOL_NAMES`
@@ -83,27 +85,6 @@ protocol_type_to_str(protocol_type_t pr)
}
/**
- * Given a string, find the corresponding protocol type and store it in
- * <b>pr_out</b>. Return 0 on success, -1 on failure.
- */
-STATIC int
-str_to_protocol_type(const char *s, protocol_type_t *pr_out)
-{
- if (BUG(!pr_out))
- return -1;
-
- unsigned i;
- for (i=0; i < N_PROTOCOL_NAMES; ++i) {
- if (0 == strcmp(s, PROTOCOL_NAMES[i].name)) {
- *pr_out = PROTOCOL_NAMES[i].protover_type;
- return 0;
- }
- }
-
- return -1;
-}
-
-/**
* Release all space held by a single proto_entry_t structure
*/
STATIC void
@@ -112,8 +93,6 @@ proto_entry_free_(proto_entry_t *entry)
if (!entry)
return;
tor_free(entry->name);
- SMARTLIST_FOREACH(entry->ranges, proto_range_t *, r, tor_free(r));
- smartlist_free(entry->ranges);
tor_free(entry);
}
@@ -194,6 +173,23 @@ is_valid_keyword(const char *s, size_t n)
return 1;
}
+/** The x'th bit in a bitmask. */
+#define BIT(x) (UINT64_C(1)<<(x))
+
+/**
+ * Return a bitmask so that bits 'low' through 'high' inclusive are set,
+ * and all other bits are cleared.
+ **/
+static uint64_t
+bitmask_for_range(uint32_t low, uint32_t high)
+{
+ uint64_t mask = ~(uint64_t)0;
+ mask <<= 63 - high;
+ mask >>= 63 - high + low;
+ mask <<= low;
+ return mask;
+}
+
/** Parse a single protocol entry from <b>s</b> up to an optional
* <b>end_of_entry</b> pointer, and return that protocol entry. Return NULL
* on error.
@@ -205,8 +201,6 @@ parse_single_entry(const char *s, const char *end_of_entry)
proto_entry_t *out = tor_malloc_zero(sizeof(proto_entry_t));
const char *equals;
- out->ranges = smartlist_new();
-
if (BUG (!end_of_entry))
end_of_entry = s + strlen(s); // LCOV_EXCL_LINE
@@ -240,17 +234,19 @@ parse_single_entry(const char *s, const char *end_of_entry)
s = equals + 1;
while (s < end_of_entry) {
const char *comma = memchr(s, ',', end_of_entry-s);
- proto_range_t *range = tor_malloc_zero(sizeof(proto_range_t));
if (! comma)
comma = end_of_entry;
- smartlist_add(out->ranges, range);
- if (parse_version_range(s, comma, &range->low, &range->high) < 0) {
+ uint32_t low=0, high=0;
+ if (parse_version_range(s, comma, &low, &high) < 0) {
goto error;
}
+ out->bitmask |= bitmask_for_range(low,high);
+
s = comma;
- while (*s == ',' && s < end_of_entry)
+ // Skip the comma separator between ranges. Don't ignore a trailing comma.
+ if (s < (end_of_entry - 1))
++s;
}
@@ -298,11 +294,12 @@ parse_protocol_list(const char *s)
}
/**
- * Return true if the unparsed protover in <b>s</b> would contain a protocol
- * name longer than MAX_PROTOCOL_NAME_LENGTH, and false otherwise.
+ * Return true if the unparsed protover list in <b>s</b> contains a
+ * parsing error, such as extra commas, a bad number, or an over-long
+ * name.
*/
bool
-protover_contains_long_protocol_names(const char *s)
+protover_list_is_invalid(const char *s)
{
smartlist_t *list = parse_protocol_list(s);
if (!list)
@@ -326,6 +323,9 @@ protover_is_supported_here(protocol_type_t pr, uint32_t ver)
/**
* Return true iff "list" encodes a protocol list that includes support for
* the indicated protocol and version.
+ *
+ * If the protocol list is unparseable, treat it as if it defines no
+ * protocols, and return 0.
*/
int
protocol_list_supports_protocol(const char *list, protocol_type_t tp,
@@ -348,6 +348,9 @@ protocol_list_supports_protocol(const char *list, protocol_type_t tp,
/**
* Return true iff "list" encodes a protocol list that includes support for
* the indicated protocol and version, or some later version.
+ *
+ * If the protocol list is unparseable, treat it as if it defines no
+ * protocols, and return 0.
*/
int
protocol_list_supports_protocol_or_later(const char *list,
@@ -364,15 +367,15 @@ protocol_list_supports_protocol_or_later(const char *list,
const char *pr_name = protocol_type_to_str(tp);
int contains = 0;
+ const uint64_t mask = bitmask_for_range(version, 63);
+
SMARTLIST_FOREACH_BEGIN(protocols, proto_entry_t *, proto) {
if (strcasecmp(proto->name, pr_name))
continue;
- SMARTLIST_FOREACH_BEGIN(proto->ranges, const proto_range_t *, range) {
- if (range->high >= version) {
- contains = 1;
- goto found;
- }
- } SMARTLIST_FOREACH_END(range);
+ if (0 != (proto->bitmask & mask)) {
+ contains = 1;
+ goto found;
+ }
} SMARTLIST_FOREACH_END(proto);
found:
@@ -387,10 +390,15 @@ protocol_list_supports_protocol_or_later(const char *list,
const char *
protover_get_supported_protocols(void)
{
+ /* WARNING!
+ *
+ * Remember to edit the SUPPORTED_PROTOCOLS list in protover.rs if you
+ * are editing this list.
+ */
return
"Cons=1-2 "
"Desc=1-2 "
- "DirCache=1-2 "
+ "DirCache=2 "
"FlowCtrl=1 "
"HSDir=1-2 "
"HSIntro=3-5 "
@@ -403,7 +411,7 @@ protover_get_supported_protocols(void)
#endif
"Microdesc=1-2 "
"Padding=2 "
- "Relay=1-2";
+ "Relay=1-3";
}
/** The protocols from protover_get_supported_protocols(), as parsed into a
@@ -423,6 +431,23 @@ get_supported_protocol_list(void)
return supported_protocol_list;
}
+/** Return the number of trailing zeros in x. Undefined if x is 0. */
+static int
+trailing_zeros(uint64_t x)
+{
+#ifdef __GNUC__
+ return __builtin_ctzll((unsigned long long)x);
+#else
+ int i;
+ for (i = 0; i <= 64; ++i) {
+ if (x&1)
+ return i;
+ x>>=1;
+ }
+ return i;
+#endif
+}
+
/**
* Given a protocol entry, encode it at the end of the smartlist <b>chunks</b>
* as one or more newly allocated strings.
@@ -432,20 +457,30 @@ proto_entry_encode_into(smartlist_t *chunks, const proto_entry_t *entry)
{
smartlist_add_asprintf(chunks, "%s=", entry->name);
- SMARTLIST_FOREACH_BEGIN(entry->ranges, proto_range_t *, range) {
- const char *comma = "";
- if (range_sl_idx != 0)
- comma = ",";
-
- if (range->low == range->high) {
- smartlist_add_asprintf(chunks, "%s%lu",
- comma, (unsigned long)range->low);
+ uint64_t mask = entry->bitmask;
+ int shift = 0; // how much have we shifted by so far?
+ bool first = true;
+ while (mask) {
+ const char *comma = first ? "" : ",";
+ if (first) {
+ first = false;
+ }
+ int zeros = trailing_zeros(mask);
+ mask >>= zeros;
+ shift += zeros;
+ int ones = !mask ? 64 : trailing_zeros(~mask);
+ if (ones == 1) {
+ smartlist_add_asprintf(chunks, "%s%d", comma, shift);
} else {
- smartlist_add_asprintf(chunks, "%s%lu-%lu",
- comma, (unsigned long)range->low,
- (unsigned long)range->high);
+ smartlist_add_asprintf(chunks, "%s%d-%d", comma,
+ shift, shift + ones - 1);
+ }
+ if (ones == 64) {
+ break; // avoid undefined behavior; can't shift by 64.
}
- } SMARTLIST_FOREACH_END(range);
+ mask >>= ones;
+ shift += ones;
+ }
}
/** Given a list of space-separated proto_entry_t items,
@@ -471,192 +506,6 @@ encode_protocol_list(const smartlist_t *sl)
return result;
}
-/* We treat any protocol list with more than this many subprotocols in it
- * as a DoS attempt. */
-/// C_RUST_COUPLED: src/rust/protover/protover.rs
-/// `MAX_PROTOCOLS_TO_EXPAND`
-static const int MAX_PROTOCOLS_TO_EXPAND = (1<<16);
-
-/** Voting helper: Given a list of proto_entry_t, return a newly allocated
- * smartlist of newly allocated strings, one for each included protocol
- * version. (So 'Foo=3,5-7' expands to a list of 'Foo=3', 'Foo=5', 'Foo=6',
- * 'Foo=7'.)
- *
- * Do not list any protocol version more than once.
- *
- * Return NULL if the list would be too big.
- */
-static smartlist_t *
-expand_protocol_list(const smartlist_t *protos)
-{
- smartlist_t *expanded = smartlist_new();
- if (!protos)
- return expanded;
-
- SMARTLIST_FOREACH_BEGIN(protos, const proto_entry_t *, ent) {
- const char *name = ent->name;
- if (strlen(name) > MAX_PROTOCOL_NAME_LENGTH) {
- log_warn(LD_NET, "When expanding a protocol entry, I got a very large "
- "protocol name. This is possibly an attack or a bug, unless "
- "the Tor network truly supports protocol names larger than "
- "%ud characters. The offending string was: %s",
- MAX_PROTOCOL_NAME_LENGTH, escaped(name));
- continue;
- }
- SMARTLIST_FOREACH_BEGIN(ent->ranges, const proto_range_t *, range) {
- uint32_t u;
- for (u = range->low; u <= range->high; ++u) {
- smartlist_add_asprintf(expanded, "%s=%lu", name, (unsigned long)u);
- if (smartlist_len(expanded) > MAX_PROTOCOLS_TO_EXPAND)
- goto too_many;
- }
- } SMARTLIST_FOREACH_END(range);
- } SMARTLIST_FOREACH_END(ent);
-
- smartlist_sort_strings(expanded);
- smartlist_uniq_strings(expanded); // This makes voting work. do not remove
- return expanded;
-
- too_many:
- SMARTLIST_FOREACH(expanded, char *, cp, tor_free(cp));
- smartlist_free(expanded);
- return NULL;
-}
-
-/** Voting helper: compare two singleton proto_entry_t items by version
- * alone. (A singleton item is one with a single range entry where
- * low==high.) */
-static int
-cmp_single_ent_by_version(const void **a_, const void **b_)
-{
- const proto_entry_t *ent_a = *a_;
- const proto_entry_t *ent_b = *b_;
-
- tor_assert(smartlist_len(ent_a->ranges) == 1);
- tor_assert(smartlist_len(ent_b->ranges) == 1);
-
- const proto_range_t *a = smartlist_get(ent_a->ranges, 0);
- const proto_range_t *b = smartlist_get(ent_b->ranges, 0);
-
- tor_assert(a->low == a->high);
- tor_assert(b->low == b->high);
-
- if (a->low < b->low) {
- return -1;
- } else if (a->low == b->low) {
- return 0;
- } else {
- return 1;
- }
-}
-
-/** Voting helper: Given a list of singleton protocol strings (of the form
- * Foo=7), return a canonical listing of all the protocol versions listed,
- * with as few ranges as possible, with protocol versions sorted lexically and
- * versions sorted in numerically increasing order, using as few range entries
- * as possible.
- **/
-static char *
-contract_protocol_list(const smartlist_t *proto_strings)
-{
- if (smartlist_len(proto_strings) == 0) {
- return tor_strdup("");
- }
-
- // map from name to list of single-version entries
- strmap_t *entry_lists_by_name = strmap_new();
- // list of protocol names
- smartlist_t *all_names = smartlist_new();
- // list of strings for the output we're building
- smartlist_t *chunks = smartlist_new();
-
- // Parse each item and stick it entry_lists_by_name. Build
- // 'all_names' at the same time.
- SMARTLIST_FOREACH_BEGIN(proto_strings, const char *, s) {
- if (BUG(!s))
- continue;// LCOV_EXCL_LINE
- proto_entry_t *ent = parse_single_entry(s, s+strlen(s));
- if (BUG(!ent))
- continue; // LCOV_EXCL_LINE
- smartlist_t *lst = strmap_get(entry_lists_by_name, ent->name);
- if (!lst) {
- smartlist_add(all_names, ent->name);
- lst = smartlist_new();
- strmap_set(entry_lists_by_name, ent->name, lst);
- }
- smartlist_add(lst, ent);
- } SMARTLIST_FOREACH_END(s);
-
- // We want to output the protocols sorted by their name.
- smartlist_sort_strings(all_names);
-
- SMARTLIST_FOREACH_BEGIN(all_names, const char *, name) {
- const int first_entry = (name_sl_idx == 0);
- smartlist_t *lst = strmap_get(entry_lists_by_name, name);
- tor_assert(lst);
- // Sort every entry with this name by version. They are
- // singletons, so there can't be overlap.
- smartlist_sort(lst, cmp_single_ent_by_version);
-
- if (! first_entry)
- smartlist_add_strdup(chunks, " ");
-
- /* We're going to construct this entry from the ranges. */
- proto_entry_t *entry = tor_malloc_zero(sizeof(proto_entry_t));
- entry->ranges = smartlist_new();
- entry->name = tor_strdup(name);
-
- // Now, find all the ranges of versions start..end where
- // all of start, start+1, start+2, ..end are included.
- int start_of_cur_series = 0;
- while (start_of_cur_series < smartlist_len(lst)) {
- const proto_entry_t *ent = smartlist_get(lst, start_of_cur_series);
- const proto_range_t *range = smartlist_get(ent->ranges, 0);
- const uint32_t ver_low = range->low;
- uint32_t ver_high = ver_low;
-
- int idx;
- for (idx = start_of_cur_series+1; idx < smartlist_len(lst); ++idx) {
- ent = smartlist_get(lst, idx);
- range = smartlist_get(ent->ranges, 0);
- if (range->low != ver_high + 1)
- break;
- ver_high += 1;
- }
-
- // Now idx is either off the end of the list, or the first sequence
- // break in the list.
- start_of_cur_series = idx;
-
- proto_range_t *new_range = tor_malloc_zero(sizeof(proto_range_t));
- new_range->low = ver_low;
- new_range->high = ver_high;
- smartlist_add(entry->ranges, new_range);
- }
- proto_entry_encode_into(chunks, entry);
- proto_entry_free(entry);
-
- } SMARTLIST_FOREACH_END(name);
-
- // Build the result...
- char *result = smartlist_join_strings(chunks, "", 0, NULL);
-
- // And free all the stuff we allocated.
- SMARTLIST_FOREACH_BEGIN(all_names, const char *, name) {
- smartlist_t *lst = strmap_get(entry_lists_by_name, name);
- tor_assert(lst);
- SMARTLIST_FOREACH(lst, proto_entry_t *, e, proto_entry_free(e));
- smartlist_free(lst);
- } SMARTLIST_FOREACH_END(name);
-
- strmap_free(entry_lists_by_name, NULL);
- smartlist_free(all_names);
- SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
- smartlist_free(chunks);
-
- return result;
-}
-
/**
* Protocol voting implementation.
*
@@ -671,13 +520,18 @@ char *
protover_compute_vote(const smartlist_t *list_of_proto_strings,
int threshold)
{
+ // we use u8 counters below.
+ tor_assert(smartlist_len(list_of_proto_strings) < 256);
+
if (smartlist_len(list_of_proto_strings) == 0) {
return tor_strdup("");
}
- smartlist_t *all_entries = smartlist_new();
+ smartlist_t *parsed = smartlist_new(); // smartlist of smartlist of entries
+ smartlist_t *proto_names = smartlist_new(); // smartlist of strings
+ smartlist_t *result = smartlist_new(); // smartlist of entries
- // First, parse the inputs and break them into singleton entries.
+ // First, parse the inputs, and accumulate a list of protocol names.
SMARTLIST_FOREACH_BEGIN(list_of_proto_strings, const char *, vote) {
smartlist_t *unexpanded = parse_protocol_list(vote);
if (! unexpanded) {
@@ -686,72 +540,74 @@ protover_compute_vote(const smartlist_t *list_of_proto_strings,
escaped(vote));
continue;
}
- smartlist_t *this_vote = expand_protocol_list(unexpanded);
- if (this_vote == NULL) {
- log_warn(LD_NET, "When expanding a protocol list from an authority, I "
- "got too many protocols. This is possibly an attack or a bug, "
- "unless the Tor network truly has expanded to support over %d "
- "different subprotocol versions. The offending string was: %s",
- MAX_PROTOCOLS_TO_EXPAND, escaped(vote));
- } else {
- smartlist_add_all(all_entries, this_vote);
- smartlist_free(this_vote);
- }
- SMARTLIST_FOREACH(unexpanded, proto_entry_t *, e, proto_entry_free(e));
- smartlist_free(unexpanded);
+ SMARTLIST_FOREACH_BEGIN(unexpanded, const proto_entry_t *, ent) {
+ if (!smartlist_contains_string(proto_names,ent->name)) {
+ smartlist_add(proto_names, ent->name);
+ }
+ } SMARTLIST_FOREACH_END(ent);
+ smartlist_add(parsed, unexpanded);
} SMARTLIST_FOREACH_END(vote);
- if (smartlist_len(all_entries) == 0) {
- smartlist_free(all_entries);
- return tor_strdup("");
- }
-
- // Now sort the singleton entries
- smartlist_sort_strings(all_entries);
+ // Sort the list of names.
+ smartlist_sort_strings(proto_names);
+
+ // For each named protocol, compute the consensus.
+ //
+ // This is not super-efficient, but it's not critical path.
+ SMARTLIST_FOREACH_BEGIN(proto_names, const char *, name) {
+ uint8_t counts[64];
+ memset(counts, 0, sizeof(counts));
+ // Count how many votes we got for each bit.
+ SMARTLIST_FOREACH_BEGIN(parsed, const smartlist_t *, vote) {
+ const proto_entry_t *ent = find_entry_by_name(vote, name);
+ if (! ent)
+ continue;
+
+ for (int i = 0; i < 64; ++i) {
+ if ((ent->bitmask & BIT(i)) != 0) {
+ ++ counts[i];
+ }
+ }
+ } SMARTLIST_FOREACH_END(vote);
- // Now find all the strings that appear at least 'threshold' times.
- smartlist_t *include_entries = smartlist_new();
- const char *cur_entry = smartlist_get(all_entries, 0);
- int n_times = 0;
- SMARTLIST_FOREACH_BEGIN(all_entries, const char *, ent) {
- if (!strcmp(ent, cur_entry)) {
- n_times++;
- } else {
- if (n_times >= threshold && cur_entry)
- smartlist_add(include_entries, (void*)cur_entry);
- cur_entry = ent;
- n_times = 1 ;
+ uint64_t result_bitmask = 0;
+ for (int i = 0; i < 64; ++i) {
+ if (counts[i] >= threshold) {
+ result_bitmask |= BIT(i);
+ }
}
- } SMARTLIST_FOREACH_END(ent);
+ if (result_bitmask != 0) {
+ proto_entry_t *newent = tor_malloc_zero(sizeof(proto_entry_t));
+ newent->name = tor_strdup(name);
+ newent->bitmask = result_bitmask;
+ smartlist_add(result, newent);
+ }
+ } SMARTLIST_FOREACH_END(name);
- if (n_times >= threshold && cur_entry)
- smartlist_add(include_entries, (void*)cur_entry);
+ char *consensus = encode_protocol_list(result);
- // Finally, compress that list.
- char *result = contract_protocol_list(include_entries);
- smartlist_free(include_entries);
- SMARTLIST_FOREACH(all_entries, char *, cp, tor_free(cp));
- smartlist_free(all_entries);
+ SMARTLIST_FOREACH(result, proto_entry_t *, ent, proto_entry_free(ent));
+ smartlist_free(result);
+ smartlist_free(proto_names); // no need to free members; they are aliases.
+ SMARTLIST_FOREACH_BEGIN(parsed, smartlist_t *, v) {
+ SMARTLIST_FOREACH(v, proto_entry_t *, ent, proto_entry_free(ent));
+ smartlist_free(v);
+ } SMARTLIST_FOREACH_END(v);
+ smartlist_free(parsed);
- return result;
+ return consensus;
}
/** Return true if every protocol version described in the string <b>s</b> is
* one that we support, and false otherwise. If <b>missing_out</b> is
* provided, set it to the list of protocols we do not support.
*
- * NOTE: This is quadratic, but we don't do it much: only a few times per
- * consensus. Checking signatures should be way more expensive than this
- * ever would be.
+ * If the protocol version string is unparseable, treat it as if it defines no
+ * protocols, and return 1.
**/
int
protover_all_supported(const char *s, char **missing_out)
{
- int all_supported = 1;
- smartlist_t *missing_some;
- smartlist_t *missing_completely;
- smartlist_t *missing_all;
-
if (!s) {
return 1;
}
@@ -762,101 +618,37 @@ protover_all_supported(const char *s, char **missing_out)
" from the consensus", escaped(s));
return 1;
}
-
- missing_some = smartlist_new();
- missing_completely = smartlist_new();
+ const smartlist_t *supported = get_supported_protocol_list();
+ smartlist_t *missing = smartlist_new();
SMARTLIST_FOREACH_BEGIN(entries, const proto_entry_t *, ent) {
- protocol_type_t tp;
- if (str_to_protocol_type(ent->name, &tp) < 0) {
- if (smartlist_len(ent->ranges)) {
- goto unsupported;
+ const proto_entry_t *mine = find_entry_by_name(supported, ent->name);
+ if (mine == NULL) {
+ if (ent->bitmask != 0) {
+ proto_entry_t *m = tor_malloc_zero(sizeof(proto_entry_t));
+ m->name = tor_strdup(ent->name);
+ m->bitmask = ent->bitmask;
+ smartlist_add(missing, m);
}
continue;
}
- SMARTLIST_FOREACH_BEGIN(ent->ranges, const proto_range_t *, range) {
- proto_entry_t *unsupported = tor_malloc_zero(sizeof(proto_entry_t));
- proto_range_t *versions = tor_malloc_zero(sizeof(proto_range_t));
- uint32_t i;
-
- unsupported->name = tor_strdup(ent->name);
- unsupported->ranges = smartlist_new();
-
- for (i = range->low; i <= range->high; ++i) {
- if (!protover_is_supported_here(tp, i)) {
- if (versions->low == 0 && versions->high == 0) {
- versions->low = i;
- /* Pre-emptively add the high now, just in case we're in a single
- * version range (e.g. "Link=999"). */
- versions->high = i;
- }
- /* If the last one to be unsupported is one less than the current
- * one, we're in a continuous range, so set the high field. */
- if ((versions->high && versions->high == i - 1) ||
- /* Similarly, if the last high wasn't set and we're currently
- * one higher than the low, add current index as the highest
- * known high. */
- (!versions->high && versions->low == i - 1)) {
- versions->high = i;
- continue;
- }
- } else {
- /* If we hit a supported version, and we previously had a range,
- * we've hit a non-continuity. Copy the previous range and add it to
- * the unsupported->ranges list and zero-out the previous range for
- * the next iteration. */
- if (versions->low != 0 && versions->high != 0) {
- proto_range_t *versions_to_add = tor_malloc(sizeof(proto_range_t));
-
- versions_to_add->low = versions->low;
- versions_to_add->high = versions->high;
- smartlist_add(unsupported->ranges, versions_to_add);
-
- versions->low = 0;
- versions->high = 0;
- }
- }
- }
- /* Once we've run out of versions to check, see if we had any unsupported
- * ones and, if so, add them to unsupported->ranges. */
- if (versions->low != 0 && versions->high != 0) {
- smartlist_add(unsupported->ranges, versions);
- } else {
- tor_free(versions);
- }
- /* Finally, if we had something unsupported, add it to the list of
- * missing_some things and mark that there was something missing. */
- if (smartlist_len(unsupported->ranges) != 0) {
- smartlist_add(missing_some, (void*) unsupported);
- all_supported = 0;
- } else {
- proto_entry_free(unsupported);
- }
- } SMARTLIST_FOREACH_END(range);
-
- continue;
-
- unsupported:
- all_supported = 0;
- smartlist_add(missing_completely, (void*) ent);
+ uint64_t missing_mask = ent->bitmask & ~mine->bitmask;
+ if (missing_mask != 0) {
+ proto_entry_t *m = tor_malloc_zero(sizeof(proto_entry_t));
+ m->name = tor_strdup(ent->name);
+ m->bitmask = missing_mask;
+ smartlist_add(missing, m);
+ }
} SMARTLIST_FOREACH_END(ent);
- /* We keep the two smartlists separate so that we can free the proto_entry_t
- * we created and put in missing_some, so here we add them together to build
- * the string. */
- missing_all = smartlist_new();
- smartlist_add_all(missing_all, missing_some);
- smartlist_add_all(missing_all, missing_completely);
-
- if (missing_out && !all_supported) {
- tor_assert(smartlist_len(missing_all) != 0);
- *missing_out = encode_protocol_list(missing_all);
+ const int all_supported = (smartlist_len(missing) == 0);
+ if (!all_supported && missing_out) {
+ *missing_out = encode_protocol_list(missing);
}
- SMARTLIST_FOREACH(missing_some, proto_entry_t *, ent, proto_entry_free(ent));
- smartlist_free(missing_some);
- smartlist_free(missing_completely);
- smartlist_free(missing_all);
+
+ SMARTLIST_FOREACH(missing, proto_entry_t *, ent, proto_entry_free(ent));
+ smartlist_free(missing);
SMARTLIST_FOREACH(entries, proto_entry_t *, ent, proto_entry_free(ent));
smartlist_free(entries);
@@ -864,6 +656,23 @@ protover_all_supported(const char *s, char **missing_out)
return all_supported;
}
+/** Helper: return the member of 'protos' whose name is
+ * 'name', or NULL if there is no such member. */
+static const proto_entry_t *
+find_entry_by_name(const smartlist_t *protos, const char *name)
+{
+ if (!protos) {
+ return NULL;
+ }
+ SMARTLIST_FOREACH_BEGIN(protos, const proto_entry_t *, ent) {
+ if (!strcmp(ent->name, name)) {
+ return ent;
+ }
+ } SMARTLIST_FOREACH_END(ent);
+
+ return NULL;
+}
+
/** Helper: Given a list of proto_entry_t, return true iff
* <b>pr</b>=<b>ver</b> is included in that list. */
static int
@@ -877,17 +686,14 @@ protocol_list_contains(const smartlist_t *protos,
if (BUG(pr_name == NULL)) {
return 0; // LCOV_EXCL_LINE
}
+ if (ver > MAX_PROTOCOL_VERSION) {
+ return 0;
+ }
- SMARTLIST_FOREACH_BEGIN(protos, const proto_entry_t *, ent) {
- if (strcasecmp(ent->name, pr_name))
- continue;
- /* name matches; check the ranges */
- SMARTLIST_FOREACH_BEGIN(ent->ranges, const proto_range_t *, range) {
- if (ver >= range->low && ver <= range->high)
- return 1;
- } SMARTLIST_FOREACH_END(range);
- } SMARTLIST_FOREACH_END(ent);
-
+ const proto_entry_t *ent = find_entry_by_name(protos, pr_name);
+ if (ent) {
+ return (ent->bitmask & BIT(ver)) != 0;
+ }
return 0;
}
diff --git a/src/core/or/protover.h b/src/core/or/protover.h
index 9509f3e8a3..88fcbb0b61 100644
--- a/src/core/or/protover.h
+++ b/src/core/or/protover.h
@@ -22,12 +22,32 @@ struct smartlist_t;
/// `FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS`
#define FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS "0.2.9.3-alpha"
-/** The protover version number that signifies HSDir support for HSv3 */
-#define PROTOVER_HSDIR_V3 2
+/** The protover version number that signifies ed25519 link handshake support
+ */
+#define PROTOVER_LINKAUTH_ED25519_HANDSHAKE 3
+
+/** The protover version number that signifies extend2 cell support */
+#define PROTOVER_RELAY_EXTEND2 2
+/** The protover version number where relays can accept IPv6 connections */
+#define PROTOVER_RELAY_ACCEPT_IPV6 2
+/** The protover version number where relays can initiate IPv6 extends */
+#define PROTOVER_RELAY_EXTEND_IPV6 3
+/** The protover version number where relays can consider IPv6 connections
+ * canonical */
+#define PROTOVER_RELAY_CANONICAL_IPV6 3
+
/** The protover version number that signifies HSv3 intro point support */
#define PROTOVER_HS_INTRO_V3 4
+/** The protover version number where intro points support denial of service
+ * resistance */
+#define PROTOVER_HS_INTRO_DOS 5
+
/** The protover version number that signifies HSv3 rendezvous point support */
#define PROTOVER_HS_RENDEZVOUS_POINT_V3 2
+
+/** The protover version number that signifies HSDir support for HSv3 */
+#define PROTOVER_HSDIR_V3 2
+
/** The protover that signals support for HS circuit setup padding machines */
#define PROTOVER_HS_SETUP_PADDING 2
@@ -49,7 +69,7 @@ typedef enum protocol_type_t {
PRT_FLOWCTRL = 11,
} protocol_type_t;
-bool protover_contains_long_protocol_names(const char *s);
+bool protover_list_is_invalid(const char *s);
int protover_all_supported(const char *s, char **missing);
int protover_is_supported_here(protocol_type_t pr, uint32_t ver);
const char *protover_get_supported_protocols(void);
@@ -66,13 +86,6 @@ int protocol_list_supports_protocol_or_later(const char *list,
void protover_free_all(void);
#ifdef PROTOVER_PRIVATE
-/** Represents a range of subprotocols of a given type. All subprotocols
- * between <b>low</b> and <b>high</b> inclusive are included. */
-typedef struct proto_range_t {
- uint32_t low;
- uint32_t high;
-} proto_range_t;
-
/** Represents a set of ranges of subprotocols of a given type. */
typedef struct proto_entry_t {
/** The name of the protocol.
@@ -81,8 +94,9 @@ typedef struct proto_entry_t {
* we don't recognize yet, so it's a char* rather than a protocol_type_t.)
*/
char *name;
- /** Smartlist of proto_range_t */
- struct smartlist_t *ranges;
+ /** Bitmask of supported protocols. Version 'x' is included in this
+ * entry if and only if bit '1<<x' is set here. */
+ uint64_t bitmask;
} proto_entry_t;
#if !defined(HAVE_RUST) && defined(TOR_UNIT_TESTS)
diff --git a/src/core/or/protover_rust.c b/src/core/or/protover_rust.c
index f44746b6da..99f3aa7f69 100644
--- a/src/core/or/protover_rust.c
+++ b/src/core/or/protover_rust.c
@@ -25,7 +25,7 @@ int protover_contains_long_protocol_names_(const char *s);
* name longer than MAX_PROTOCOL_NAME_LENGTH, and false otherwise.
*/
bool
-protover_contains_long_protocol_names(const char *s)
+protover_list_is_invalid(const char *s)
{
return protover_contains_long_protocol_names_(s) != 0;
}
diff --git a/src/core/or/relay.c b/src/core/or/relay.c
index 75d2d479e7..f986883370 100644
--- a/src/core/or/relay.c
+++ b/src/core/or/relay.c
@@ -56,6 +56,7 @@
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
#include "core/or/circuitpadding.h"
+#include "core/or/extendinfo.h"
#include "lib/compress/compress.h"
#include "app/config/config.h"
#include "core/mainloop/connection.h"
@@ -82,6 +83,7 @@
#include "feature/nodelist/describe.h"
#include "feature/nodelist/routerlist.h"
#include "core/or/scheduler.h"
+#include "feature/hs/hs_metrics.h"
#include "core/or/cell_st.h"
#include "core/or/cell_queue_st.h"
@@ -1688,6 +1690,13 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ,
circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh->length);
}
+ /* For onion service connection, update the metrics. */
+ if (conn->hs_ident) {
+ hs_metrics_app_write_bytes(&conn->hs_ident->identity_pk,
+ conn->hs_ident->orig_virtual_port,
+ rh->length);
+ }
+
stats_n_data_bytes_received += rh->length;
connection_buf_add((char*)(cell->payload + RELAY_HEADER_SIZE),
rh->length, TO_CONN(conn));
diff --git a/src/core/or/scheduler.c b/src/core/or/scheduler.c
index 072d78128b..18f11487d9 100644
--- a/src/core/or/scheduler.c
+++ b/src/core/or/scheduler.c
@@ -713,7 +713,7 @@ scheduler_bug_occurred(const channel_t *chan)
if (chan != NULL) {
const size_t outbuf_len =
- buf_datalen(TO_CONN(BASE_CHAN_TO_TLS((channel_t *) chan)->conn)->outbuf);
+ buf_datalen(TO_CONN(CONST_BASE_CHAN_TO_TLS(chan)->conn)->outbuf);
tor_snprintf(buf, sizeof(buf),
"Channel %" PRIu64 " in state %s and scheduler state %s."
" Num cells on cmux: %d. Connection outbuf len: %lu.",
diff --git a/src/core/or/scheduler_kist.c b/src/core/or/scheduler_kist.c
index c73d768f88..8c6a7bd1d1 100644
--- a/src/core/or/scheduler_kist.c
+++ b/src/core/or/scheduler_kist.c
@@ -203,7 +203,7 @@ update_socket_info_impl, (socket_table_ent_t *ent))
tor_assert(ent);
tor_assert(ent->chan);
const tor_socket_t sock =
- TO_CONN(BASE_CHAN_TO_TLS((channel_t *) ent->chan)->conn)->s;
+ TO_CONN(CONST_BASE_CHAN_TO_TLS(ent->chan)->conn)->s;
struct tcp_info tcp;
socklen_t tcp_info_len = sizeof(tcp);
@@ -445,6 +445,11 @@ update_socket_written(socket_table_t *table, channel_t *chan, size_t bytes)
* one cell for each and bouncing back and forth. This KIST impl avoids that
* by only writing a channel's outbuf to the kernel if it has 8 cells or more
* in it.
+ *
+ * Note: The number 8 has been picked for no particular reasons except that it
+ * is 4096 bytes which is a common number for buffering. A TLS record can hold
+ * up to 16KiB thus using 8 cells means that a relay will at most send a TLS
+ * record of 4KiB or 1/4 of the maximum capacity of a TLS record.
*/
MOCK_IMPL(int, channel_should_write_to_kernel,
(outbuf_table_t *table, channel_t *chan))
diff --git a/src/core/or/sendme.c b/src/core/or/sendme.c
index 788f56088c..9cad245b29 100644
--- a/src/core/or/sendme.c
+++ b/src/core/or/sendme.c
@@ -394,12 +394,12 @@ sendme_connection_edge_consider_sending(edge_connection_t *conn)
while (conn->deliver_window <=
(STREAMWINDOW_START - STREAMWINDOW_INCREMENT)) {
log_debug(log_domain, "Outbuf %" TOR_PRIuSZ ", queuing stream SENDME.",
- TO_CONN(conn)->outbuf_flushlen);
+ buf_datalen(TO_CONN(conn)->outbuf));
conn->deliver_window += STREAMWINDOW_INCREMENT;
if (connection_edge_send_command(conn, RELAY_COMMAND_SENDME,
NULL, 0) < 0) {
- log_warn(LD_BUG, "connection_edge_send_command failed while sending "
- "a SENDME. Circuit probably closed, skipping.");
+ log_debug(LD_CIRC, "connection_edge_send_command failed while sending "
+ "a SENDME. Circuit probably closed, skipping.");
goto end; /* The circuit's closed, don't continue */
}
}
@@ -678,7 +678,7 @@ sendme_record_received_cell_digest(circuit_t *circ, crypt_path_t *cpath)
/* Record incoming digest. */
cpath_sendme_record_cell_digest(cpath, false);
} else {
- /* Record foward digest. */
+ /* Record forward digest. */
relay_crypto_record_sendme_digest(&TO_OR_CIRCUIT(circ)->crypto, true);
}
}
diff --git a/src/core/or/server_port_cfg_st.h b/src/core/or/server_port_cfg_st.h
index 9a005eccdf..69cdb29cbc 100644
--- a/src/core/or/server_port_cfg_st.h
+++ b/src/core/or/server_port_cfg_st.h
@@ -6,7 +6,7 @@
/**
* @file server_port_cfg_st.h
- * @brief Cnfiguration structure for server ports.
+ * @brief Configuration structure for server ports.
**/
#ifndef SERVER_PORT_CFG_ST_H
diff --git a/src/core/or/status.c b/src/core/or/status.c
index ed8448883c..00a88a3178 100644
--- a/src/core/or/status.c
+++ b/src/core/or/status.c
@@ -113,6 +113,41 @@ log_onion_service_stats(void)
hs_stats_get_n_rendezvous_launches());
}
+/**
+ * @name connection counts for heartbeat
+ *
+ * Tracks incoming and outgoing connections on IPv4/IPv6, for heartbeat
+ * logs.
+ **/
+/**@{*/
+static unsigned n_incoming_ipv4;
+static unsigned n_incoming_ipv6;
+static unsigned n_outgoing_ipv4;
+static unsigned n_outgoing_ipv6;
+/**@}*/
+
+/**
+ * Note that a connection has arrived or has been made, for use in the
+ * heartbeat message.
+ **/
+void
+note_connection(bool inbound, int family)
+{
+ if (family == AF_INET) {
+ if (inbound) {
+ ++n_incoming_ipv4;
+ } else {
+ ++n_outgoing_ipv4;
+ }
+ } else if (family == AF_INET6) {
+ if (inbound) {
+ ++n_incoming_ipv6;
+ } else {
+ ++n_outgoing_ipv6;
+ }
+ }
+}
+
/** Log a "heartbeat" message describing Tor's status and history so that the
* user can know that there is indeed a running Tor. Return 0 on success and
* -1 on failure. */
@@ -143,8 +178,12 @@ log_heartbeat(time_t now)
bw_sent = bytes_to_usage(get_bytes_written());
log_fn(LOG_NOTICE, LD_HEARTBEAT, "Heartbeat: Tor's uptime is %s, with %d "
- "circuits open. I've sent %s and received %s.%s",
+ "circuits open. I've sent %s and received %s. I've received %u "
+ "connections on IPv4 and %u on IPv6. I've made %u connections "
+ "with IPv4 and %u with IPv6.%s",
uptime, count_circuits(), bw_sent, bw_rcvd,
+ n_incoming_ipv4, n_incoming_ipv6,
+ n_outgoing_ipv4, n_outgoing_ipv6,
hibernating?" We are currently hibernating.":"");
dirclient_dump_total_dls();
diff --git a/src/core/or/status.h b/src/core/or/status.h
index 639f8cdf51..271e0dbc9a 100644
--- a/src/core/or/status.h
+++ b/src/core/or/status.h
@@ -11,6 +11,7 @@
#include "lib/testsupport/testsupport.h"
+void note_connection(bool inbound, int family);
int log_heartbeat(time_t now);
#ifdef STATUS_PRIVATE
diff --git a/src/core/or/trace_probes_circuit.c b/src/core/or/trace_probes_circuit.c
new file mode 100644
index 0000000000..b186ffda7f
--- /dev/null
+++ b/src/core/or/trace_probes_circuit.c
@@ -0,0 +1,30 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file trace_probes_circuit.c
+ * \brief Tracepoint provider source file for the circuit subsystem. Probes
+ * are generated within this C file for LTTng-UST
+ **/
+
+#include "orconfig.h"
+
+/*
+ * Following section is specific to LTTng-UST.
+ */
+#ifdef USE_TRACING_INSTRUMENTATION_LTTNG
+
+/* Header files that the probes need. */
+#include "core/or/circuitlist.h"
+#include "core/or/crypt_path_st.h"
+#include "core/or/extend_info_st.h"
+#include "core/or/or.h"
+#include "core/or/or_circuit_st.h"
+#include "core/or/origin_circuit_st.h"
+
+#define TRACEPOINT_DEFINE
+#define TRACEPOINT_CREATE_PROBES
+
+#include "trace_probes_circuit.h"
+
+#endif /* USE_TRACING_INSTRUMENTATION_LTTNG */
diff --git a/src/core/or/trace_probes_circuit.h b/src/core/or/trace_probes_circuit.h
new file mode 100644
index 0000000000..59f53c324a
--- /dev/null
+++ b/src/core/or/trace_probes_circuit.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file trace_probes_circuit.c
+ * \brief The tracing probes for the circuit subsystem. Currently, only
+ * LTTng-UST probes are available.
+ **/
+
+#ifndef TOR_TRACE_PROBES_CIRCUIT_H
+#define TOR_TRACE_PROBES_CIRCUIT_H
+
+#include "lib/trace/events.h"
+
+/* We only build the following if LTTng instrumentation has been enabled. */
+#ifdef USE_TRACING_INSTRUMENTATION_LTTNG
+
+#include "core/or/lttng_circuit.inc"
+
+#endif /* USE_TRACING_INSTRUMENTATION_LTTNG */
+
+#endif /* TOR_TRACE_PROBES_CIRCUIT_H */
diff --git a/src/core/or/versions.c b/src/core/or/versions.c
index 31f1f5b997..5dfe0c2cc9 100644
--- a/src/core/or/versions.c
+++ b/src/core/or/versions.c
@@ -408,6 +408,10 @@ static strmap_t *protover_summary_map = NULL;
/**
* Helper. Given a non-NULL protover string <b>protocols</b>, set <b>out</b>
* to its summary, and memoize the result in <b>protover_summary_map</b>.
+ *
+ * If the protover string does not contain any recognised protocols, sets
+ * protocols_known, but does not set any other flags. (Empty strings are also
+ * treated this way.)
*/
static void
memoize_protover_summary(protover_summary_flags_t *out,
@@ -434,25 +438,49 @@ memoize_protover_summary(protover_summary_flags_t *out,
memset(out, 0, sizeof(*out));
out->protocols_known = 1;
- out->supports_extend2_cells =
- protocol_list_supports_protocol(protocols, PRT_RELAY, 2);
+
out->supports_ed25519_link_handshake_compat =
- protocol_list_supports_protocol(protocols, PRT_LINKAUTH, 3);
+ protocol_list_supports_protocol(protocols, PRT_LINKAUTH,
+ PROTOVER_LINKAUTH_ED25519_HANDSHAKE);
out->supports_ed25519_link_handshake_any =
- protocol_list_supports_protocol_or_later(protocols, PRT_LINKAUTH, 3);
+ protocol_list_supports_protocol_or_later(
+ protocols,
+ PRT_LINKAUTH,
+ PROTOVER_LINKAUTH_ED25519_HANDSHAKE);
+
+ out->supports_extend2_cells =
+ protocol_list_supports_protocol(protocols, PRT_RELAY,
+ PROTOVER_RELAY_EXTEND2);
+ out->supports_accepting_ipv6_extends = (
+ protocol_list_supports_protocol(protocols, PRT_RELAY,
+ PROTOVER_RELAY_ACCEPT_IPV6) ||
+ protocol_list_supports_protocol(protocols, PRT_RELAY,
+ PROTOVER_RELAY_EXTEND_IPV6));
+ out->supports_initiating_ipv6_extends =
+ protocol_list_supports_protocol(protocols, PRT_RELAY,
+ PROTOVER_RELAY_EXTEND_IPV6);
+ out->supports_canonical_ipv6_conns =
+ protocol_list_supports_protocol(protocols, PRT_RELAY,
+ PROTOVER_RELAY_CANONICAL_IPV6);
+
out->supports_ed25519_hs_intro =
- protocol_list_supports_protocol(protocols, PRT_HSINTRO, 4);
- out->supports_v3_hsdir =
- protocol_list_supports_protocol(protocols, PRT_HSDIR,
- PROTOVER_HSDIR_V3);
+ protocol_list_supports_protocol(protocols, PRT_HSINTRO,
+ PROTOVER_HS_INTRO_V3);
+ out->supports_establish_intro_dos_extension =
+ protocol_list_supports_protocol(protocols, PRT_HSINTRO,
+ PROTOVER_HS_INTRO_DOS);
+
out->supports_v3_rendezvous_point =
protocol_list_supports_protocol(protocols, PRT_HSREND,
PROTOVER_HS_RENDEZVOUS_POINT_V3);
+
+ out->supports_v3_hsdir =
+ protocol_list_supports_protocol(protocols, PRT_HSDIR,
+ PROTOVER_HSDIR_V3);
+
out->supports_hs_setup_padding =
protocol_list_supports_protocol(protocols, PRT_PADDING,
PROTOVER_HS_SETUP_PADDING);
- out->supports_establish_intro_dos_extension =
- protocol_list_supports_protocol(protocols, PRT_HSINTRO, 5);
protover_summary_flags_t *new_cached = tor_memdup(out, sizeof(*out));
cached = strmap_set(protover_summary_map, protocols, new_cached);
@@ -461,6 +489,13 @@ memoize_protover_summary(protover_summary_flags_t *out,
/** Summarize the protocols listed in <b>protocols</b> into <b>out</b>,
* falling back or correcting them based on <b>version</b> as appropriate.
+ *
+ * If protocols and version are both NULL or "", returns a summary with no
+ * flags set.
+ *
+ * If the protover string does not contain any recognised protocols, and the
+ * version is not recognised, sets protocols_known, but does not set any other
+ * flags. (Empty strings are also treated this way.)
*/
void
summarize_protover_flags(protover_summary_flags_t *out,
@@ -469,10 +504,10 @@ summarize_protover_flags(protover_summary_flags_t *out,
{
tor_assert(out);
memset(out, 0, sizeof(*out));
- if (protocols) {
+ if (protocols && strcmp(protocols, "")) {
memoize_protover_summary(out, protocols);
}
- if (version && !strcmpstart(version, "Tor ")) {
+ if (version && strcmp(version, "") && !strcmpstart(version, "Tor ")) {
if (!out->protocols_known) {
/* The version is a "Tor" version, and where there is no
* list of protocol versions that we should be looking at instead. */
diff --git a/src/core/proto/proto_socks.c b/src/core/proto/proto_socks.c
index bcb0c2b2f9..a7ee190b3f 100644
--- a/src/core/proto/proto_socks.c
+++ b/src/core/proto/proto_socks.c
@@ -67,8 +67,8 @@ log_unsafe_socks_warning(int socks_protocol, const char *address,
"Tor only an IP address. Applications that do DNS resolves "
"themselves may leak information. Consider using Socks4A "
"(e.g. via privoxy or socat) instead. For more information, "
- "please see https://wiki.torproject.org/TheOnionRouter/"
- "TorFAQ#SOCKSAndDNS.%s",
+ "please see https://2019.www.torproject.org/docs/faq.html.en"
+ "#WarningsAboutSOCKSandDNSInformationLeaks.%s",
socks_protocol,
(int)port,
safe_socks ? " Rejecting." : "");
@@ -479,7 +479,7 @@ parse_socks5_userpass_auth(const uint8_t *raw_data, socks_request_t *req,
/**
* Validate and respond to SOCKS5 username/password request we
* parsed in parse_socks5_userpass_auth (corresponding to <b>req</b>.
- * Set <b>req->reply</b> to appropriate responsed. Return
+ * Set <b>req->reply</b> to appropriate response. Return
* SOCKS_RESULT_DONE on success or SOCKS_RESULT_INVALID on failure.
*/
static socks_result_t
diff --git a/src/core/stA1RajU b/src/core/stA1RajU
deleted file mode 100644
index e69de29bb2..0000000000
--- a/src/core/stA1RajU
+++ /dev/null
diff --git a/src/core/stiysZND b/src/core/stiysZND
deleted file mode 100644
index faa365b769..0000000000
--- a/src/core/stiysZND
+++ /dev/null
Binary files differ
diff --git a/src/ext/README b/src/ext/README
deleted file mode 100644
index d7e5439c71..0000000000
--- a/src/ext/README
+++ /dev/null
@@ -1,79 +0,0 @@
-
-OpenBSD_malloc_Linux.c:
-
- The OpenBSD malloc implementation, ported to Linux. Used only when
- --enable-openbsd-malloc is passed to the configure script.
-
-strlcat.c
-strlcpy.c
-
- Implementations of strlcat and strlcpy, the more sane replacements
- for strcat and strcpy. These are nonstandard, and some libc
- implementations refuse to add them for religious reasons.
-
-ht.h
-
- An implementation of a hash table in the style of Niels Provos's
- tree.h. Shared with Libevent.
-
-tinytest.[ch]
-tinytest_demos.c
-tinytest_macros.h
-
- A unit testing framework. https://github.com/nmathewson/tinytest
-
-tor_queue.h
-
- A copy of sys/queue.h from OpenBSD. We keep our own copy rather
- than using sys/queue.h, since some platforms don't have a
- sys/queue.h, and the ones that do have diverged in incompatible
- ways. (CIRCLEQ or no CIRCLEQ? SIMPLQ or STAILQ?) We also rename
- the identifiers with a TOR_ prefix to avoid conflicts with
- the system headers.
-
-curve25519_donna/*.c
-
- A copy of Adam Langley's curve25519-donna mostly-portable
- implementations of curve25519.
-
-csiphash.c
-siphash.h
-
- Marek Majkowski's implementation of siphash 2-4, a secure keyed
- hash algorithm to avoid collision-based DoS attacks against hash
- tables.
-
-trunnel/*.[ch]
-
- Headers and runtime code for Trunnel, a system for generating
- code to encode and decode binary formats.
-
-ed25519/ref10/*
-
- Daniel Bernsten's portable ref10 implementation of ed25519.
- Public domain.
-
-ed25519/donna/*
-
- Andrew Moon's semi-portable ed25519-donna implementation of
- ed25519. Public domain.
-
-keccak-tiny/
-
- David Leon Gil's portable Keccak implementation. CC0.
-
-readpassphrase.[ch]
-
- Portable readpassphrase implementation from OpenSSH portable, version
- 6.8p1.
-
-timeouts/
-
- William Ahern's hierarchical timer-wheel implementation. MIT license.
-
-mulodi/
-
- Contains an overflow-checking 64-bit signed integer multiply
- from LLVM's compiler_rt. For some reason, this is missing from
- 32-bit libclang in many places. Dual licensed MIT-license and
- BSD-like license; see mulodi/LICENSE.TXT.
diff --git a/src/ext/curve25519_donna/README b/src/ext/curve25519_donna/README
index 9f77bd7d95..acab07cab9 100644
--- a/src/ext/curve25519_donna/README
+++ b/src/ext/curve25519_donna/README
@@ -6,7 +6,7 @@ If you run `make`, two .a archives will be built, similar to djb's curve25519
code. Alternatively, read on:
The C implementation is contained within curve25519-donna.c. It has no external
-dependancies and is BSD licenced. You can copy/include/link it directly in with
+dependencies and is BSD licenced. You can copy/include/link it directly in with
your program. Recommended C flags: -O2
The x86-64 bit implementation is contained within curve25519-donna-x86-64.c and
diff --git a/src/ext/ed25519/donna/README.md b/src/ext/ed25519/donna/README.md
index e09fc27e31..aa77651bf4 100644
--- a/src/ext/ed25519/donna/README.md
+++ b/src/ext/ed25519/donna/README.md
@@ -1,5 +1,5 @@
[ed25519](http://ed25519.cr.yp.to/) is an
-[Elliptic Curve Digital Signature Algortithm](http://en.wikipedia.org/wiki/Elliptic_Curve_DSA),
+[Elliptic Curve Digital Signature Algorithm](http://en.wikipedia.org/wiki/Elliptic_Curve_DSA),
developed by [Dan Bernstein](http://cr.yp.to/djb.html),
[Niels Duif](http://www.nielsduif.nl/),
[Tanja Lange](http://hyperelliptic.org/tanja),
@@ -56,7 +56,7 @@ No configuration is needed **if you are compiling against OpenSSL**.
##### Hash Options
-If you are not compiling aginst OpenSSL, you will need a hash function.
+If you are not compiling against OpenSSL, you will need a hash function.
To use a simple/**slow** implementation of SHA-512, use `-DED25519_REFHASH` when compiling `ed25519.c`.
This should never be used except to verify the code works when OpenSSL is not available.
@@ -73,7 +73,7 @@ custom hash implementation in ed25519-hash-custom.h. The hash must have a 512bit
##### Random Options
-If you are not compiling aginst OpenSSL, you will need a random function for batch verification.
+If you are not compiling against OpenSSL, you will need a random function for batch verification.
To use a custom random function, use `-DED25519_CUSTOMRANDOM` when compiling `ed25519.c` and put your
custom hash implementation in ed25519-randombytes-custom.h. The random function must implement:
@@ -170,7 +170,7 @@ signing due to both using the same code for the scalar multiply.
#### Testing
-Fuzzing against reference implemenations is now available. See [fuzz/README](fuzz/README.md).
+Fuzzing against reference implementations is now available. See [fuzz/README](fuzz/README.md).
Building `ed25519.c` with `-DED25519_TEST` and linking with `test.c` will run basic sanity tests
and benchmark each function. `test-batch.c` has been incorporated in to `test.c`.
@@ -180,4 +180,4 @@ with extreme values to ensure they function correctly. SSE2 is now supported.
#### Papers
-[Available on the Ed25519 website](http://ed25519.cr.yp.to/papers.html) \ No newline at end of file
+[Available on the Ed25519 website](http://ed25519.cr.yp.to/papers.html)
diff --git a/src/ext/ed25519/donna/ed25519_tor.c b/src/ext/ed25519/donna/ed25519_tor.c
index a5bb6f4e21..4b35c9f634 100644
--- a/src/ext/ed25519/donna/ed25519_tor.c
+++ b/src/ext/ed25519/donna/ed25519_tor.c
@@ -43,6 +43,7 @@
#include "ed25519-randombytes.h"
#include "ed25519-hash.h"
+#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
typedef unsigned char ed25519_signature[64];
diff --git a/src/ext/ed25519/donna/fuzz/build-nix.php b/src/ext/ed25519/donna/fuzz/build-nix.php
index c69144ebc9..7f068922d6 100644
--- a/src/ext/ed25519/donna/fuzz/build-nix.php
+++ b/src/ext/ed25519/donna/fuzz/build-nix.php
@@ -6,7 +6,7 @@
function usage($reason) {
echoln("Usage: php build-nix.php [flags]");
- echoln("Flags in parantheses are optional");
+ echoln("Flags in parentheses are optional");
echoln("");
echoln(" --bits=[32,64]");
echoln(" --function=[curve25519,ed25519]");
diff --git a/src/ext/ed25519/donna/test-internals.c b/src/ext/ed25519/donna/test-internals.c
index fe9db9d669..8afe89d5ed 100644
--- a/src/ext/ed25519/donna/test-internals.c
+++ b/src/ext/ed25519/donna/test-internals.c
@@ -1,4 +1,4 @@
-/* Tor: Removed, file is inclued in ed25519.c instead. */
+/* Tor: Removed, file is included in ed25519.c instead. */
/* #include <stdio.h> */
/* #include "ed25519-donna.h" */
diff --git a/src/ext/ext.md b/src/ext/ext.md
new file mode 100644
index 0000000000..1eaaab605b
--- /dev/null
+++ b/src/ext/ext.md
@@ -0,0 +1,88 @@
+@dir /ext
+@brief Externally maintained code
+
+The "ext" directory holds code that was written elsewhere, and is not
+reliably packaged as a library where we want to build, so we ship
+it along with Tor.
+
+In general, you should not edit this code: we are not the maintainers.
+Instead, you should submit patches upstream.
+
+OpenBSD_malloc_Linux.c:
+
+> The OpenBSD malloc implementation, ported to Linux. Used only when
+> --enable-openbsd-malloc is passed to the configure script.
+
+strlcat.c
+strlcpy.c
+
+> Implementations of strlcat and strlcpy, the more sane replacements
+> for strcat and strcpy. These are nonstandard, and some libc
+> implementations refuse to add them for religious reasons.
+
+ht.h
+
+> An implementation of a hash table in the style of Niels Provos's
+> tree.h. Shared with Libevent.
+
+tinytest.c tinytest.h
+tinytest_demos.c
+tinytest_macros.h
+
+> A unit testing framework. https://github.com/nmathewson/tinytest
+
+tor_queue.h
+
+> A copy of sys/queue.h from OpenBSD. We keep our own copy rather
+> than using sys/queue.h, since some platforms don't have a
+> sys/queue.h, and the ones that do have diverged in incompatible
+> ways. (CIRCLEQ or no CIRCLEQ? SIMPLQ or STAILQ?) We also rename
+> the identifiers with a TOR_ prefix to avoid conflicts with
+> the system headers.
+
+curve25519_donna/*.c
+
+> A copy of Adam Langley's curve25519-donna mostly-portable
+> implementations of curve25519.
+
+csiphash.c
+siphash.h
+
+> Marek Majkowski's implementation of siphash 2-4, a secure keyed
+> hash algorithm to avoid collision-based DoS attacks against hash
+> tables.
+
+trunnel/*.[ch]
+
+> Headers and runtime code for Trunnel, a system for generating
+> code to encode and decode binary formats.
+
+ed25519/ref10/*
+
+> Daniel Bernsten's portable ref10 implementation of ed25519.
+> Public domain.
+
+ed25519/donna/*
+
+> Andrew Moon's semi-portable ed25519-donna implementation of
+> ed25519. Public domain.
+
+keccak-tiny/
+
+> David Leon Gil's portable Keccak implementation. CC0.
+
+readpassphrase.[ch]
+
+> Portable readpassphrase implementation from OpenSSH portable, version
+> 6.8p1.
+
+timeouts/
+
+> William Ahern's hierarchical timer-wheel implementation. MIT license.
+
+mulodi/
+
+> Contains an overflow-checking 64-bit signed integer multiply
+> from LLVM's compiler_rt. For some reason, this is missing from
+> 32-bit libclang in many places. Dual licensed MIT-license and
+> BSD-like license; see mulodi/LICENSE.TXT.
diff --git a/src/ext/include.am b/src/ext/include.am
index 317e25d78e..8b646b1b4e 100644
--- a/src/ext/include.am
+++ b/src/ext/include.am
@@ -1,7 +1,7 @@
AM_CPPFLAGS += -I$(srcdir)/src/ext -Isrc/ext
-EXTRA_DIST += src/ext/README
+EXTRA_DIST += src/ext/ext.md
EXTHEADERS = \
src/ext/ht.h \
diff --git a/src/feature/client/addressmap.c b/src/feature/client/addressmap.c
index 9ad2d7f934..e5bf2cc49c 100644
--- a/src/feature/client/addressmap.c
+++ b/src/feature/client/addressmap.c
@@ -422,7 +422,7 @@ addressmap_rewrite(char *address, size_t maxlen,
goto done;
}
- /* Check wither the flags we were passed tell us not to use this
+ /* Check whether the flags we were passed tell us not to use this
* mapping. */
switch (ent->source) {
case ADDRMAPSRC_DNS:
@@ -515,7 +515,7 @@ addressmap_rewrite_reverse(char *address, size_t maxlen, unsigned flags,
else if (f == AF_INET6 && !(flags & AMR_FLAG_USE_IPV6_DNS))
return 0;
/* FFFF we should reverse-map virtual addresses even if we haven't
- * enabled DNS cacheing. */
+ * enabled DNS caching. */
}
tor_asprintf(&s, "REVERSE[%s]", address);
diff --git a/src/feature/client/bridges.c b/src/feature/client/bridges.c
index 66b04f3bc2..96c3497c6f 100644
--- a/src/feature/client/bridges.c
+++ b/src/feature/client/bridges.c
@@ -164,6 +164,28 @@ bridge_get_addr_port(const bridge_info_t *bridge)
return &bridge->addrport_configured;
}
+/**
+ * Given a <b>bridge</b>, return the transport name. If none were configured,
+ * NULL is returned.
+ */
+const char *
+bridget_get_transport_name(const bridge_info_t *bridge)
+{
+ tor_assert(bridge);
+ return bridge->transport_name;
+}
+
+/**
+ * Return true if @a bridge has a transport name for which we don't actually
+ * know a transport.
+ */
+bool
+bridge_has_invalid_transport(const bridge_info_t *bridge)
+{
+ const char *tname = bridget_get_transport_name(bridge);
+ return tname && transport_get_by_name(tname) == NULL;
+}
+
/** If we have a bridge configured whose digest matches <b>digest</b>, or a
* bridge with no known digest whose address matches any of the
* tor_addr_port_t's in <b>orports</b>, return that bridge. Else return
@@ -249,8 +271,8 @@ get_configured_bridge_by_exact_addr_port_digest(const tor_addr_t *addr,
* address/port matches only. */
int
addr_is_a_configured_bridge(const tor_addr_t *addr,
- uint16_t port,
- const char *digest)
+ uint16_t port,
+ const char *digest)
{
tor_assert(addr);
return get_configured_bridge_by_addr_port_digest(addr, port, digest) ? 1 : 0;
@@ -259,12 +281,26 @@ addr_is_a_configured_bridge(const tor_addr_t *addr,
/** If we have a bridge configured whose digest matches
* <b>ei->identity_digest</b>, or a bridge with no known digest whose address
* matches <b>ei->addr</b>:<b>ei->port</b>, return 1. Else return 0.
- * If <b>ei->onion_key</b> is NULL, check for address/port matches only. */
+ * If <b>ei->onion_key</b> is NULL, check for address/port matches only.
+ *
+ * Note that if the extend_info_t contains multiple addresses, we return true
+ * only if _every_ address is a bridge.
+ */
int
extend_info_is_a_configured_bridge(const extend_info_t *ei)
{
const char *digest = ei->onion_key ? ei->identity_digest : NULL;
- return addr_is_a_configured_bridge(&ei->addr, ei->port, digest);
+ const tor_addr_port_t *ap1 = NULL, *ap2 = NULL;
+ if (! tor_addr_is_null(&ei->orports[0].addr))
+ ap1 = &ei->orports[0];
+ if (! tor_addr_is_null(&ei->orports[1].addr))
+ ap2 = &ei->orports[1];
+ IF_BUG_ONCE(ap1 == NULL) {
+ return 0;
+ }
+ return addr_is_a_configured_bridge(&ap1->addr, ap1->port, digest) &&
+ (ap2 == NULL ||
+ addr_is_a_configured_bridge(&ap2->addr, ap2->port, digest));
}
/** Wrapper around get_configured_bridge_by_addr_port_digest() to look
@@ -289,51 +325,21 @@ routerinfo_is_a_configured_bridge(const routerinfo_t *ri)
}
/**
- * Return 1 iff <b>bridge_list</b> contains entry matching
- * given; IPv4 address in host byte order (<b>ipv4_addr</b>
- * and <b>port</b> (and no identity digest) OR it contains an
- * entry whose identity matches <b>digest</b>. Otherwise,
- * return 0.
- */
-static int
-bridge_exists_with_ipv4h_addr_and_port(const uint32_t ipv4_addr,
- const uint16_t port,
- const char *digest)
-{
- tor_addr_t node_ipv4;
-
- if (tor_addr_port_is_valid_ipv4h(ipv4_addr, port, 0)) {
- tor_addr_from_ipv4h(&node_ipv4, ipv4_addr);
-
- bridge_info_t *bridge =
- get_configured_bridge_by_addr_port_digest(&node_ipv4,
- port,
- digest);
-
- return (bridge != NULL);
- }
-
- return 0;
-}
-
-/**
* Return 1 iff <b>bridge_list</b> contains entry matching given
- * <b>ipv6_addr</b> and <b>port</b> (and no identity digest) OR
+ * <b>addr</b> and <b>port</b> (and no identity digest) OR
* it contains an entry whose identity matches <b>digest</b>.
* Otherwise, return 0.
*/
static int
-bridge_exists_with_ipv6_addr_and_port(const tor_addr_t *ipv6_addr,
- const uint16_t port,
- const char *digest)
+bridge_exists_with_addr_and_port(const tor_addr_t *addr,
+ const uint16_t port,
+ const char *digest)
{
- if (!tor_addr_port_is_valid(ipv6_addr, port, 0))
+ if (!tor_addr_port_is_valid(addr, port, 0))
return 0;
bridge_info_t *bridge =
- get_configured_bridge_by_addr_port_digest(ipv6_addr,
- port,
- digest);
+ get_configured_bridge_by_addr_port_digest(addr, port, digest);
return (bridge != NULL);
}
@@ -360,29 +366,29 @@ node_is_a_configured_bridge(const node_t *node)
* check for absence of identity digest in a bridge.
*/
if (node->ri) {
- if (bridge_exists_with_ipv4h_addr_and_port(node->ri->addr,
- node->ri->or_port,
- node->identity))
+ if (bridge_exists_with_addr_and_port(&node->ri->ipv4_addr,
+ node->ri->ipv4_orport,
+ node->identity))
return 1;
- if (bridge_exists_with_ipv6_addr_and_port(&node->ri->ipv6_addr,
- node->ri->ipv6_orport,
- node->identity))
+ if (bridge_exists_with_addr_and_port(&node->ri->ipv6_addr,
+ node->ri->ipv6_orport,
+ node->identity))
return 1;
} else if (node->rs) {
- if (bridge_exists_with_ipv4h_addr_and_port(node->rs->addr,
- node->rs->or_port,
- node->identity))
+ if (bridge_exists_with_addr_and_port(&node->rs->ipv4_addr,
+ node->rs->ipv4_orport,
+ node->identity))
return 1;
- if (bridge_exists_with_ipv6_addr_and_port(&node->rs->ipv6_addr,
- node->rs->ipv6_orport,
- node->identity))
+ if (bridge_exists_with_addr_and_port(&node->rs->ipv6_addr,
+ node->rs->ipv6_orport,
+ node->identity))
return 1;
} else if (node->md) {
- if (bridge_exists_with_ipv6_addr_and_port(&node->md->ipv6_addr,
- node->md->ipv6_orport,
- node->identity))
+ if (bridge_exists_with_addr_and_port(&node->md->ipv6_addr,
+ node->md->ipv6_orport,
+ node->identity))
return 1;
}
@@ -612,7 +618,7 @@ find_transport_name_by_bridge_addrport(const tor_addr_t *addr, uint16_t port)
*/
int
get_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port,
- const transport_t **transport)
+ const transport_t **transport)
{
*transport = NULL;
if (!bridge_list)
@@ -661,6 +667,15 @@ launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge)
DIR_PURPOSE_FETCH_SERVERDESC))
return; /* it's already on the way */
+ if (bridge_has_invalid_transport(bridge)) {
+ download_status_mark_impossible(&bridge->fetch_status);
+ log_warn(LD_CONFIG, "Can't use bridge at %s: there is no configured "
+ "transport called \"%s\".",
+ safe_str_client(fmt_and_decorate_addr(&bridge->addr)),
+ bridget_get_transport_name(bridge));
+ return; /* Can't use this bridge; it has not */
+ }
+
if (routerset_contains_bridge(options->ExcludeNodes, bridge)) {
download_status_mark_impossible(&bridge->fetch_status);
log_warn(LD_APP, "Not using bridge at %s: it is in ExcludeNodes.",
@@ -670,7 +685,7 @@ launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge)
/* Until we get a descriptor for the bridge, we only know one address for
* it. */
- if (!fascist_firewall_allows_address_addr(&bridge->addr, bridge->port,
+ if (!reachable_addr_allows_addr(&bridge->addr, bridge->port,
FIREWALL_OR_CONNECTION, 0, 0)) {
log_notice(LD_CONFIG, "Tried to fetch a descriptor directly from a "
"bridge, but that bridge is not reachable through our "
@@ -762,7 +777,7 @@ fetch_bridge_descriptors(const or_options_t *options, time_t now)
!options->UpdateBridgesFromAuthority, !num_bridge_auths);
if (ask_bridge_directly &&
- !fascist_firewall_allows_address_addr(&bridge->addr, bridge->port,
+ !reachable_addr_allows_addr(&bridge->addr, bridge->port,
FIREWALL_OR_CONNECTION, 0,
0)) {
log_notice(LD_DIR, "Bridge at '%s' isn't reachable by our "
@@ -811,25 +826,23 @@ rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node)
* do that safely if we know that no function that connects to an OR
* does so through an address from any source other than node_get_addr().
*/
- tor_addr_t addr;
const or_options_t *options = get_options();
if (node->ri) {
routerinfo_t *ri = node->ri;
- tor_addr_from_ipv4h(&addr, ri->addr);
- if ((!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
- bridge->port == ri->or_port) ||
+ if ((!tor_addr_compare(&bridge->addr, &ri->ipv4_addr, CMP_EXACT) &&
+ bridge->port == ri->ipv4_orport) ||
(!tor_addr_compare(&bridge->addr, &ri->ipv6_addr, CMP_EXACT) &&
bridge->port == ri->ipv6_orport)) {
/* they match, so no need to do anything */
} else {
if (tor_addr_family(&bridge->addr) == AF_INET) {
- ri->addr = tor_addr_to_ipv4h(&bridge->addr);
- ri->or_port = bridge->port;
+ tor_addr_copy(&ri->ipv4_addr, &bridge->addr);
+ ri->ipv4_orport = bridge->port;
log_info(LD_DIR,
"Adjusted bridge routerinfo for '%s' to match configured "
"address %s:%d.",
- ri->nickname, fmt_addr32(ri->addr), ri->or_port);
+ ri->nickname, fmt_addr(&ri->ipv4_addr), ri->ipv4_orport);
} else if (tor_addr_family(&bridge->addr) == AF_INET6) {
tor_addr_copy(&ri->ipv6_addr, &bridge->addr);
ri->ipv6_orport = bridge->port;
@@ -850,7 +863,7 @@ rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node)
!tor_addr_is_null(&node->ri->ipv6_addr));
} else {
/* Mark which address to use based on user preference */
- node->ipv6_preferred = (fascist_firewall_prefer_ipv6_orport(options) &&
+ node->ipv6_preferred = (reachable_addr_prefer_ipv6_orport(options) &&
!tor_addr_is_null(&node->ri->ipv6_addr));
}
@@ -872,21 +885,20 @@ rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node)
}
if (node->rs) {
routerstatus_t *rs = node->rs;
- tor_addr_from_ipv4h(&addr, rs->addr);
- if ((!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
- bridge->port == rs->or_port) ||
+ if ((!tor_addr_compare(&bridge->addr, &rs->ipv4_addr, CMP_EXACT) &&
+ bridge->port == rs->ipv4_orport) ||
(!tor_addr_compare(&bridge->addr, &rs->ipv6_addr, CMP_EXACT) &&
bridge->port == rs->ipv6_orport)) {
/* they match, so no need to do anything */
} else {
if (tor_addr_family(&bridge->addr) == AF_INET) {
- rs->addr = tor_addr_to_ipv4h(&bridge->addr);
- rs->or_port = bridge->port;
+ tor_addr_copy(&rs->ipv4_addr, &bridge->addr);
+ rs->ipv4_orport = bridge->port;
log_info(LD_DIR,
"Adjusted bridge routerstatus for '%s' to match "
"configured address %s.",
- rs->nickname, fmt_addrport(&bridge->addr, rs->or_port));
+ rs->nickname, fmt_addrport(&bridge->addr, rs->ipv4_orport));
/* set IPv6 preferences even if there is no ri */
} else if (tor_addr_family(&bridge->addr) == AF_INET6) {
tor_addr_copy(&rs->ipv6_addr, &bridge->addr);
@@ -908,7 +920,7 @@ rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node)
!tor_addr_is_null(&node->rs->ipv6_addr));
} else {
/* Mark which address to use based on user preference */
- node->ipv6_preferred = (fascist_firewall_prefer_ipv6_orport(options) &&
+ node->ipv6_preferred = (reachable_addr_prefer_ipv6_orport(options) &&
!tor_addr_is_null(&node->rs->ipv6_addr));
}
@@ -953,7 +965,7 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
if (!from_cache) {
/* This schedules the re-fetch at a constant interval, which produces
* a pattern of bridge traffic. But it's better than trying all
- * configured briges several times in the first few minutes. */
+ * configured bridges several times in the first few minutes. */
download_status_reset(&bridge->fetch_status);
}
diff --git a/src/feature/client/bridges.h b/src/feature/client/bridges.h
index 174149cf97..f5ecc1b76d 100644
--- a/src/feature/client/bridges.h
+++ b/src/feature/client/bridges.h
@@ -23,6 +23,8 @@ void sweep_bridge_list(void);
const smartlist_t *bridge_list_get(void);
const uint8_t *bridge_get_rsa_id_digest(const bridge_info_t *bridge);
const tor_addr_port_t * bridge_get_addr_port(const bridge_info_t *bridge);
+const char *bridget_get_transport_name(const bridge_info_t *bridge);
+bool bridge_has_invalid_transport(const bridge_info_t *bridge);
bridge_info_t *get_configured_bridge_by_addr_port_digest(
const tor_addr_t *addr,
uint16_t port,
diff --git a/src/feature/client/circpathbias.c b/src/feature/client/circpathbias.c
index 74260171fe..4d27553926 100644
--- a/src/feature/client/circpathbias.c
+++ b/src/feature/client/circpathbias.c
@@ -683,7 +683,7 @@ pathbias_mark_use_success(origin_circuit_t *circ)
}
/**
- * If a stream ever detatches from a circuit in a retriable way,
+ * If a stream ever detaches from a circuit in a retriable way,
* we need to mark this circuit as still needing either another
* successful stream, or in need of a probe.
*
diff --git a/src/feature/client/entrynodes.c b/src/feature/client/entrynodes.c
index 70ef64cc86..82866ea668 100644
--- a/src/feature/client/entrynodes.c
+++ b/src/feature/client/entrynodes.c
@@ -342,7 +342,7 @@ entry_guard_get_pathbias_state(entry_guard_t *guard)
HANDLE_IMPL(entry_guard, entry_guard_t, ATTR_UNUSED STATIC)
-/** Return an interval betweeen 'now' and 'max_backdate' seconds in the past,
+/** Return an interval between 'now' and 'max_backdate' seconds in the past,
* chosen uniformly at random. We use this before recording persistent
* dates, so that we aren't leaking exactly when we recorded it.
*/
@@ -1466,7 +1466,7 @@ node_passes_guard_filter(const or_options_t *options,
!routerset_contains_node(options->EntryNodes, node))
return 0;
- if (!fascist_firewall_allows_node(node, FIREWALL_OR_CONNECTION, 0))
+ if (!reachable_addr_allows_node(node, FIREWALL_OR_CONNECTION, 0))
return 0;
if (node_is_a_configured_bridge(node))
@@ -1492,7 +1492,7 @@ bridge_passes_guard_filter(const or_options_t *options,
/* Ignore entrynodes */
const tor_addr_port_t *addrport = bridge_get_addr_port(bridge);
- if (!fascist_firewall_allows_address_addr(&addrport->addr,
+ if (!reachable_addr_allows_addr(&addrport->addr,
addrport->port,
FIREWALL_OR_CONNECTION,
0, 0))
@@ -1554,7 +1554,7 @@ guard_in_node_family(const entry_guard_t *guard, const node_t *node)
if (get_options()->EnforceDistinctSubnets && guard->bridge_addr) {
tor_addr_t node_addr;
node_get_addr(node, &node_addr);
- if (addrs_in_same_network_family(&node_addr,
+ if (router_addrs_in_same_network(&node_addr,
&guard->bridge_addr->addr)) {
return 1;
}
@@ -1576,12 +1576,12 @@ guard_create_exit_restriction(const uint8_t *exit_id)
}
/** If we have fewer than this many possible usable guards, don't set
- * MD-availability-based restrictions: we might blacklist all of them. */
+ * MD-availability-based restrictions: we might denylist all of them. */
#define MIN_GUARDS_FOR_MD_RESTRICTION 10
/** Return true if we should set md dirserver restrictions. We might not want
* to set those if our guard options are too restricted, since we don't want
- * to blacklist all of them. */
+ * to denylist all of them. */
static int
should_set_md_dirserver_restriction(void)
{
@@ -3359,7 +3359,7 @@ get_guard_state_for_bridge_desc_fetch(const char *digest)
}
/* Update the guard last_tried_to_connect time since it's checked by the
- * guard susbsystem. */
+ * guard subsystem. */
guard->last_tried_to_connect = approx_time();
/* Create the guard state */
diff --git a/src/feature/client/transports.c b/src/feature/client/transports.c
index 2bdc0ae151..4b05d55494 100644
--- a/src/feature/client/transports.c
+++ b/src/feature/client/transports.c
@@ -16,7 +16,7 @@
* managed proxies that are still unconfigured.
*
* In every run_scheduled_event() tick, we attempt to launch and then
- * configure the unconfiged managed proxies, using the configuration
+ * configure the unconfigured managed proxies, using the configuration
* protocol defined in the 180_pluggable_transport.txt proposal. A
* managed proxy might need several ticks to get fully configured.
*
@@ -71,7 +71,7 @@
*
* We then start parsing torrc again.
*
- * Everytime we encounter a transport line using a managed proxy that
+ * Every time we encounter a transport line using a managed proxy that
* was around before the config read, we cleanse that proxy from the
* removal mark. We also toggle the <b>check_if_restarts_needed</b>
* flag, so that on the next <b>pt_configure_remaining_proxies</b>
@@ -368,6 +368,28 @@ static int unconfigured_proxies_n = 0;
/** Boolean: True iff we might need to restart some proxies. */
static int check_if_restarts_needed = 0;
+/** Return true iff we have a managed_proxy_t in the global list is for the
+ * given transport name. */
+bool
+managed_proxy_has_transport(const char *transport_name)
+{
+ tor_assert(transport_name);
+
+ if (!managed_proxy_list) {
+ return false;
+ }
+
+ SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
+ SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, const char *, name) {
+ if (!strcasecmp(name, transport_name)) {
+ return true;
+ }
+ } SMARTLIST_FOREACH_END(name);
+ } SMARTLIST_FOREACH_END(mp);
+
+ return false;
+}
+
/** Return true if there are still unconfigured managed proxies, or proxies
* that need restarting. */
int
@@ -1447,6 +1469,37 @@ create_managed_proxy_environment(const managed_proxy_t *mp)
*/
smartlist_add_asprintf(envs, "TOR_PT_EXIT_ON_STDIN_CLOSE=1");
+ /* Specify which IPv4 and IPv6 addresses the PT should make its outgoing
+ * connections from. See: https://bugs.torproject.org/5304 for more
+ * information about this. */
+ {
+ /* Set TOR_PT_OUTBOUND_BIND_ADDRESS_V4. */
+ const tor_addr_t *ipv4_addr = managed_proxy_outbound_address(options,
+ AF_INET);
+
+ /* managed_proxy_outbound_address() only returns a non-NULL value if
+ * tor_addr_is_null() was false, which means we don't have to check that
+ * here. */
+ if (ipv4_addr) {
+ char *ipv4_addr_str = tor_addr_to_str_dup(ipv4_addr);
+ smartlist_add_asprintf(envs,
+ "TOR_PT_OUTBOUND_BIND_ADDRESS_V4=%s",
+ ipv4_addr_str);
+ tor_free(ipv4_addr_str);
+ }
+
+ /* Set TOR_PT_OUTBOUND_BIND_ADDRESS_V6. */
+ const tor_addr_t *ipv6_addr = managed_proxy_outbound_address(options,
+ AF_INET6);
+ if (ipv6_addr) {
+ char *ipv6_addr_str = tor_addr_to_str_dup(ipv6_addr);
+ smartlist_add_asprintf(envs,
+ "TOR_PT_OUTBOUND_BIND_ADDRESS_V6=[%s]",
+ ipv6_addr_str);
+ tor_free(ipv6_addr_str);
+ }
+ }
+
SMARTLIST_FOREACH_BEGIN(envs, const char *, env_var) {
set_environment_variable_in_smartlist(merged_env_vars, env_var,
tor_free_, 1);
@@ -1643,17 +1696,26 @@ pt_get_extra_info_descriptor_string(void)
SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
char *transport_args = NULL;
+ const char *addrport = NULL;
/* If the transport proxy returned "0.0.0.0" as its address, and
* we know our external IP address, use it. Otherwise, use the
* returned address. */
- const char *addrport = NULL;
- uint32_t external_ip_address = 0;
- if (tor_addr_is_null(&t->addr) &&
- router_pick_published_address(get_options(),
- &external_ip_address, 0) >= 0) {
+ if (tor_addr_is_null(&t->addr)) {
tor_addr_t addr;
- tor_addr_from_ipv4h(&addr, external_ip_address);
+ /* Attempt to find the IPv4 and then attempt to find the IPv6 if we
+ * can't find it. */
+ bool found = relay_find_addr_to_publish(get_options(), AF_INET,
+ RELAY_FIND_ADDR_NO_FLAG,
+ &addr);
+ if (!found) {
+ found = relay_find_addr_to_publish(get_options(), AF_INET6,
+ RELAY_FIND_ADDR_NO_FLAG, &addr);
+ }
+ if (!found) {
+ log_err(LD_PT, "Unable to find address for transport %s", t->name);
+ continue;
+ }
addrport = fmt_addrport(&addr, t->port);
} else {
addrport = fmt_addrport(&t->addr, t->port);
@@ -1910,3 +1972,46 @@ managed_proxy_severity_parse(const char *severity)
return -1;
}
+
+/** Return the outbound address from the given <b>family</b>. Returns NULL if
+ * the user haven't specified a specific outbound address in either
+ * OutboundBindAddress or OutboundBindAddressPT. */
+STATIC const tor_addr_t *
+managed_proxy_outbound_address(const or_options_t *options, sa_family_t family)
+{
+ tor_assert(options);
+
+ const tor_addr_t *address = NULL;
+ int family_index;
+
+ switch (family) {
+ case AF_INET:
+ family_index = 0;
+ break;
+ case AF_INET6:
+ family_index = 1;
+ break;
+ default:
+ /* LCOV_EXCL_START */
+ tor_assert_unreached();
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ /* We start by checking if the user specified an address in
+ * OutboundBindAddressPT. */
+ address = &options->OutboundBindAddresses[OUTBOUND_ADDR_PT][family_index];
+
+ if (! tor_addr_is_null(address))
+ return address;
+
+ /* We fallback to check if the user specified an address in
+ * OutboundBindAddress. */
+ address = &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY][family_index];
+
+ if (! tor_addr_is_null(address))
+ return address;
+
+ /* The user have not specified a preference for outgoing connections. */
+ return NULL;
+}
diff --git a/src/feature/client/transports.h b/src/feature/client/transports.h
index 1ed942c175..47b118e77b 100644
--- a/src/feature/client/transports.h
+++ b/src/feature/client/transports.h
@@ -41,6 +41,7 @@ void transport_free_(transport_t *transport);
#define transport_free(tr) FREE_AND_NULL(transport_t, transport_free_, (tr))
MOCK_DECL(transport_t*, transport_get_by_name, (const char *name));
+bool managed_proxy_has_transport(const char *transport_name);
MOCK_DECL(void, pt_kickstart_proxy,
(const smartlist_t *transport_list, char **proxy_argv,
@@ -149,6 +150,8 @@ STATIC void managed_proxy_stderr_callback(process_t *, const char *, size_t);
STATIC bool managed_proxy_exit_callback(process_t *, process_exit_code_t);
STATIC int managed_proxy_severity_parse(const char *);
+STATIC const tor_addr_t *managed_proxy_outbound_address(const or_options_t *,
+ sa_family_t);
#endif /* defined(PT_PRIVATE) */
diff --git a/src/feature/control/control.c b/src/feature/control/control.c
index ee1026359d..2aebe1aac6 100644
--- a/src/feature/control/control.c
+++ b/src/feature/control/control.c
@@ -61,8 +61,12 @@
#include <sys/stat.h>
#endif
-/** Convert a connection_t* to an control_connection_t*; assert if the cast is
- * invalid. */
+/**
+ * Cast a `connection_t *` to a `control_connection_t *`.
+ *
+ * Exit with an assertion failure if the input is not a
+ * `control_connection_t`.
+ **/
control_connection_t *
TO_CONTROL_CONN(connection_t *c)
{
@@ -70,6 +74,18 @@ TO_CONTROL_CONN(connection_t *c)
return DOWNCAST(control_connection_t, c);
}
+/**
+ * Cast a `const connection_t *` to a `const control_connection_t *`.
+ *
+ * Exit with an assertion failure if the input is not a
+ * `control_connection_t`.
+ **/
+const control_connection_t *
+CONST_TO_CONTROL_CONN(const connection_t *c)
+{
+ return TO_CONTROL_CONN((connection_t*)c);
+}
+
/** Create and add a new controller connection on <b>sock</b>. If
* <b>CC_LOCAL_FD_IS_OWNER</b> is set in <b>flags</b>, this Tor process should
* exit when the connection closes. If <b>CC_LOCAL_FD_IS_AUTHENTICATED</b>
@@ -264,7 +280,7 @@ is_valid_initial_command(control_connection_t *conn, const char *cmd)
#define MAX_COMMAND_LINE_LENGTH (1024*1024)
/** Wrapper around peek_buf_has_control0 command: presents the same
- * interface as that underlying functions, but takes a connection_t intead of
+ * interface as that underlying functions, but takes a connection_t instead of
* a buf_t.
*/
static int
diff --git a/src/feature/control/control.h b/src/feature/control/control.h
index 7e72b2736b..f884286ec7 100644
--- a/src/feature/control/control.h
+++ b/src/feature/control/control.h
@@ -13,6 +13,7 @@
#define TOR_CONTROL_H
control_connection_t *TO_CONTROL_CONN(connection_t *);
+const control_connection_t *CONST_TO_CONTROL_CONN(const connection_t *);
#define CONTROL_CONN_STATE_MIN_ 1
/** State for a control connection: Authenticated and accepting v1 commands. */
diff --git a/src/feature/control/control_bootstrap.c b/src/feature/control/control_bootstrap.c
index fee7612ba2..d6dfdad94e 100644
--- a/src/feature/control/control_bootstrap.c
+++ b/src/feature/control/control_bootstrap.c
@@ -274,7 +274,7 @@ control_event_bootstrap_problem(const char *warn, const char *reason,
const char *recommendation = "ignore";
int severity;
char *or_id = NULL, *hostaddr = NULL;
- or_connection_t *or_conn = NULL;
+ const or_connection_t *or_conn = NULL;
/* bootstrap_percent must not be in "undefined" state here. */
tor_assert(status >= 0);
@@ -301,7 +301,7 @@ control_event_bootstrap_problem(const char *warn, const char *reason,
if (conn && conn->type == CONN_TYPE_OR) {
/* XXX TO_OR_CONN can't deal with const */
- or_conn = TO_OR_CONN((connection_t *)conn);
+ or_conn = CONST_TO_OR_CONN(conn);
or_id = tor_strdup(hex_str(or_conn->identity_digest, DIGEST_LEN));
} else {
or_id = tor_strdup("?");
@@ -348,6 +348,18 @@ control_event_bootstrap_prob_or, (const char *warn, int reason,
{
int dowarn = 0;
+ if (! or_conn->potentially_used_for_bootstrapping) {
+ /* We never decided that this channel was a good match for one of our
+ * origin_circuit_t objects. That means that we probably launched it
+ * for somebody else, most likely in response to an EXTEND cell.
+ *
+ * Since EXTEND cells can contain arbitrarily broken descriptions of
+ * relays, a failure on this connection here won't necessarily indicate a
+ * bootstrapping problem.
+ */
+ return;
+ }
+
if (or_conn->have_noted_bootstrap_problem)
return;
diff --git a/src/feature/control/control_cmd.c b/src/feature/control/control_cmd.c
index eb14f101e7..0456d709f5 100644
--- a/src/feature/control/control_cmd.c
+++ b/src/feature/control/control_cmd.c
@@ -20,6 +20,8 @@
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
#include "core/or/connection_edge.h"
+#include "core/or/circuitstats.h"
+#include "core/or/extendinfo.h"
#include "feature/client/addressmap.h"
#include "feature/client/dnsserv.h"
#include "feature/client/entrynodes.h"
@@ -55,6 +57,8 @@
#include "feature/rend/rend_encoded_v2_service_descriptor_st.h"
#include "feature/rend/rend_service_descriptor_st.h"
+#include "src/app/config/statefile.h"
+
static int control_setconf_helper(control_connection_t *conn,
const control_cmd_args_t *args,
int use_defaults);
@@ -815,6 +819,7 @@ handle_control_extendcircuit(control_connection_t *conn,
if (zero_circ) {
/* start a new circuit */
circ = origin_circuit_init(intended_purpose, 0);
+ circ->first_hop_from_controller = 1;
}
/* now circ refers to something that is ready to be extended */
@@ -977,8 +982,7 @@ handle_control_attachstream(control_connection_t *conn,
edge_conn->end_reason = 0;
if (tmpcirc)
circuit_detach_stream(tmpcirc, edge_conn);
- CONNECTION_AP_EXPECT_NONPENDING(ap_conn);
- TO_CONN(edge_conn)->state = AP_CONN_STATE_CONTROLLER_WAIT;
+ connection_entry_set_controller_wait(ap_conn);
}
if (circ && (circ->base_.state != CIRCUIT_STATE_OPEN)) {
@@ -1396,6 +1400,34 @@ handle_control_dropguards(control_connection_t *conn,
return 0;
}
+static const control_cmd_syntax_t droptimeouts_syntax = {
+ .max_args = 0,
+};
+
+/** Implementation for the DROPTIMEOUTS command. */
+static int
+handle_control_droptimeouts(control_connection_t *conn,
+ const control_cmd_args_t *args)
+{
+ (void) args; /* We don't take arguments. */
+
+ static int have_warned = 0;
+ if (! have_warned) {
+ log_warn(LD_CONTROL, "DROPTIMEOUTS is dangerous; make sure you understand "
+ "the risks before using it. It may be removed in a future "
+ "version of Tor.");
+ have_warned = 1;
+ }
+
+ circuit_build_times_reset(get_circuit_build_times_mutable());
+ send_control_done(conn);
+ or_state_mark_dirty(get_or_state(), 0);
+ cbt_control_event_buildtimeout_set(get_circuit_build_times(),
+ BUILDTIMEOUT_SET_EVENT_RESET);
+
+ return 0;
+}
+
static const char *hsfetch_keywords[] = {
"SERVER", NULL,
};
@@ -2331,6 +2363,7 @@ static const control_cmd_def_t CONTROL_COMMANDS[] =
ONE_LINE(protocolinfo, 0),
ONE_LINE(authchallenge, CMD_FL_WIPE),
ONE_LINE(dropguards, 0),
+ ONE_LINE(droptimeouts, 0),
ONE_LINE(hsfetch, 0),
MULTLINE(hspost, 0),
ONE_LINE(add_onion, CMD_FL_WIPE),
diff --git a/src/feature/control/control_events.c b/src/feature/control/control_events.c
index 916ccea875..0dd52659ec 100644
--- a/src/feature/control/control_events.c
+++ b/src/feature/control/control_events.c
@@ -17,6 +17,7 @@
#include "core/mainloop/mainloop.h"
#include "core/or/channeltls.h"
#include "core/or/circuitlist.h"
+#include "core/or/circuitstats.h"
#include "core/or/command.h"
#include "core/or/connection_edge.h"
#include "core/or/connection_or.h"
@@ -141,6 +142,64 @@ clear_circ_bw_fields(void)
SMARTLIST_FOREACH_END(circ);
}
+/* Helper to emit the BUILDTIMEOUT_SET circuit build time event */
+void
+cbt_control_event_buildtimeout_set(const circuit_build_times_t *cbt,
+ buildtimeout_set_event_t type)
+{
+ char *args = NULL;
+ double qnt;
+ double timeout_rate = 0.0;
+ double close_rate = 0.0;
+
+ switch (type) {
+ case BUILDTIMEOUT_SET_EVENT_RESET:
+ case BUILDTIMEOUT_SET_EVENT_SUSPENDED:
+ case BUILDTIMEOUT_SET_EVENT_DISCARD:
+ qnt = 1.0;
+ break;
+ case BUILDTIMEOUT_SET_EVENT_COMPUTED:
+ case BUILDTIMEOUT_SET_EVENT_RESUME:
+ default:
+ qnt = circuit_build_times_quantile_cutoff();
+ break;
+ }
+
+ /* The timeout rate is the ratio of the timeout count over
+ * the total number of circuits attempted. The total number of
+ * circuits is (timeouts+succeeded), since every circuit
+ * either succeeds, or times out. "Closed" circuits are
+ * MEASURE_TIMEOUT circuits whose measurement period expired.
+ * All MEASURE_TIMEOUT circuits are counted in the timeouts stat
+ * before transitioning to MEASURE_TIMEOUT (in
+ * circuit_build_times_mark_circ_as_measurement_only()).
+ * MEASURE_TIMEOUT circuits that succeed are *not* counted as
+ * "succeeded". See circuit_build_times_handle_completed_hop().
+ *
+ * We cast the denominator
+ * to promote it to double before the addition, to avoid int32
+ * overflow. */
+ const double total_circuits =
+ ((double)cbt->num_circ_timeouts) + cbt->num_circ_succeeded;
+ if (total_circuits >= 1.0) {
+ timeout_rate = cbt->num_circ_timeouts / total_circuits;
+ close_rate = cbt->num_circ_closed / total_circuits;
+ }
+
+ tor_asprintf(&args, "TOTAL_TIMES=%lu "
+ "TIMEOUT_MS=%lu XM=%lu ALPHA=%f CUTOFF_QUANTILE=%f "
+ "TIMEOUT_RATE=%f CLOSE_MS=%lu CLOSE_RATE=%f",
+ (unsigned long)cbt->total_build_times,
+ (unsigned long)cbt->timeout_ms,
+ (unsigned long)cbt->Xm, cbt->alpha, qnt,
+ timeout_rate,
+ (unsigned long)cbt->close_ms,
+ close_rate);
+
+ control_event_buildtimeout_set(type, args);
+
+ tor_free(args);
+}
/** Set <b>global_event_mask*</b> to the bitwise OR of each live control
* connection's event_mask field. */
void
@@ -759,6 +818,7 @@ control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp,
case STREAM_EVENT_NEW_RESOLVE: status = "NEWRESOLVE"; break;
case STREAM_EVENT_FAILED_RETRIABLE: status = "DETACHED"; break;
case STREAM_EVENT_REMAP: status = "REMAP"; break;
+ case STREAM_EVENT_CONTROLLER_WAIT: status = "CONTROLLER_WAIT"; break;
default:
log_warn(LD_BUG, "Unrecognized status code %d", (int)tp);
return 0;
@@ -1292,6 +1352,27 @@ enable_control_logging(void)
tor_assert(0);
}
+/** Remove newline and carriage-return characters from @a msg, replacing them
+ * with spaces, and discarding any that appear at the end of the message */
+void
+control_logmsg_strip_newlines(char *msg)
+{
+ char *cp;
+ for (cp = msg; *cp; ++cp) {
+ if (*cp == '\r' || *cp == '\n') {
+ *cp = ' ';
+ }
+ }
+ if (cp == msg)
+ return;
+ /* Remove trailing spaces */
+ for (--cp; *cp == ' '; --cp) {
+ *cp = '\0';
+ if (cp == msg)
+ break;
+ }
+}
+
/** We got a log message: tell any interested control connections. */
void
control_event_logmsg(int severity, log_domain_mask_t domain, const char *msg)
@@ -1320,11 +1401,8 @@ control_event_logmsg(int severity, log_domain_mask_t domain, const char *msg)
char *b = NULL;
const char *s;
if (strchr(msg, '\n')) {
- char *cp;
b = tor_strdup(msg);
- for (cp = b; *cp; ++cp)
- if (*cp == '\r' || *cp == '\n')
- *cp = ' ';
+ control_logmsg_strip_newlines(b);
}
switch (severity) {
case LOG_DEBUG: s = "DEBUG"; break;
diff --git a/src/feature/control/control_events.h b/src/feature/control/control_events.h
index 4a5492b510..0ac233cc6e 100644
--- a/src/feature/control/control_events.h
+++ b/src/feature/control/control_events.h
@@ -36,7 +36,8 @@ typedef enum stream_status_event_t {
STREAM_EVENT_NEW = 5,
STREAM_EVENT_NEW_RESOLVE = 6,
STREAM_EVENT_FAILED_RETRIABLE = 7,
- STREAM_EVENT_REMAP = 8
+ STREAM_EVENT_REMAP = 8,
+ STREAM_EVENT_CONTROLLER_WAIT = 9
} stream_status_event_t;
/** Used to indicate the type of a buildtime event */
@@ -223,6 +224,10 @@ void control_event_hs_descriptor_content(const char *onion_address,
const char *desc_id,
const char *hsdir_fp,
const char *content);
+void cbt_control_event_buildtimeout_set(const circuit_build_times_t *cbt,
+ buildtimeout_set_event_t type);
+
+int control_event_enter_controller_wait(void);
void control_events_free_all(void);
@@ -336,6 +341,8 @@ struct control_event_t {
extern const struct control_event_t control_event_table[];
+void control_logmsg_strip_newlines(char *msg);
+
#ifdef TOR_UNIT_TESTS
MOCK_DECL(STATIC void,
send_control_event_string,(uint16_t event, const char *msg));
diff --git a/src/feature/control/control_fmt.c b/src/feature/control/control_fmt.c
index d76e6ad8dd..014427c5b5 100644
--- a/src/feature/control/control_fmt.c
+++ b/src/feature/control/control_fmt.c
@@ -206,6 +206,8 @@ entry_connection_describe_status_for_controller(const entry_connection_t *conn)
case CONN_TYPE_AP_DNS_LISTENER: client_protocol = "DNS"; break;
case CONN_TYPE_AP_HTTP_CONNECT_LISTENER:
client_protocol = "HTTPCONNECT"; break;
+ case CONN_TYPE_METRICS_LISTENER:
+ client_protocol = "METRICS"; break;
default: client_protocol = "UNKNOWN";
}
smartlist_add_asprintf(descparts, "CLIENT_PROTOCOL=%s",
diff --git a/src/feature/control/control_getinfo.c b/src/feature/control/control_getinfo.c
index 0823acbe07..5feadd23d1 100644
--- a/src/feature/control/control_getinfo.c
+++ b/src/feature/control/control_getinfo.c
@@ -29,7 +29,6 @@
#include "feature/control/control_fmt.h"
#include "feature/control/control_getinfo.h"
#include "feature/control/control_proto.h"
-#include "feature/control/fmt_serverstatus.h"
#include "feature/control/getinfo_geoip.h"
#include "feature/dircache/dirserv.h"
#include "feature/dirclient/dirclient.h"
@@ -51,6 +50,7 @@
#include "feature/rend/rendcache.h"
#include "feature/stats/geoip_stats.h"
#include "feature/stats/predict_ports.h"
+#include "feature/stats/rephist.h"
#include "lib/version/torversion.h"
#include "lib/encoding/kvline.h"
@@ -130,13 +130,23 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
smartlist_free(signal_names);
} else if (!strcmp(question, "features/names")) {
*answer = tor_strdup("VERBOSE_NAMES EXTENDED_EVENTS");
- } else if (!strcmp(question, "address")) {
- uint32_t addr;
- if (router_pick_published_address(get_options(), &addr, 0) < 0) {
+ } else if (!strcmp(question, "address") || !strcmp(question, "address/v4")) {
+ tor_addr_t addr;
+ if (!relay_find_addr_to_publish(get_options(), AF_INET,
+ RELAY_FIND_ADDR_CACHE_ONLY, &addr)) {
*errmsg = "Address unknown";
return -1;
}
- *answer = tor_dup_ip(addr);
+ *answer = tor_addr_to_str_dup(&addr);
+ tor_assert_nonfatal(*answer);
+ } else if (!strcmp(question, "address/v6")) {
+ tor_addr_t addr;
+ if (!relay_find_addr_to_publish(get_options(), AF_INET6,
+ RELAY_FIND_ADDR_CACHE_ONLY, &addr)) {
+ *errmsg = "Address unknown";
+ return -1;
+ }
+ *answer = tor_addr_to_str_dup(&addr);
tor_assert_nonfatal(*answer);
} else if (!strcmp(question, "traffic/read")) {
tor_asprintf(answer, "%"PRIu64, (get_bytes_read()));
@@ -276,6 +286,8 @@ getinfo_helper_listeners(control_connection_t *control_conn,
type = CONN_TYPE_AP_DNS_LISTENER;
else if (!strcmp(question, "net/listeners/control"))
type = CONN_TYPE_CONTROL_LISTENER;
+ else if (!strcmp(question, "net/listeners/metrics"))
+ type = CONN_TYPE_METRICS_LISTENER;
else
return 0; /* unknown key */
@@ -708,18 +720,6 @@ getinfo_helper_dir(control_connection_t *control_conn,
if (consensus_result < 0) {
return -1;
}
- } else if (!strcmp(question, "network-status")) { /* v1 */
- static int network_status_warned = 0;
- if (!network_status_warned) {
- log_warn(LD_CONTROL, "GETINFO network-status is deprecated; it will "
- "go away in a future version of Tor.");
- network_status_warned = 1;
- }
- routerlist_t *routerlist = router_get_routerlist();
- if (!routerlist || !routerlist->routers ||
- list_server_status_v1(routerlist->routers, answer, 1) < 0) {
- return -1;
- }
} else if (!strcmpstart(question, "extra-info/digest/")) {
question += strlen("extra-info/digest/");
if (strlen(question) == HEX_DIGEST_LEN) {
@@ -1278,15 +1278,18 @@ getinfo_helper_events(control_connection_t *control_conn,
*answer = tor_strdup(directories_have_accepted_server_descriptor()
? "1" : "0");
} else if (!strcmp(question, "status/reachability-succeeded/or")) {
- *answer = tor_strdup(check_whether_orport_reachable(options) ?
- "1" : "0");
+ *answer = tor_strdup(
+ router_all_orports_seem_reachable(options) ?
+ "1" : "0");
} else if (!strcmp(question, "status/reachability-succeeded/dir")) {
- *answer = tor_strdup(check_whether_dirport_reachable(options) ?
- "1" : "0");
+ *answer = tor_strdup(
+ router_dirport_seems_reachable(options) ?
+ "1" : "0");
} else if (!strcmp(question, "status/reachability-succeeded")) {
- tor_asprintf(answer, "OR=%d DIR=%d",
- check_whether_orport_reachable(options) ? 1 : 0,
- check_whether_dirport_reachable(options) ? 1 : 0);
+ tor_asprintf(
+ answer, "OR=%d DIR=%d",
+ router_all_orports_seem_reachable(options) ? 1 : 0,
+ router_dirport_seems_reachable(options) ? 1 : 0);
} else if (!strcmp(question, "status/bootstrap-phase")) {
*answer = control_event_boot_last_msg();
} else if (!strcmpstart(question, "status/version/")) {
@@ -1437,6 +1440,39 @@ getinfo_helper_liveness(control_connection_t *control_conn,
return 0;
}
+/** Implementation helper for GETINFO: answers queries about circuit onion
+ * handshake rephist values */
+STATIC int
+getinfo_helper_rephist(control_connection_t *control_conn,
+ const char *question, char **answer,
+ const char **errmsg)
+{
+ (void) control_conn;
+ (void) errmsg;
+ int result;
+
+ if (!strcmp(question, "stats/ntor/assigned")) {
+ result =
+ rep_hist_get_circuit_handshake_assigned(ONION_HANDSHAKE_TYPE_NTOR);
+ } else if (!strcmp(question, "stats/ntor/requested")) {
+ result =
+ rep_hist_get_circuit_handshake_requested(ONION_HANDSHAKE_TYPE_NTOR);
+ } else if (!strcmp(question, "stats/tap/assigned")) {
+ result =
+ rep_hist_get_circuit_handshake_assigned(ONION_HANDSHAKE_TYPE_TAP);
+ } else if (!strcmp(question, "stats/tap/requested")) {
+ result =
+ rep_hist_get_circuit_handshake_requested(ONION_HANDSHAKE_TYPE_TAP);
+ } else {
+ *errmsg = "Unrecognized handshake type";
+ return -1;
+ }
+
+ tor_asprintf(answer, "%d", result);
+
+ return 0;
+}
+
/** Implementation helper for GETINFO: answers queries about shared random
* value. */
static int
@@ -1625,6 +1661,10 @@ static const getinfo_item_t getinfo_items[] = {
DOC("status/version/recommended", "List of currently recommended versions."),
DOC("status/version/current", "Status of the current version."),
ITEM("address", misc, "IP address of this Tor host, if we can guess it."),
+ ITEM("address/v4", misc,
+ "IPv4 address of this Tor host, if we can guess it."),
+ ITEM("address/v6", misc,
+ "IPv6 address of this Tor host, if we can guess it."),
ITEM("traffic/read", misc,"Bytes read since the process was started."),
ITEM("traffic/written", misc,
"Bytes written since the process was started."),
@@ -1661,6 +1701,16 @@ static const getinfo_item_t getinfo_items[] = {
"Onion services detached from the control connection."),
ITEM("sr/current", sr, "Get current shared random value."),
ITEM("sr/previous", sr, "Get previous shared random value."),
+ PREFIX("stats/ntor/", rephist, "NTor circuit handshake stats."),
+ ITEM("stats/ntor/assigned", rephist,
+ "Assigned NTor circuit handshake stats."),
+ ITEM("stats/ntor/requested", rephist,
+ "Requested NTor circuit handshake stats."),
+ PREFIX("stats/tap/", rephist, "TAP circuit handshake stats."),
+ ITEM("stats/tap/assigned", rephist,
+ "Assigned TAP circuit handshake stats."),
+ ITEM("stats/tap/requested", rephist,
+ "Requested TAP circuit handshake stats."),
{ NULL, NULL, NULL, 0 }
};
diff --git a/src/feature/control/control_getinfo.h b/src/feature/control/control_getinfo.h
index 0ada49258e..f61d632446 100644
--- a/src/feature/control/control_getinfo.h
+++ b/src/feature/control/control_getinfo.h
@@ -60,6 +60,10 @@ STATIC int getinfo_helper_current_time(
control_connection_t *control_conn,
const char *question, char **answer,
const char **errmsg);
+STATIC int getinfo_helper_rephist(
+ control_connection_t *control_conn,
+ const char *question, char **answer,
+ const char **errmsg);
#endif /* defined(CONTROL_GETINFO_PRIVATE) */
#endif /* !defined(TOR_CONTROL_GETINFO_H) */
diff --git a/src/feature/control/fmt_serverstatus.c b/src/feature/control/fmt_serverstatus.c
deleted file mode 100644
index ed9ad95ce2..0000000000
--- a/src/feature/control/fmt_serverstatus.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/* 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 fmt_serverstatus.c
- * @brief Format relay info for a controller.
- **/
-
-#include "core/or/or.h"
-#include "feature/control/fmt_serverstatus.h"
-
-#include "app/config/config.h"
-#include "feature/dirauth/authmode.h"
-#include "feature/dirauth/voteflags.h"// XXXX remove
-#include "feature/nodelist/describe.h"
-#include "feature/nodelist/nodelist.h"
-
-#include "feature/nodelist/node_st.h"
-#include "feature/nodelist/routerinfo_st.h"
-
-/**
- * Allocate and return a description of the status of the server <b>desc</b>,
- * for use in a v1-style router-status line. The server is listed
- * as running iff <b>is_live</b> is true.
- *
- * This is deprecated: it's only used for controllers that want outputs in
- * the old format.
- */
-static char *
-list_single_server_status(const routerinfo_t *desc, int is_live)
-{
- char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */
- char *cp;
- const node_t *node;
-
- tor_assert(desc);
-
- cp = buf;
- if (!is_live) {
- *cp++ = '!';
- }
- node = node_get_by_id(desc->cache_info.identity_digest);
- if (node && node->is_valid) {
- strlcpy(cp, desc->nickname, sizeof(buf)-(cp-buf));
- cp += strlen(cp);
- *cp++ = '=';
- }
- *cp++ = '$';
- base16_encode(cp, HEX_DIGEST_LEN+1, desc->cache_info.identity_digest,
- DIGEST_LEN);
- return tor_strdup(buf);
-}
-
-/** Based on the routerinfo_ts in <b>routers</b>, allocate the
- * contents of a v1-style router-status line, and store it in
- * *<b>router_status_out</b>. Return 0 on success, -1 on failure.
- *
- * If for_controller is true, include the routers with very old descriptors.
- *
- * This is deprecated: it's only used for controllers that want outputs in
- * the old format.
- */
-int
-list_server_status_v1(smartlist_t *routers, char **router_status_out,
- int for_controller)
-{
- /* List of entries in a router-status style: An optional !, then an optional
- * equals-suffixed nickname, then a dollar-prefixed hexdigest. */
- smartlist_t *rs_entries;
- time_t now = time(NULL);
- time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
- /* We include v2 dir auths here too, because they need to answer
- * controllers. Eventually we'll deprecate this whole function;
- * see also networkstatus_getinfo_by_purpose(). */
- tor_assert(router_status_out);
-
- rs_entries = smartlist_new();
-
- SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) {
- const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
- tor_assert(node);
- if (for_controller) {
- char name_buf[MAX_VERBOSE_NICKNAME_LEN+2];
- char *cp = name_buf;
- if (!node->is_running)
- *cp++ = '!';
- router_get_verbose_nickname(cp, ri);
- smartlist_add_strdup(rs_entries, name_buf);
- } else if (ri->cache_info.published_on >= cutoff) {
- smartlist_add(rs_entries, list_single_server_status(ri,
- node->is_running));
- }
- } SMARTLIST_FOREACH_END(ri);
-
- *router_status_out = smartlist_join_strings(rs_entries, " ", 0, NULL);
-
- SMARTLIST_FOREACH(rs_entries, char *, cp, tor_free(cp));
- smartlist_free(rs_entries);
-
- return 0;
-}
diff --git a/src/feature/control/fmt_serverstatus.h b/src/feature/control/fmt_serverstatus.h
deleted file mode 100644
index 9dd9fe125c..0000000000
--- a/src/feature/control/fmt_serverstatus.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* 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 fmt_serverstatus.h
- * \brief Header file for fmt_serverstatus.c.
- **/
-
-#ifndef TOR_FMT_SERVERSTATUS_H
-#define TOR_FMT_SERVERSTATUS_H
-
-int list_server_status_v1(smartlist_t *routers, char **router_status_out,
- int for_controller);
-
-#endif /* !defined(TOR_FMT_SERVERSTATUS_H) */
diff --git a/src/feature/control/getinfo_geoip.c b/src/feature/control/getinfo_geoip.c
index 33019207e6..542f3e97f7 100644
--- a/src/feature/control/getinfo_geoip.c
+++ b/src/feature/control/getinfo_geoip.c
@@ -5,7 +5,7 @@
/**
* @file getinfo_geoip.c
- * @brief GEOIP-related contoller GETINFO commands.
+ * @brief GEOIP-related controller GETINFO commands.
**/
#include "core/or/or.h"
diff --git a/src/feature/control/include.am b/src/feature/control/include.am
index 07094f23bb..101fe3c705 100644
--- a/src/feature/control/include.am
+++ b/src/feature/control/include.am
@@ -15,7 +15,6 @@ LIBTOR_APP_A_SOURCES += \
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.
@@ -35,5 +34,4 @@ noinst_HEADERS += \
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/dirauth_config.c b/src/feature/dirauth/dirauth_config.c
index a0b6de7eca..1ffd33e5f1 100644
--- a/src/feature/dirauth/dirauth_config.c
+++ b/src/feature/dirauth/dirauth_config.c
@@ -77,8 +77,8 @@ options_validate_dirauth_mode(const or_options_t *old_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)
+ tor_addr_t tmp;
+ if (!find_my_address(options, AF_INET, LOG_WARN, &tmp, NULL, NULL))
REJECT("Failed to resolve/guess local address. See logs for details.");
if (!options->ContactInfo && !options->TestingTorNetwork)
diff --git a/src/feature/dirauth/dirauth_options.inc b/src/feature/dirauth/dirauth_options.inc
index 2aa07a6c88..05726b8c2f 100644
--- a/src/feature/dirauth/dirauth_options.inc
+++ b/src/feature/dirauth/dirauth_options.inc
@@ -44,6 +44,13 @@ CONF_VAR(AuthDirSharedRandomness, BOOL, 0, "1")
/* NOTE: remove this option someday. */
CONF_VAR(AuthDirTestEd25519LinkKeys, BOOL, 0, "1")
+/**
+ * Bool (default 1): As an authority, should we launch tests for
+ * reachability, and use those results to vote on "Running"? If 0,
+ * we assume that every relay is Running.
+ **/
+CONF_VAR(AuthDirTestReachability, BOOL, 0, "1")
+
/** Authority only: key=value pairs that we add to our networkstatus
* consensus vote on the 'params' line. */
CONF_VAR(ConsensusParams, LINELIST, 0, NULL)
diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c
index d9fbd2a7ce..7d83d105b1 100644
--- a/src/feature/dirauth/dirvote.c
+++ b/src/feature/dirauth/dirvote.c
@@ -4,6 +4,7 @@
/* See LICENSE for licensing information */
#define DIRVOTE_PRIVATE
+
#include "core/or/or.h"
#include "app/config/config.h"
#include "app/config/resolve_addr.h"
@@ -225,7 +226,6 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
smartlist_t *chunks = smartlist_new();
char fingerprint[FINGERPRINT_LEN+1];
char digest[DIGEST_LEN];
- uint32_t addr;
char *protocols_lines = NULL;
char *client_versions_line = NULL, *server_versions_line = NULL;
char *shared_random_vote_str = NULL;
@@ -237,8 +237,6 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
voter = smartlist_get(v3_ns->voters, 0);
- addr = voter->addr;
-
base16_encode(fingerprint, sizeof(fingerprint),
v3_ns->cert->cache_info.identity_digest, DIGEST_LEN);
@@ -322,7 +320,7 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
tor_free(digest_algo_b64_digest_bw_file);
}
- const char *ip_str = fmt_addr32(addr);
+ const char *ip_str = fmt_addr(&voter->ipv4_addr);
if (ip_str[0]) {
smartlist_add_asprintf(chunks,
@@ -358,7 +356,7 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
bw_headers_line ? bw_headers_line : "",
bw_file_digest ? bw_file_digest: "",
voter->nickname, fingerprint, voter->address,
- ip_str, voter->dir_port, voter->or_port,
+ ip_str, voter->ipv4_dirport, voter->ipv4_orport,
voter->contact,
shared_random_vote_str ?
shared_random_vote_str : "");
@@ -636,9 +634,12 @@ compare_vote_rs(const vote_routerstatus_t *a, const vote_routerstatus_t *b)
if ((r = strcmp(b->status.nickname, a->status.nickname)))
return r;
- CMP_FIELD(unsigned, int, addr);
- CMP_FIELD(unsigned, int, or_port);
- CMP_FIELD(unsigned, int, dir_port);
+ if ((r = tor_addr_compare(&a->status.ipv4_addr, &b->status.ipv4_addr,
+ CMP_EXACT))) {
+ return r;
+ }
+ CMP_FIELD(unsigned, int, ipv4_orport);
+ CMP_FIELD(unsigned, int, ipv4_dirport);
return 0;
}
@@ -1740,9 +1741,9 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_add_asprintf(chunks,
"dir-source %s%s %s %s %s %d %d\n",
voter->nickname, e->is_legacy ? "-legacy" : "",
- fingerprint, voter->address, fmt_addr32(voter->addr),
- voter->dir_port,
- voter->or_port);
+ fingerprint, voter->address, fmt_addr(&voter->ipv4_addr),
+ voter->ipv4_dirport,
+ voter->ipv4_orport);
if (! e->is_legacy) {
smartlist_add_asprintf(chunks,
"contact %s\n"
@@ -2039,10 +2040,10 @@ networkstatus_compute_consensus(smartlist_t *votes,
memcpy(rs_out.identity_digest, current_rsa_id, DIGEST_LEN);
memcpy(rs_out.descriptor_digest, rs->status.descriptor_digest,
DIGEST_LEN);
- rs_out.addr = rs->status.addr;
+ tor_addr_copy(&rs_out.ipv4_addr, &rs->status.ipv4_addr);
rs_out.published_on = rs->status.published_on;
- rs_out.dir_port = rs->status.dir_port;
- rs_out.or_port = rs->status.or_port;
+ rs_out.ipv4_dirport = rs->status.ipv4_dirport;
+ rs_out.ipv4_orport = rs->status.ipv4_orport;
tor_addr_copy(&rs_out.ipv6_addr, &alt_orport.addr);
rs_out.ipv6_orport = alt_orport.port;
rs_out.has_bandwidth = 0;
@@ -2974,7 +2975,7 @@ dirvote_perform_vote(void)
if (!contents)
return -1;
- pending_vote = dirvote_add_vote(contents, 0, &msg, &status);
+ pending_vote = dirvote_add_vote(contents, 0, "self", &msg, &status);
tor_free(contents);
if (!pending_vote) {
log_warn(LD_DIR, "Couldn't store my own vote! (I told myself, '%s'.)",
@@ -3168,6 +3169,7 @@ add_new_cert_if_needed(const struct authority_cert_t *cert)
* only) */
pending_vote_t *
dirvote_add_vote(const char *vote_body, time_t time_posted,
+ const char *where_from,
const char **msg_out, int *status_out)
{
networkstatus_t *vote;
@@ -3225,6 +3227,14 @@ dirvote_add_vote(const char *vote_body, time_t time_posted,
goto err;
}
+ if (time_posted) { /* they sent it to me via a POST */
+ log_notice(LD_DIR, "%s posted a vote to me from %s.",
+ vi->nickname, where_from);
+ } else { /* I imported this one myself */
+ log_notice(LD_DIR, "Retrieved %s's vote from %s.",
+ vi->nickname, where_from);
+ }
+
/* Check if we received it, as a post, after the cutoff when we
* start asking other dir auths for it. If we do, the best plan
* is to discard it, because using it greatly increases the chances
@@ -3234,10 +3244,10 @@ dirvote_add_vote(const char *vote_body, time_t time_posted,
char tbuf1[ISO_TIME_LEN+1], tbuf2[ISO_TIME_LEN+1];
format_iso_time(tbuf1, time_posted);
format_iso_time(tbuf2, voting_schedule.fetch_missing_votes);
- log_warn(LD_DIR, "Rejecting posted vote from %s received at %s; "
+ log_warn(LD_DIR, "Rejecting %s's posted vote from %s received at %s; "
"our cutoff for received votes is %s. Check your clock, "
"CPU load, and network load. Also check the authority that "
- "posted the vote.", vi->address, tbuf1, tbuf2);
+ "posted the vote.", vi->nickname, vi->address, tbuf1, tbuf2);
*msg_out = "Posted vote received too late, would be dangerous to count it";
goto err;
}
@@ -3253,8 +3263,8 @@ dirvote_add_vote(const char *vote_body, time_t time_posted,
networkstatus_voter_info_t *vi_old = get_voter(v->vote);
if (fast_memeq(vi_old->vote_digest, vi->vote_digest, DIGEST_LEN)) {
/* Ah, it's the same vote. Not a problem. */
- log_info(LD_DIR, "Discarding a vote we already have (from %s).",
- vi->address);
+ log_notice(LD_DIR, "Discarding a vote we already have (from %s).",
+ vi->address);
if (*status_out < 200)
*status_out = 200;
goto discard;
@@ -3277,6 +3287,8 @@ dirvote_add_vote(const char *vote_body, time_t time_posted,
*msg_out = "OK";
return v;
} else {
+ log_notice(LD_DIR, "Discarding vote from %s because we have "
+ "a newer one already.", vi->address);
*msg_out = "Already have a newer pending vote";
goto err;
}
@@ -3461,6 +3473,15 @@ dirvote_compute_consensuses(void)
pending[flav].body = consensus_body;
pending[flav].consensus = consensus;
n_generated++;
+
+ /* Write it out to disk too, for dir auth debugging purposes */
+ {
+ char *filename;
+ tor_asprintf(&filename, "my-consensus-%s", flavor_name);
+ write_str_to_file(get_datadir_fname(filename), consensus_body, 0);
+ tor_free(filename);
+ }
+
consensus_body = NULL;
consensus = NULL;
}
@@ -3848,11 +3869,10 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method)
smartlist_add_asprintf(chunks, "onion-key\n%s", key);
if (ri->onion_curve25519_pkey) {
- char kbuf[128];
- base64_encode(kbuf, sizeof(kbuf),
- (const char*)ri->onion_curve25519_pkey->public_key,
- CURVE25519_PUBKEY_LEN, BASE64_ENCODE_MULTILINE);
- smartlist_add_asprintf(chunks, "ntor-onion-key %s", kbuf);
+ char kbuf[CURVE25519_BASE64_PADDED_LEN + 1];
+ bool add_padding = (consensus_method < MIN_METHOD_FOR_UNPADDED_NTOR_KEY);
+ curve25519_public_to_base64(kbuf, ri->onion_curve25519_pkey, add_padding);
+ smartlist_add_asprintf(chunks, "ntor-onion-key %s\n", kbuf);
}
if (family) {
@@ -3963,6 +3983,8 @@ static const struct consensus_method_range_t {
{MIN_SUPPORTED_CONSENSUS_METHOD,
MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS - 1},
{MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS,
+ MIN_METHOD_FOR_UNPADDED_NTOR_KEY - 1},
+ {MIN_METHOD_FOR_UNPADDED_NTOR_KEY,
MAX_SUPPORTED_CONSENSUS_METHOD},
{-1, -1}
};
@@ -4176,8 +4198,8 @@ dirvote_dirreq_get_status_vote(const char *url, smartlist_t *items,
/** Get the best estimate of a router's bandwidth for dirauth purposes,
* preferring measured to advertised values if available. */
-static uint32_t
-dirserv_get_bandwidth_for_router_kb(const routerinfo_t *ri)
+MOCK_IMPL(uint32_t,dirserv_get_bandwidth_for_router_kb,
+ (const routerinfo_t *ri))
{
uint32_t bw_kb = 0;
/*
@@ -4206,31 +4228,72 @@ dirserv_get_bandwidth_for_router_kb(const routerinfo_t *ri)
return bw_kb;
}
-/** Helper for sorting: compares two routerinfos first by address, and then by
- * descending order of "usefulness". (An authority is more useful than a
- * non-authority; a running router is more useful than a non-running router;
- * and a router with more bandwidth is more useful than one with less.)
+/**
+ * Helper: compare the address of family `family` in `a` with the address in
+ * `b`. The family must be one of `AF_INET` and `AF_INET6`.
**/
static int
-compare_routerinfo_by_ip_and_bw_(const void **a, const void **b)
+compare_routerinfo_addrs_by_family(const routerinfo_t *a,
+ const routerinfo_t *b,
+ int family)
+{
+ const tor_addr_t *addr1 = (family==AF_INET) ? &a->ipv4_addr : &a->ipv6_addr;
+ const tor_addr_t *addr2 = (family==AF_INET) ? &b->ipv4_addr : &b->ipv6_addr;
+ return tor_addr_compare(addr1, addr2, CMP_EXACT);
+}
+
+/** Helper for sorting: compares two ipv4 routerinfos first by ipv4 address,
+ * and then by descending order of "usefulness"
+ * (see compare_routerinfo_usefulness)
+ **/
+STATIC int
+compare_routerinfo_by_ipv4(const void **a, const void **b)
+{
+ const routerinfo_t *first = *(const routerinfo_t **)a;
+ const routerinfo_t *second = *(const routerinfo_t **)b;
+ int comparison = compare_routerinfo_addrs_by_family(first, second, AF_INET);
+ if (comparison == 0) {
+ // If addresses are equal, use other comparison criteria
+ return compare_routerinfo_usefulness(first, second);
+ } else {
+ return comparison;
+ }
+}
+
+/** Helper for sorting: compares two ipv6 routerinfos first by ipv6 address,
+ * and then by descending order of "usefulness"
+ * (see compare_routerinfo_usefulness)
+ **/
+STATIC int
+compare_routerinfo_by_ipv6(const void **a, const void **b)
+{
+ const routerinfo_t *first = *(const routerinfo_t **)a;
+ const routerinfo_t *second = *(const routerinfo_t **)b;
+ int comparison = compare_routerinfo_addrs_by_family(first, second, AF_INET6);
+ // If addresses are equal, use other comparison criteria
+ if (comparison == 0)
+ return compare_routerinfo_usefulness(first, second);
+ else
+ return comparison;
+}
+
+/**
+* Compare routerinfos by descending order of "usefulness" :
+* An authority is more useful than a non-authority; a running router is
+* more useful than a non-running router; and a router with more bandwidth
+* is more useful than one with less.
+**/
+STATIC int
+compare_routerinfo_usefulness(const routerinfo_t *first,
+ const routerinfo_t *second)
{
- routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b;
int first_is_auth, second_is_auth;
- uint32_t bw_kb_first, bw_kb_second;
const node_t *node_first, *node_second;
int first_is_running, second_is_running;
-
- /* we return -1 if first should appear before second... that is,
- * if first is a better router. */
- if (first->addr < second->addr)
- return -1;
- else if (first->addr > second->addr)
- return 1;
-
+ uint32_t bw_kb_first, bw_kb_second;
/* Potentially, this next bit could cause k n lg n memeq calls. But in
* reality, we will almost never get here, since addresses will usually be
* different. */
-
first_is_auth =
router_digest_is_trusted_dir(first->cache_info.identity_digest);
second_is_auth =
@@ -4245,7 +4308,6 @@ compare_routerinfo_by_ip_and_bw_(const void **a, const void **b)
node_second = node_get_by_id(second->cache_info.identity_digest);
first_is_running = node_first && node_first->is_running;
second_is_running = node_second && node_second->is_running;
-
if (first_is_running && !second_is_running)
return -1;
else if (!first_is_running && second_is_running)
@@ -4266,41 +4328,89 @@ compare_routerinfo_by_ip_and_bw_(const void **a, const void **b)
DIGEST_LEN);
}
-/** Given a list of routerinfo_t in <b>routers</b>, return a new digestmap_t
- * whose keys are the identity digests of those routers that we're going to
- * exclude for Sybil-like appearance. */
-static digestmap_t *
-get_possible_sybil_list(const smartlist_t *routers)
+/** Given a list of routerinfo_t in <b>routers</b> that all use the same
+ * IP version, specified in <b>family</b>, return a new digestmap_t whose keys
+ * are the identity digests of those routers that we're going to exclude for
+ * Sybil-like appearance.
+ */
+STATIC digestmap_t *
+get_sybil_list_by_ip_version(const smartlist_t *routers, sa_family_t family)
{
const dirauth_options_t *options = dirauth_get_options();
- digestmap_t *omit_as_sybil;
+ digestmap_t *omit_as_sybil = digestmap_new();
smartlist_t *routers_by_ip = smartlist_new();
- uint32_t last_addr;
- int addr_count;
+ int addr_count = 0;
+ routerinfo_t *last_ri = NULL;
/* Allow at most this number of Tor servers on a single IP address, ... */
int max_with_same_addr = options->AuthDirMaxServersPerAddr;
if (max_with_same_addr <= 0)
max_with_same_addr = INT_MAX;
smartlist_add_all(routers_by_ip, routers);
- smartlist_sort(routers_by_ip, compare_routerinfo_by_ip_and_bw_);
- omit_as_sybil = digestmap_new();
+ if (family == AF_INET6)
+ smartlist_sort(routers_by_ip, compare_routerinfo_by_ipv6);
+ else
+ smartlist_sort(routers_by_ip, compare_routerinfo_by_ipv4);
- last_addr = 0;
- addr_count = 0;
SMARTLIST_FOREACH_BEGIN(routers_by_ip, routerinfo_t *, ri) {
- if (last_addr != ri->addr) {
- last_addr = ri->addr;
+ bool addrs_equal;
+ if (last_ri)
+ addrs_equal = !compare_routerinfo_addrs_by_family(last_ri, ri, family);
+ else
+ addrs_equal = false;
+
+ if (! addrs_equal) {
+ last_ri = ri;
addr_count = 1;
} else if (++addr_count > max_with_same_addr) {
digestmap_set(omit_as_sybil, ri->cache_info.identity_digest, ri);
}
} SMARTLIST_FOREACH_END(ri);
-
smartlist_free(routers_by_ip);
return omit_as_sybil;
}
+/** Given a list of routerinfo_t in <b>routers</b>, return a new digestmap_t
+ * whose keys are the identity digests of those routers that we're going to
+ * exclude for Sybil-like appearance. */
+STATIC digestmap_t *
+get_all_possible_sybil(const smartlist_t *routers)
+{
+ smartlist_t *routers_ipv6, *routers_ipv4;
+ routers_ipv6 = smartlist_new();
+ routers_ipv4 = smartlist_new();
+ digestmap_t *omit_as_sybil_ipv4;
+ digestmap_t *omit_as_sybil_ipv6;
+ digestmap_t *omit_as_sybil = digestmap_new();
+ // Sort the routers in two lists depending on their IP version
+ SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) {
+ // If the router has an IPv6 address
+ if (tor_addr_family(&(ri->ipv6_addr)) == AF_INET6) {
+ smartlist_add(routers_ipv6, ri);
+ }
+ // If the router has an IPv4 address
+ if (tor_addr_family(&(ri->ipv4_addr)) == AF_INET) {
+ smartlist_add(routers_ipv4, ri);
+ }
+ } SMARTLIST_FOREACH_END(ri);
+ omit_as_sybil_ipv4 = get_sybil_list_by_ip_version(routers_ipv4, AF_INET);
+ omit_as_sybil_ipv6 = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6);
+
+ // Add all possible sybils to the common digestmap
+ DIGESTMAP_FOREACH (omit_as_sybil_ipv4, sybil_id, routerinfo_t *, ri) {
+ digestmap_set(omit_as_sybil, ri->cache_info.identity_digest, ri);
+ } DIGESTMAP_FOREACH_END;
+ DIGESTMAP_FOREACH (omit_as_sybil_ipv6, sybil_id, routerinfo_t *, ri) {
+ digestmap_set(omit_as_sybil, ri->cache_info.identity_digest, ri);
+ } DIGESTMAP_FOREACH_END;
+ // Clean the temp variables
+ smartlist_free(routers_ipv4);
+ smartlist_free(routers_ipv6);
+ digestmap_free(omit_as_sybil_ipv4, NULL);
+ digestmap_free(omit_as_sybil_ipv6, NULL);
+ // Return the digestmap: it now contains all the possible sybils
+ return omit_as_sybil;
+}
/** Given a platform string as in a routerinfo_t (possibly null), return a
* newly allocated version string for a networkstatus document, or NULL if the
* platform doesn't give a Tor version. */
@@ -4463,7 +4573,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
const or_options_t *options = get_options();
const dirauth_options_t *d_options = dirauth_get_options();
networkstatus_t *v3_out = NULL;
- uint32_t addr;
+ tor_addr_t addr;
char *hostname = NULL, *client_versions = NULL, *server_versions = NULL;
const char *contact;
smartlist_t *routers, *routerstatuses;
@@ -4475,7 +4585,6 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
networkstatus_voter_info_t *voter = NULL;
vote_timing_t timing;
- digestmap_t *omit_as_sybil = NULL;
const int vote_on_reachability = running_long_enough_to_decide_unreachable();
smartlist_t *microdescriptors = NULL;
smartlist_t *bw_file_headers = NULL;
@@ -4492,13 +4601,13 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
log_err(LD_BUG, "Error computing identity key digest");
return NULL;
}
- if (resolve_my_address(LOG_WARN, options, &addr, NULL, &hostname)<0) {
+ if (!find_my_address(options, AF_INET, LOG_WARN, &addr, NULL, &hostname)) {
log_warn(LD_NET, "Couldn't resolve my hostname");
return NULL;
}
if (!hostname || !strchr(hostname, '.')) {
tor_free(hostname);
- hostname = tor_dup_ip(addr);
+ hostname = tor_addr_to_str_dup(&addr);
}
if (!hostname) {
@@ -4545,19 +4654,16 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
routers_make_ed_keys_unique(routers);
/* After this point, don't use rl->routers; use 'routers' instead. */
routers_sort_by_identity(routers);
- omit_as_sybil = get_possible_sybil_list(routers);
-
- DIGESTMAP_FOREACH(omit_as_sybil, sybil_id, void *, ignore) {
- (void) ignore;
+ /* Get a digestmap of possible sybil routers, IPv4 or IPv6 */
+ digestmap_t *omit_as_sybil = get_all_possible_sybil(routers);
+ DIGESTMAP_FOREACH (omit_as_sybil, sybil_id, void *, ignore) {
+ (void)ignore;
rep_hist_make_router_pessimal(sybil_id, now);
- } DIGESTMAP_FOREACH_END;
-
+ } DIGESTMAP_FOREACH_END
/* Count how many have measured bandwidths so we know how to assign flags;
* this must come before dirserv_compute_performance_thresholds() */
dirserv_count_measured_bws(routers);
-
dirserv_compute_performance_thresholds(omit_as_sybil);
-
routerstatuses = smartlist_new();
microdescriptors = smartlist_new();
@@ -4565,7 +4671,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
/* If it has a protover list and contains a protocol name greater than
* MAX_PROTOCOL_NAME_LENGTH, skip it. */
if (ri->protocol_list &&
- protover_contains_long_protocol_names(ri->protocol_list)) {
+ protover_list_is_invalid(ri->protocol_list)) {
continue;
}
if (ri->cache_info.published_on >= cutoff) {
@@ -4585,7 +4691,6 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
ri->cache_info.signing_key_cert->signing_key.pubkey,
ED25519_PUBKEY_LEN);
}
-
if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
clear_status_flags_on_sybil(rs);
@@ -4725,9 +4830,9 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
memcpy(voter->identity_digest, identity_digest, DIGEST_LEN);
voter->sigs = smartlist_new();
voter->address = hostname;
- voter->addr = addr;
- voter->dir_port = router_get_advertised_dir_port(options, 0);
- voter->or_port = router_get_advertised_or_port(options);
+ tor_addr_copy(&voter->ipv4_addr, &addr);
+ voter->ipv4_dirport = routerconf_find_dir_port(options, 0);
+ voter->ipv4_orport = routerconf_find_or_port(options, AF_INET);
voter->contact = tor_strdup(contact);
if (options->V3AuthUseLegacyKey) {
authority_cert_t *c = get_my_v3_legacy_cert();
diff --git a/src/feature/dirauth/dirvote.h b/src/feature/dirauth/dirvote.h
index a9b356b387..f9441773a7 100644
--- a/src/feature/dirauth/dirvote.h
+++ b/src/feature/dirauth/dirvote.h
@@ -53,7 +53,7 @@
#define MIN_SUPPORTED_CONSENSUS_METHOD 28
/** The highest consensus method that we currently support. */
-#define MAX_SUPPORTED_CONSENSUS_METHOD 29
+#define MAX_SUPPORTED_CONSENSUS_METHOD 30
/**
* Lowest consensus method where microdescriptor lines are put in canonical
@@ -61,6 +61,10 @@
**/
#define MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS 29
+/** Lowest consensus method where an unpadded base64 onion-key-ntor is allowed
+ * See #7869 */
+#define MIN_METHOD_FOR_UNPADDED_NTOR_KEY 30
+
/** Default bandwidth to clip unmeasured bandwidths to using method >=
* MIN_METHOD_TO_CLIP_UNMEASURED_BW. (This is not a consensus method; do not
* get confused with the above macros.) */
@@ -95,6 +99,7 @@ void dirvote_dirreq_get_status_vote(const char *url, smartlist_t *items,
/* Storing signatures and votes functions */
struct pending_vote_t * dirvote_add_vote(const char *vote_body,
time_t time_posted,
+ const char *where_from,
const char **msg_out,
int *status_out);
int dirvote_add_signatures(const char *detached_signatures_body,
@@ -145,11 +150,13 @@ dirvote_dirreq_get_status_vote(const char *url, smartlist_t *items,
static inline struct pending_vote_t *
dirvote_add_vote(const char *vote_body,
time_t time_posted,
+ const char *where_from,
const char **msg_out,
int *status_out)
{
(void) vote_body;
(void) time_posted;
+ (void) where_from;
/* If the dirauth module is disabled, this should NEVER be called else we
* failed to safeguard the dirauth module. */
tor_assert_nonfatal_unreached();
@@ -179,6 +186,8 @@ dirvote_add_signatures(const char *detached_signatures_body,
/* Item access */
MOCK_DECL(const char*, dirvote_get_pending_consensus,
(consensus_flavor_t flav));
+MOCK_DECL(uint32_t,dirserv_get_bandwidth_for_router_kb,
+ (const routerinfo_t *ri));
MOCK_DECL(const char*, dirvote_get_pending_detached_signatures, (void));
const cached_dir_t *dirvote_get_vote(const char *fp, int flags);
@@ -230,6 +239,22 @@ int networkstatus_add_detached_signatures(networkstatus_t *target,
const char *source,
int severity,
const char **msg_out);
+STATIC int
+compare_routerinfo_usefulness(const routerinfo_t *first,
+ const routerinfo_t *second);
+STATIC
+int compare_routerinfo_by_ipv4(const void **a, const void **b);
+
+STATIC
+int compare_routerinfo_by_ipv6(const void **a, const void **b);
+
+STATIC
+digestmap_t * get_sybil_list_by_ip_version(
+ const smartlist_t *routers, sa_family_t family);
+
+STATIC
+digestmap_t * get_all_possible_sybil(const smartlist_t *routers);
+
STATIC
char *networkstatus_get_detached_signatures(smartlist_t *consensuses);
STATIC microdesc_t *dirvote_create_microdescriptor(const routerinfo_t *ri,
diff --git a/src/feature/dirauth/keypin.c b/src/feature/dirauth/keypin.c
index 5072a58573..21afff550a 100644
--- a/src/feature/dirauth/keypin.c
+++ b/src/feature/dirauth/keypin.c
@@ -70,7 +70,7 @@
*
* We persist these entries to disk using a simple format, where each line
* has a base64-encoded RSA SHA1 hash, then a base64-endoded Ed25519 key.
- * Empty lines, misformed lines, and lines beginning with # are
+ * Empty lines, malformed lines, and lines beginning with # are
* ignored. Lines beginning with @ are reserved for future extensions.
*
* The dirserv.c module is the main user of these functions.
@@ -507,7 +507,7 @@ keypin_clear(void)
HT_CLEAR(rsamap,&the_rsa_map);
if (bad_entries) {
- log_warn(LD_BUG, "Found %d discrepencies in the keypin database.",
+ log_warn(LD_BUG, "Found %d discrepancies in the keypin database.",
bad_entries);
}
}
diff --git a/src/feature/dirauth/process_descs.c b/src/feature/dirauth/process_descs.c
index 5025d0ae39..a382f237c4 100644
--- a/src/feature/dirauth/process_descs.c
+++ b/src/feature/dirauth/process_descs.c
@@ -56,8 +56,9 @@ static was_router_added_t dirserv_add_extrainfo(extrainfo_t *ei,
static uint32_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);
+ const char *nickname, const tor_addr_t *ipv4_addr,
+ uint16_t ipv4_orport, const char *platform,
+ const char **msg, int severity);
/** Should be static; exposed for testing. */
static authdir_config_t *fingerprint_list = NULL;
@@ -307,9 +308,9 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg,
/* 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);
+ r = dirserv_get_status_impl(d, signing_key, router->nickname,
+ &router->ipv4_addr, router->ipv4_orport,
+ router->platform, msg, severity);
if (r)
return r;
@@ -321,8 +322,9 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg,
* and is non-zero (clients check that it's non-zero before using it). */
if (!routerinfo_has_curve25519_onion_key(router)) {
log_fn(severity, LD_DIR,
- "Descriptor from router %s is missing an ntor curve25519 onion "
- "key.", router_describe(router));
+ "Descriptor from router %s (platform %s) "
+ "is missing an ntor curve25519 onion key.",
+ router_describe(router), router->platform);
if (msg)
*msg = "Missing ntor curve25519 onion key. Please upgrade!";
return RTR_REJECT;
@@ -378,7 +380,8 @@ dirserv_would_reject_router(const routerstatus_t *rs,
memcpy(&pk.pubkey, vrs->ed25519_id, ED25519_PUBKEY_LEN);
res = dirserv_get_status_impl(rs->identity_digest, &pk, rs->nickname,
- rs->addr, rs->or_port, NULL, NULL, LOG_DEBUG);
+ &rs->ipv4_addr, rs->ipv4_orport, NULL, NULL,
+ LOG_DEBUG);
return (res & RTR_REJECT) != 0;
}
@@ -409,11 +412,11 @@ dirserv_rejects_tor_version(const char *platform,
return true;
}
- /* 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. */
+ /* Series between Tor 0.3.6 and 0.4.1 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")) {
+ !tor_version_as_new_as(platform,"0.4.2.1-alpha")) {
if (msg) {
*msg = please_upgrade_string;
}
@@ -433,8 +436,9 @@ dirserv_rejects_tor_version(const char *platform,
static uint32_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)
+ const char *nickname, const tor_addr_t *ipv4_addr,
+ uint16_t ipv4_orport, const char *platform,
+ const char **msg, int severity)
{
uint32_t result = 0;
rtr_flags_t *status_by_digest;
@@ -485,16 +489,16 @@ dirserv_get_status_impl(const char *id_digest,
*msg = "Fingerprint and/or ed25519 identity is marked invalid";
}
- if (authdir_policy_badexit_address(addr, or_port)) {
+ if (authdir_policy_badexit_address(ipv4_addr, ipv4_orport)) {
log_fn(severity, LD_DIRSERV,
"Marking '%s' as bad exit because of address '%s'",
- nickname, fmt_addr32(addr));
+ nickname, fmt_addr(ipv4_addr));
result |= RTR_BADEXIT;
}
- if (!authdir_policy_permits_address(addr, or_port)) {
+ if (!authdir_policy_permits_address(ipv4_addr, ipv4_orport)) {
log_fn(severity, LD_DIRSERV, "Rejecting '%s' because of address '%s'",
- nickname, fmt_addr32(addr));
+ nickname, fmt_addr(ipv4_addr));
if (msg)
*msg = "Suspicious relay address range -- if you think this is a "
"mistake please set a valid email address in ContactInfo and "
@@ -502,10 +506,10 @@ dirserv_get_status_impl(const char *id_digest,
"your address(es) and fingerprint(s)?";
return RTR_REJECT;
}
- if (!authdir_policy_valid_address(addr, or_port)) {
+ if (!authdir_policy_valid_address(ipv4_addr, ipv4_orport)) {
log_fn(severity, LD_DIRSERV,
"Not marking '%s' valid because of address '%s'",
- nickname, fmt_addr32(addr));
+ nickname, fmt_addr(ipv4_addr));
result |= RTR_INVALID;
}
@@ -534,13 +538,11 @@ dirserv_free_fingerprint_list(void)
STATIC int
dirserv_router_has_valid_address(routerinfo_t *ri)
{
- tor_addr_t addr;
-
if (get_options()->DirAllowPrivateAddresses)
return 0; /* whatever it is, we're fine with it */
- tor_addr_from_ipv4h(&addr, ri->addr);
- if (tor_addr_is_null(&addr) || tor_addr_is_internal(&addr, 0)) {
+ if (tor_addr_is_null(&ri->ipv4_addr) ||
+ tor_addr_is_internal(&ri->ipv4_addr, 0)) {
log_info(LD_DIRSERV,
"Router %s published internal IPv4 address. Refusing.",
router_describe(ri));
@@ -760,6 +762,9 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
goto fail;
}
+ log_info(LD_DIR, "Assessing new descriptor: %s: %s",
+ ri->nickname, ri->platform);
+
/* Check whether this descriptor is semantically identical to the last one
* from this server. (We do this here and not in router_add_to_routerlist
* because we want to be able to accept the newest router descriptor that
diff --git a/src/feature/dirauth/reachability.c b/src/feature/dirauth/reachability.c
index 65fa27ed80..8717646314 100644
--- a/src/feature/dirauth/reachability.c
+++ b/src/feature/dirauth/reachability.c
@@ -84,7 +84,7 @@ dirserv_orconn_tls_done(const tor_addr_t *addr,
log_info(LD_DIRSERV, "Found router %s to be reachable at %s:%d. Yay.",
router_describe(ri),
tor_addr_to_str(addrstr, addr, sizeof(addrstr), 1),
- ri->or_port);
+ ri->ipv4_orport);
if (tor_addr_family(addr) == AF_INET) {
rep_hist_note_router_reachable(digest_rcvd, addr, or_port, now);
node->last_reachable = now;
@@ -105,17 +105,23 @@ dirserv_should_launch_reachability_test(const routerinfo_t *ri,
{
if (!authdir_mode_handles_descs(get_options(), ri->purpose))
return 0;
+ if (! dirauth_get_options()->AuthDirTestReachability)
+ return 0;
if (!ri_old) {
/* New router: Launch an immediate reachability test, so we will have an
* opinion soon in case we're generating a consensus soon */
+ log_info(LD_DIR, "descriptor for new router %s", router_describe(ri));
return 1;
}
if (ri_old->is_hibernating && !ri->is_hibernating) {
/* It just came out of hibernation; launch a reachability test */
+ log_info(LD_DIR, "out of hibernation: router %s", router_describe(ri));
return 1;
}
if (! routers_have_same_or_addrs(ri, ri_old)) {
/* Address or port changed; launch a reachability test */
+ log_info(LD_DIR, "address or port changed: router %s",
+ router_describe(ri));
return 1;
}
return 0;
@@ -130,7 +136,6 @@ dirserv_single_reachability_test(time_t now, routerinfo_t *router)
const dirauth_options_t *dirauth_options = dirauth_get_options();
channel_t *chan = NULL;
const node_t *node = NULL;
- tor_addr_t router_addr;
const ed25519_public_key_t *ed_id_key;
(void) now;
@@ -147,10 +152,10 @@ dirserv_single_reachability_test(time_t now, routerinfo_t *router)
}
/* IPv4. */
- log_debug(LD_OR,"Testing reachability of %s at %s:%u.",
- router->nickname, fmt_addr32(router->addr), router->or_port);
- tor_addr_from_ipv4h(&router_addr, router->addr);
- chan = channel_tls_connect(&router_addr, router->or_port,
+ log_info(LD_OR,"Testing reachability of %s at %s:%u.",
+ router->nickname, fmt_addr(&router->ipv4_addr),
+ router->ipv4_orport);
+ chan = channel_tls_connect(&router->ipv4_addr, router->ipv4_orport,
router->cache_info.identity_digest,
ed_id_key);
if (chan) command_setup_channel(chan);
@@ -159,10 +164,10 @@ dirserv_single_reachability_test(time_t now, routerinfo_t *router)
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.",
- router->nickname,
- tor_addr_to_str(addrstr, &router->ipv6_addr, sizeof(addrstr), 1),
- router->ipv6_orport);
+ log_info(LD_OR, "Testing reachability of %s at %s:%u.",
+ router->nickname,
+ tor_addr_to_str(addrstr, &router->ipv6_addr, sizeof(addrstr), 1),
+ router->ipv6_orport);
chan = channel_tls_connect(&router->ipv6_addr, router->ipv6_orport,
router->cache_info.identity_digest,
ed_id_key);
@@ -189,6 +194,9 @@ dirserv_test_reachability(time_t now)
* the testing, and directory authorities are easy to upgrade. Let's
* wait til 0.2.0. -RD */
// time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
+ if (! dirauth_get_options()->AuthDirTestReachability)
+ return;
+
routerlist_t *rl = router_get_routerlist();
static char ctr = 0;
int bridge_auth = authdir_mode_bridge(get_options());
diff --git a/src/feature/dirauth/shared_random.c b/src/feature/dirauth/shared_random.c
index fd55008242..e7c13787c4 100644
--- a/src/feature/dirauth/shared_random.c
+++ b/src/feature/dirauth/shared_random.c
@@ -52,7 +52,7 @@
* saves the current state of the protocol on disk so that it can resume
* normally in case of reboot. The disk state (sr_disk_state_t) is managed by
* shared_random_state.c:state_query() and we go to extra lengths to ensure
- * that the state is flushed on disk everytime we receive any useful
+ * that the state is flushed on disk every time we receive any useful
* information like commits or SRVs.
*
* - When we receive a commit from a vote, we examine it to see if it's useful
@@ -62,7 +62,7 @@
* receive the reveal information corresponding to a commitment, we verify
* that they indeed match using verify_commit_and_reveal().
*
- * - We treat consensuses as the ground truth, so everytime we generate a new
+ * - We treat consensuses as the ground truth, so every time we generate a new
* consensus we update our SR state accordingly even if our local view was
* different (see sr_act_post_consensus()).
*
@@ -170,7 +170,7 @@ commit_log(const sr_commit_t *commit)
/** 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
+ * used every time we receive a new reveal value. Furthermore, the commit
* object MUST have a reveal value and the hash of the reveal value. */
STATIC int
verify_commit_and_reveal(const sr_commit_t *commit)
diff --git a/src/feature/dirauth/shared_random_state.c b/src/feature/dirauth/shared_random_state.c
index 07bc757506..c555202942 100644
--- a/src/feature/dirauth/shared_random_state.c
+++ b/src/feature/dirauth/shared_random_state.c
@@ -780,7 +780,7 @@ new_protocol_run(time_t valid_after)
sr_compute_srv();
}
- /* Prepare for the new protocol run by reseting the state */
+ /* Prepare for the new protocol run by resetting the state */
reset_state_for_new_protocol_run(valid_after);
/* Do some logging */
diff --git a/src/feature/dirauth/vote_microdesc_hash_st.h b/src/feature/dirauth/vote_microdesc_hash_st.h
index 7f8ebf7fd7..6870bbab2c 100644
--- a/src/feature/dirauth/vote_microdesc_hash_st.h
+++ b/src/feature/dirauth/vote_microdesc_hash_st.h
@@ -6,7 +6,7 @@
/**
* @file vote_microdesc_hash_st.h
- * @brief Microdescriptor-hash voting strcture.
+ * @brief Microdescriptor-hash voting structure.
**/
#ifndef VOTE_MICRODESC_HASH_ST_H
diff --git a/src/feature/dirauth/voteflags.c b/src/feature/dirauth/voteflags.c
index 477eb6f0b7..3938b61adb 100644
--- a/src/feature/dirauth/voteflags.c
+++ b/src/feature/dirauth/voteflags.c
@@ -487,7 +487,6 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
unreachable.
*/
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);
@@ -501,8 +500,9 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
/* A hibernating router is down unless we (somehow) had contact with it
* since it declared itself to be hibernating. */
answer = 0;
- } else if (options->AssumeReachable) {
- /* If AssumeReachable, everybody is up unless they say they are down! */
+ } else if (! dirauth_options->AuthDirTestReachability) {
+ /* If we aren't testing reachability, then everybody is up unless they say
+ * they are down. */
answer = 1;
} else {
/* Otherwise, a router counts as up if we found all announced OR
diff --git a/src/feature/dirauth/voting_schedule.h b/src/feature/dirauth/voting_schedule.h
index 9e2ac29c75..271bdcda33 100644
--- a/src/feature/dirauth/voting_schedule.h
+++ b/src/feature/dirauth/voting_schedule.h
@@ -45,7 +45,7 @@ typedef struct {
/* True iff this voting schedule was set on demand meaning not through the
* normal vote operation of a dirauth or when a consensus is set. This only
* applies to a directory authority that needs to recalculate the voting
- * timings only for the first vote even though this object was initilized
+ * timings only for the first vote even though this object was initialized
* prior to voting. */
int created_on_demand;
diff --git a/src/feature/dircache/consdiffmgr.c b/src/feature/dircache/consdiffmgr.c
index 10590cd6d2..21f536432c 100644
--- a/src/feature/dircache/consdiffmgr.c
+++ b/src/feature/dircache/consdiffmgr.c
@@ -177,6 +177,16 @@ typedef struct cdm_diff_t {
/** Hashtable mapping flavor and source consensus digest to status. */
static HT_HEAD(cdm_diff_ht, cdm_diff_t) cdm_diff_ht = HT_INITIALIZER();
+#ifdef _WIN32
+ // XXX(ahf): For tor#24857, a contributor suggested that on Windows, the CPU
+ // begins to spike at 100% once the number of files handled by the consensus
+ // diff manager becomes larger than 64. To see if the issue goes away, we
+ // hardcode this value to 64 now while we investigate a better solution.
+# define CACHE_MAX_NUM 64
+#else
+# define CACHE_MAX_NUM 128
+#endif
+
/**
* Configuration for this module
*/
@@ -184,7 +194,7 @@ static consdiff_cfg_t consdiff_cfg = {
// XXXX I'd like to make this number bigger, but it interferes with the
// XXXX seccomp2 syscall filter, which tops out at BPF_MAXINS (4096)
// XXXX rules.
- /* .cache_max_num = */ 128
+ /* .cache_max_num = */ CACHE_MAX_NUM
};
static int consdiffmgr_ensure_space_for_files(int n);
diff --git a/src/feature/dircache/dircache.c b/src/feature/dircache/dircache.c
index ca127720f2..00bb0abf23 100644
--- a/src/feature/dircache/dircache.c
+++ b/src/feature/dircache/dircache.c
@@ -142,7 +142,7 @@ write_http_response_header_impl(dir_connection_t *conn, ssize_t length,
if (type) {
buf_add_printf(buf, "Content-Type: %s\r\n", type);
}
- if (!is_local_addr(&conn->base_.addr)) {
+ if (!is_local_to_resolve_addr(&conn->base_.addr)) {
/* Don't report the source address for a nearby/private connection.
* Otherwise we tend to mis-report in cases where incoming ports are
* being forwarded to a Tor server running behind the firewall. */
@@ -735,7 +735,7 @@ digest_list_contains_best_consensus(consensus_flavor_t flavor,
typedef struct {
/** name of the flavor to retrieve. */
char *flavor;
- /** flavor to retrive, as enum. */
+ /** flavor to retrieve, as enum. */
consensus_flavor_t flav;
/** plus-separated list of authority fingerprints; see
* client_likes_consensus(). Aliases the URL in the request passed to
@@ -1614,7 +1614,8 @@ directory_handle_command_post,(dir_connection_t *conn, const char *headers,
if (!public_server_mode(options)) {
log_info(LD_DIR, "Rejected dir post request from %s "
- "since we're not a public relay.", conn->base_.address);
+ "since we're not a public relay.",
+ connection_describe_peer(TO_CONN(conn)));
write_short_http_response(conn, 503, "Not acting as a public relay");
goto done;
}
@@ -1630,7 +1631,8 @@ directory_handle_command_post,(dir_connection_t *conn, const char *headers,
!strcmpstart(url,"/tor/rendezvous2/publish")) {
if (rend_cache_store_v2_desc_as_dir(body) < 0) {
log_warn(LD_REND, "Rejected v2 rend descriptor (body size %d) from %s.",
- (int)body_len, conn->base_.address);
+ (int)body_len,
+ connection_describe_peer(TO_CONN(conn)));
write_short_http_response(conn, 400,
"Invalid v2 service descriptor rejected");
} else {
@@ -1673,6 +1675,15 @@ directory_handle_command_post,(dir_connection_t *conn, const char *headers,
const char *msg = "[None]";
uint8_t purpose = authdir_mode_bridge(options) ?
ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
+
+ {
+ char *genreason = http_get_header(headers, "X-Desc-Gen-Reason: ");
+ log_info(LD_DIRSERV,
+ "New descriptor post, because: %s",
+ genreason ? genreason : "not specified");
+ tor_free(genreason);
+ }
+
was_router_added_t r = dirserv_add_multiple_descriptors(body, body_len,
purpose, conn->base_.address, &msg);
tor_assert(msg);
@@ -1686,7 +1697,8 @@ directory_handle_command_post,(dir_connection_t *conn, const char *headers,
log_info(LD_DIRSERV,
"Rejected router descriptor or extra-info from %s "
"(\"%s\").",
- conn->base_.address, msg);
+ connection_describe_peer(TO_CONN(conn)),
+ msg);
write_short_http_response(conn, 400, msg);
}
goto done;
@@ -1696,12 +1708,14 @@ directory_handle_command_post,(dir_connection_t *conn, const char *headers,
!strcmp(url,"/tor/post/vote")) { /* v3 networkstatus vote */
const char *msg = "OK";
int status;
- if (dirvote_add_vote(body, approx_time(), &msg, &status)) {
+ if (dirvote_add_vote(body, approx_time(), TO_CONN(conn)->address,
+ &msg, &status)) {
write_short_http_response(conn, status, "Vote stored");
} else {
tor_assert(msg);
log_warn(LD_DIRSERV, "Rejected vote from %s (\"%s\").",
- conn->base_.address, msg);
+ connection_describe_peer(TO_CONN(conn)),
+ msg);
write_short_http_response(conn, status, msg);
}
goto done;
@@ -1714,7 +1728,8 @@ directory_handle_command_post,(dir_connection_t *conn, const char *headers,
write_short_http_response(conn, 200, msg?msg:"Signatures stored");
} else {
log_warn(LD_DIR, "Unable to store signatures posted by %s: %s",
- conn->base_.address, msg?msg:"???");
+ connection_describe_peer(TO_CONN(conn)),
+ msg?msg:"???");
write_short_http_response(conn, 400,
msg?msg:"Unable to store signatures");
}
@@ -1775,8 +1790,8 @@ directory_handle_command(dir_connection_t *conn)
&body, &body_len, MAX_DIR_UL_SIZE, 0)) {
case -1: /* overflow */
log_warn(LD_DIRSERV,
- "Request too large from address '%s' to DirPort. Closing.",
- safe_str(conn->base_.address));
+ "Request too large from %s to DirPort. Closing.",
+ connection_describe_peer(TO_CONN(conn)));
return -1;
case 0:
log_debug(LD_DIRSERV,"command not all here yet.");
diff --git a/src/feature/dirclient/dir_server_st.h b/src/feature/dirclient/dir_server_st.h
index 37fa3148a7..57530a571b 100644
--- a/src/feature/dirclient/dir_server_st.h
+++ b/src/feature/dirclient/dir_server_st.h
@@ -24,10 +24,10 @@ struct dir_server_t {
char *address; /**< Hostname. */
/* XX/teor - why do we duplicate the address and port fields here and in
* fake_status? Surely we could just use fake_status (#17867). */
+ tor_addr_t ipv4_addr;
+ uint16_t ipv4_dirport; /**< Directory port. */
+ uint16_t ipv4_orport; /**< OR port: Used for tunneling connections. */
tor_addr_t ipv6_addr; /**< IPv6 address if present; AF_UNSPEC if not */
- uint32_t addr; /**< IPv4 address. */
- uint16_t dir_port; /**< Directory port. */
- uint16_t or_port; /**< OR port: Used for tunneling connections. */
uint16_t ipv6_orport; /**< OR port corresponding to ipv6_addr. */
double weight; /** Weight used when selecting this node at random */
char digest[DIGEST_LEN]; /**< Digest of identity key. */
diff --git a/src/feature/dirclient/dirclient.c b/src/feature/dirclient/dirclient.c
index ae1e018df2..a5dd856729 100644
--- a/src/feature/dirclient/dirclient.c
+++ b/src/feature/dirclient/dirclient.c
@@ -284,10 +284,10 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
}
if (purpose_needs_anonymity(dir_purpose, router_purpose, NULL)) {
indirection = DIRIND_ANONYMOUS;
- } else if (!fascist_firewall_allows_dir_server(ds,
+ } else if (!reachable_addr_allows_dir_server(ds,
FIREWALL_DIR_CONNECTION,
0)) {
- if (fascist_firewall_allows_dir_server(ds, FIREWALL_OR_CONNECTION, 0))
+ if (reachable_addr_allows_dir_server(ds, FIREWALL_OR_CONNECTION, 0))
indirection = DIRIND_ONEHOP;
else
indirection = DIRIND_ANONYMOUS;
@@ -487,7 +487,7 @@ directory_get_from_dirserver,(
tor_addr_port_t or_ap;
directory_request_t *req = directory_request_new(dir_purpose);
/* we are willing to use a non-preferred address if we need to */
- fascist_firewall_choose_address_node(node, FIREWALL_OR_CONNECTION, 0,
+ reachable_addr_choose_from_node(node, FIREWALL_OR_CONNECTION, 0,
&or_ap);
directory_request_set_or_addr_port(req, &or_ap);
directory_request_set_directory_id_digest(req,
@@ -654,11 +654,11 @@ directory_choose_address_routerstatus(const routerstatus_t *status,
/* ORPort connections */
if (indirection == DIRIND_ANONYMOUS) {
- if (status->addr) {
+ if (!tor_addr_is_null(&status->ipv4_addr)) {
/* Since we're going to build a 3-hop circuit and ask the 2nd relay
* to extend to this address, always use the primary (IPv4) OR address */
- tor_addr_from_ipv4h(&use_or_ap->addr, status->addr);
- use_or_ap->port = status->or_port;
+ tor_addr_copy(&use_or_ap->addr, &status->ipv4_addr);
+ use_or_ap->port = status->ipv4_orport;
have_or = 1;
}
} else if (indirection == DIRIND_ONEHOP) {
@@ -666,7 +666,7 @@ directory_choose_address_routerstatus(const routerstatus_t *status,
* Use the preferred address and port if they are reachable, otherwise,
* use the alternate address and port (if any).
*/
- fascist_firewall_choose_address_rs(status, FIREWALL_OR_CONNECTION, 0,
+ reachable_addr_choose_from_rs(status, FIREWALL_OR_CONNECTION, 0,
use_or_ap);
have_or = tor_addr_port_is_valid_ap(use_or_ap, 0);
}
@@ -677,7 +677,7 @@ directory_choose_address_routerstatus(const routerstatus_t *status,
indirection == DIRIND_ANON_DIRPORT ||
(indirection == DIRIND_ONEHOP
&& !dirclient_must_use_begindir(options))) {
- fascist_firewall_choose_address_rs(status, FIREWALL_DIR_CONNECTION, 0,
+ reachable_addr_choose_from_rs(status, FIREWALL_DIR_CONNECTION, 0,
use_dir_ap);
have_dir = tor_addr_port_is_valid_ap(use_dir_ap, 0);
}
@@ -686,12 +686,14 @@ directory_choose_address_routerstatus(const routerstatus_t *status,
* connect to it. */
if (!have_or && !have_dir) {
static int logged_backtrace = 0;
+ char *ipv6_str = tor_addr_to_str_dup(&status->ipv6_addr);
log_info(LD_BUG, "Rejected all OR and Dir addresses from %s when "
"launching an outgoing directory connection to: IPv4 %s OR %d "
"Dir %d IPv6 %s OR %d Dir %d", routerstatus_describe(status),
- fmt_addr32(status->addr), status->or_port,
- status->dir_port, fmt_addr(&status->ipv6_addr),
- status->ipv6_orport, status->dir_port);
+ fmt_addr(&status->ipv4_addr), status->ipv4_orport,
+ status->ipv4_dirport, ipv6_str, status->ipv6_orport,
+ status->ipv4_dirport);
+ tor_free(ipv6_str);
if (!logged_backtrace) {
log_backtrace(LOG_INFO, LD_BUG, "Addresses came from");
logged_backtrace = 1;
@@ -713,8 +715,8 @@ directory_conn_is_self_reachability_test(dir_connection_t *conn)
const routerinfo_t *me = router_get_my_routerinfo();
if (me &&
router_digest_is_me(conn->identity_digest) &&
- tor_addr_eq_ipv4h(&conn->base_.addr, me->addr) && /*XXXX prop 118*/
- me->dir_port == conn->base_.port)
+ tor_addr_eq(&TO_CONN(conn)->addr, &me->ipv4_addr) &&
+ me->ipv4_dirport == conn->base_.port)
return 1;
}
return 0;
@@ -740,8 +742,8 @@ connection_dir_client_request_failed(dir_connection_t *conn)
if (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
log_info(LD_DIR, "Giving up on serverdesc/extrainfo fetch from "
- "directory server at '%s'; retrying",
- conn->base_.address);
+ "directory server at %s; retrying",
+ connection_describe_peer(TO_CONN(conn)));
if (conn->router_purpose == ROUTER_PURPOSE_BRIDGE)
connection_dir_bridge_routerdesc_failed(conn);
connection_dir_download_routerdesc_failed(conn);
@@ -750,18 +752,19 @@ connection_dir_client_request_failed(dir_connection_t *conn)
networkstatus_consensus_download_failed(0, conn->requested_resource);
} else if (conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
log_info(LD_DIR, "Giving up on certificate fetch from directory server "
- "at '%s'; retrying",
- conn->base_.address);
+ "at %s; retrying",
+ connection_describe_peer(TO_CONN(conn)));
connection_dir_download_cert_failed(conn, 0);
} else if (conn->base_.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
- log_info(LD_DIR, "Giving up downloading detached signatures from '%s'",
- conn->base_.address);
+ log_info(LD_DIR, "Giving up downloading detached signatures from %s",
+ connection_describe_peer(TO_CONN(conn)));
} else if (conn->base_.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
- log_info(LD_DIR, "Giving up downloading votes from '%s'",
- conn->base_.address);
+ log_info(LD_DIR, "Giving up downloading votes from %s",
+ connection_describe_peer(TO_CONN(conn)));
} else if (conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC) {
log_info(LD_DIR, "Giving up on downloading microdescriptors from "
- "directory server at '%s'; will retry", conn->base_.address);
+ "directory server at %s; will retry",
+ connection_describe_peer(TO_CONN(conn)));
connection_dir_download_routerdesc_failed(conn);
}
}
@@ -918,7 +921,7 @@ directory_command_should_use_begindir(const or_options_t *options,
}
if (indirection == DIRIND_ONEHOP) {
/* We're firewalled and want a direct OR connection */
- if (!fascist_firewall_allows_address_addr(or_addr, or_port,
+ if (!reachable_addr_allows_addr(or_addr, or_port,
FIREWALL_OR_CONNECTION, 0, 0)) {
*reason = "ORPort not reachable";
return 0;
@@ -1754,10 +1757,10 @@ directory_send_command(dir_connection_t *conn,
smartlist_free(headers);
log_debug(LD_DIR,
- "Sent request to directory server '%s:%d': "
+ "Sent request to directory server %s "
"(purpose: %d, request size: %"TOR_PRIuSZ", "
"payload size: %"TOR_PRIuSZ")",
- conn->base_.address, conn->base_.port,
+ connection_describe_peer(TO_CONN(conn)),
conn->base_.purpose,
(total_request_len),
(payload ? payload_len : 0));
@@ -1893,9 +1896,10 @@ dir_client_decompress_response_body(char **bodyp, size_t *bodylenp,
}
tor_log(severity, LD_HTTP,
- "HTTP body from server '%s:%d' was labeled as %s, "
+ "HTTP body from %s was labeled as %s, "
"%s it seems to be %s.%s",
- conn->base_.address, conn->base_.port, description1,
+ connection_describe(TO_CONN(conn)),
+ description1,
guessed != compression?"but":"and",
description2,
(compression>0 && guessed>0 && want_to_try_both)?
@@ -1941,11 +1945,11 @@ dir_client_decompress_response_body(char **bodyp, size_t *bodylenp,
* we didn't manage to uncompress it, then warn and bail. */
if (!plausible && !new_body) {
log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
- "Unable to decompress HTTP body (tried %s%s%s, server '%s:%d').",
+ "Unable to decompress HTTP body (tried %s%s%s, on %s).",
description1,
tried_both?" and ":"",
tried_both?description2:"",
- conn->base_.address, conn->base_.port);
+ connection_describe(TO_CONN(conn)));
rv = -1;
goto done;
}
@@ -1983,7 +1987,7 @@ dirclient_dump_total_dls(void)
{
const or_options_t *options = get_options();
for (int bootstrapped = 0; bootstrapped < 2; ++bootstrapped) {
- bool first_time = true;
+ smartlist_t *lines = smartlist_new();
for (int i=0; i < DIR_PURPOSE_MAX_; ++i) {
uint64_t n = total_dl[i][bootstrapped];
if (n == 0)
@@ -1991,15 +1995,19 @@ dirclient_dump_total_dls(void)
if (options->SafeLogging_ != SAFELOG_SCRUB_NONE &&
purpose_needs_anonymity(i, ROUTER_PURPOSE_GENERAL, NULL))
continue;
- if (first_time) {
- log_notice(LD_NET,
- "While %sbootstrapping, fetched this many bytes: ",
- bootstrapped?"not ":"");
- first_time = false;
- }
- log_notice(LD_NET, " %"PRIu64" (%s)",
- n, dir_conn_purpose_to_string(i));
+ smartlist_add_asprintf(lines, "%"PRIu64" (%s)",
+ n, dir_conn_purpose_to_string(i));
}
+
+ if (smartlist_len(lines) > 0) {
+ char *log_line = smartlist_join_strings(lines, "; ", 0, NULL);
+ log_notice(LD_NET, "While %sbootstrapping, fetched this many bytes: %s",
+ bootstrapped?"not ":"", log_line);
+ tor_free(log_line);
+
+ SMARTLIST_FOREACH(lines, char *, s, tor_free(s));
+ }
+ smartlist_free(lines);
}
}
@@ -2052,8 +2060,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
allow_partial)) {
case -1: /* overflow */
log_warn(LD_PROTOCOL,
- "'fetch' response too large (server '%s:%d'). Closing.",
- conn->base_.address, conn->base_.port);
+ "'fetch' response too large (%s). Closing.",
+ connection_describe(TO_CONN(conn)));
return -1;
case 0:
log_info(LD_HTTP,
@@ -2064,22 +2072,22 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (parse_http_response(headers, &status_code, &date_header,
&compression, &reason) < 0) {
- log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
- conn->base_.address, conn->base_.port);
-
+ log_warn(LD_HTTP,"Unparseable headers (%s). Closing.",
+ connection_describe(TO_CONN(conn)));
rv = -1;
goto done;
}
if (!reason) reason = tor_strdup("[no reason given]");
tor_log(LOG_DEBUG, LD_DIR,
- "Received response from directory server '%s:%d': %d %s "
+ "Received response on %s: %d %s "
"(purpose: %d, response size: %"TOR_PRIuSZ
#ifdef MEASUREMENTS_21206
", data cells received: %d, data cells sent: %d"
#endif
", compression: %d)",
- conn->base_.address, conn->base_.port, status_code,
+ connection_describe(TO_CONN(conn)),
+ status_code,
escaped(reason), conn->base_.purpose,
(received_bytes),
#ifdef MEASUREMENTS_21206
@@ -2104,7 +2112,13 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (conn->dirconn_direct) {
char *guess = http_get_header(headers, X_ADDRESS_HEADER);
if (guess) {
- router_new_address_suggestion(guess, conn);
+ tor_addr_t addr;
+ if (tor_addr_parse(&addr, guess) < 0) {
+ log_debug(LD_DIR, "Malformed X-Your-Address-Is header %s. Ignoring.",
+ escaped(guess));
+ } else {
+ relay_address_new_suggestion(&addr, &TO_CONN(conn)->addr, NULL);
+ }
tor_free(guess);
}
}
@@ -2133,9 +2147,9 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
dir_server_t *ds;
const char *id_digest = conn->identity_digest;
log_info(LD_DIR,"Received http status code %d (%s) from server "
- "'%s:%d'. I'll try again soon.",
- status_code, escaped(reason), conn->base_.address,
- conn->base_.port);
+ "%s. I'll try again soon.",
+ status_code, escaped(reason),
+ connection_describe_peer(TO_CONN(conn)));
time_t now = approx_time();
if ((rs = router_get_mutable_consensus_status_by_id(id_digest)))
rs->last_dir_503_at = now;
@@ -2240,9 +2254,9 @@ handle_response_fetch_consensus(dir_connection_t *conn,
int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
tor_log(severity, LD_DIR,
"Received http status code %d (%s) from server "
- "'%s:%d' while fetching consensus directory.",
- status_code, escaped(reason), conn->base_.address,
- conn->base_.port);
+ "%s while fetching consensus directory.",
+ status_code, escaped(reason),
+ connection_describe_peer(TO_CONN(conn)));
networkstatus_consensus_download_failed(status_code, flavname);
return -1;
}
@@ -2277,21 +2291,21 @@ handle_response_fetch_consensus(dir_connection_t *conn,
tor_munmap_file(mapped_consensus);
if (new_consensus == NULL) {
log_warn(LD_DIR, "Could not apply consensus diff received from server "
- "'%s:%d'", conn->base_.address, conn->base_.port);
+ "%s", connection_describe_peer(TO_CONN(conn)));
// XXXX If this happens too many times, we should maybe not use
// XXXX this directory for diffs any more?
networkstatus_consensus_download_failed(0, flavname);
return -1;
}
log_info(LD_DIR, "Applied consensus diff (size %d) from server "
- "'%s:%d', resulting in a new consensus document (size %d).",
- (int)body_len, conn->base_.address, conn->base_.port,
+ "%s, resulting in a new consensus document (size %d).",
+ (int)body_len, connection_describe_peer(TO_CONN(conn)),
(int)strlen(new_consensus));
consensus = new_consensus;
sourcename = "generated based on a diff";
} else {
log_info(LD_DIR,"Received consensus directory (body size %d) from server "
- "'%s:%d'", (int)body_len, conn->base_.address, conn->base_.port);
+ "%s", (int)body_len, connection_describe_peer(TO_CONN(conn)));
consensus = body;
sourcename = "downloaded";
}
@@ -2302,8 +2316,9 @@ handle_response_fetch_consensus(dir_connection_t *conn,
conn->identity_digest))<0) {
log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
"Unable to load %s consensus directory %s from "
- "server '%s:%d'. I'll try again soon.",
- flavname, sourcename, conn->base_.address, conn->base_.port);
+ "server %s. I'll try again soon.",
+ flavname, sourcename,
+ connection_describe_peer(TO_CONN(conn)));
networkstatus_consensus_download_failed(0, flavname);
tor_free(new_consensus);
return -1;
@@ -2344,15 +2359,16 @@ handle_response_fetch_certificate(dir_connection_t *conn,
if (status_code != 200) {
log_warn(LD_DIR,
"Received http status code %d (%s) from server "
- "'%s:%d' while fetching \"/tor/keys/%s\".",
- status_code, escaped(reason), conn->base_.address,
- conn->base_.port, conn->requested_resource);
+ "%s while fetching \"/tor/keys/%s\".",
+ status_code, escaped(reason),
+ connection_describe_peer(TO_CONN(conn)),
+ conn->requested_resource);
connection_dir_download_cert_failed(conn, status_code);
return -1;
}
log_info(LD_DIR,"Received authority certificates (body size %d) from "
- "server '%s:%d'",
- (int)body_len, conn->base_.address, conn->base_.port);
+ "server %s",
+ (int)body_len, connection_describe_peer(TO_CONN(conn)));
/*
* Tell trusted_dirs_load_certs_from_string() whether it was by fp
@@ -2403,17 +2419,18 @@ handle_response_fetch_status_vote(dir_connection_t *conn,
const char *msg;
int st;
- log_info(LD_DIR,"Got votes (body size %d) from server %s:%d",
- (int)body_len, conn->base_.address, conn->base_.port);
+ log_notice(LD_DIR,"Got votes (body size %d) from server %s",
+ (int)body_len, connection_describe_peer(TO_CONN(conn)));
if (status_code != 200) {
log_warn(LD_DIR,
"Received http status code %d (%s) from server "
- "'%s:%d' while fetching \"/tor/status-vote/next/%s.z\".",
- status_code, escaped(reason), conn->base_.address,
- conn->base_.port, conn->requested_resource);
+ "%s while fetching \"/tor/status-vote/next/%s.z\".",
+ status_code, escaped(reason),
+ connection_describe_peer(TO_CONN(conn)),
+ conn->requested_resource);
return -1;
}
- dirvote_add_vote(body, 0, &msg, &st);
+ dirvote_add_vote(body, 0, TO_CONN(conn)->address, &msg, &st);
if (st > 299) {
log_warn(LD_DIR, "Error adding retrieved vote: %s", msg);
} else {
@@ -2438,19 +2455,21 @@ handle_response_fetch_detached_signatures(dir_connection_t *conn,
const size_t body_len = args->body_len;
const char *msg = NULL;
- log_info(LD_DIR,"Got detached signatures (body size %d) from server %s:%d",
- (int)body_len, conn->base_.address, conn->base_.port);
+ log_info(LD_DIR,"Got detached signatures (body size %d) from server %s",
+ (int)body_len,
+ connection_describe_peer(TO_CONN(conn)));
if (status_code != 200) {
log_warn(LD_DIR,
- "Received http status code %d (%s) from server '%s:%d' while fetching "
+ "Received http status code %d (%s) from server %s while fetching "
"\"/tor/status-vote/next/consensus-signatures.z\".",
- status_code, escaped(reason), conn->base_.address,
- conn->base_.port);
+ status_code, escaped(reason),
+ connection_describe_peer(TO_CONN(conn)));
return -1;
}
if (dirvote_add_signatures(body, conn->base_.address, &msg)<0) {
- log_warn(LD_DIR, "Problem adding detached signatures from %s:%d: %s",
- conn->base_.address, conn->base_.port, msg?msg:"???");
+ log_warn(LD_DIR, "Problem adding detached signatures from %s: %s",
+ connection_describe_peer(TO_CONN(conn)),
+ msg?msg:"???");
}
return 0;
@@ -2476,9 +2495,9 @@ handle_response_fetch_desc(dir_connection_t *conn,
int n_asked_for = 0;
int descriptor_digests = conn->requested_resource &&
!strcmpstart(conn->requested_resource,"d/");
- log_info(LD_DIR,"Received %s (body size %d) from server '%s:%d'",
+ log_info(LD_DIR,"Received %s (body size %d) from server %s",
was_ei ? "extra server info" : "server info",
- (int)body_len, conn->base_.address, conn->base_.port);
+ (int)body_len, connection_describe_peer(TO_CONN(conn)));
if (conn->requested_resource &&
(!strcmpstart(conn->requested_resource,"d/") ||
!strcmpstart(conn->requested_resource,"fp/"))) {
@@ -2490,14 +2509,18 @@ handle_response_fetch_desc(dir_connection_t *conn,
}
if (status_code != 200) {
int dir_okay = status_code == 404 ||
- (status_code == 400 && !strcmp(reason, "Servers unavailable."));
+ (status_code == 400 && !strcmp(reason, "Servers unavailable.")) ||
+ status_code == 301;
/* 404 means that it didn't have them; no big deal.
- * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
+ * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead.
+ * 301 is considered as an error since Tor does not follow redirects,
+ * which means we failed to reach the server we wanted. */
log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
- "Received http status code %d (%s) from server '%s:%d' "
+ "Received http status code %d (%s) from server %s "
"while fetching \"/tor/server/%s\". I'll try again soon.",
- status_code, escaped(reason), conn->base_.address,
- conn->base_.port, conn->requested_resource);
+ status_code, escaped(reason),
+ connection_describe_peer(TO_CONN(conn)),
+ conn->requested_resource);
if (!which) {
connection_dir_download_routerdesc_failed(conn);
} else {
@@ -2537,10 +2560,10 @@ handle_response_fetch_desc(dir_connection_t *conn,
}
}
if (which) { /* mark remaining ones as failed */
- log_info(LD_DIR, "Received %d/%d %s requested from %s:%d",
+ log_info(LD_DIR, "Received %d/%d %s requested from %s",
n_asked_for-smartlist_len(which), n_asked_for,
was_ei ? "extra-info documents" : "router descriptors",
- conn->base_.address, (int)conn->base_.port);
+ connection_describe_peer(TO_CONN(conn)));
if (smartlist_len(which)) {
dir_routerdesc_download_failed(which, status_code,
conn->router_purpose,
@@ -2571,9 +2594,9 @@ handle_response_fetch_microdesc(dir_connection_t *conn,
smartlist_t *which = NULL;
log_info(LD_DIR,"Received answer to microdescriptor request (status %d, "
- "body size %d) from server '%s:%d'",
- status_code, (int)body_len, conn->base_.address,
- conn->base_.port);
+ "body size %d) from server %s",
+ status_code, (int)body_len,
+ connection_describe_peer(TO_CONN(conn)));
tor_assert(conn->requested_resource &&
!strcmpstart(conn->requested_resource, "d/"));
tor_assert_nonfatal(!fast_mem_is_zero(conn->identity_digest, DIGEST_LEN));
@@ -2583,10 +2606,11 @@ handle_response_fetch_microdesc(dir_connection_t *conn,
DSR_DIGEST256|DSR_BASE64);
if (status_code != 200) {
log_info(LD_DIR, "Received status code %d (%s) from server "
- "'%s:%d' while fetching \"/tor/micro/%s\". I'll try again "
+ "%s while fetching \"/tor/micro/%s\". I'll try again "
"soon.",
- status_code, escaped(reason), conn->base_.address,
- (int)conn->base_.port, conn->requested_resource);
+ status_code, escaped(reason),
+ connection_describe_peer(TO_CONN(conn)),
+ conn->requested_resource);
dir_microdesc_download_failed(which, status_code, conn->identity_digest);
SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
smartlist_free(which);
@@ -2661,8 +2685,8 @@ handle_response_upload_dir(dir_connection_t *conn,
break;
case 400:
log_warn(LD_GENERAL,"http status 400 (%s) response from "
- "dirserver '%s:%d'. Please correct.",
- escaped(reason), conn->base_.address, conn->base_.port);
+ "dirserver %s. Please correct.",
+ escaped(reason), connection_describe_peer(TO_CONN(conn)));
control_event_server_status(LOG_WARN,
"BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
conn->base_.address, conn->base_.port, escaped(reason));
@@ -2670,10 +2694,10 @@ handle_response_upload_dir(dir_connection_t *conn,
default:
log_warn(LD_GENERAL,
"HTTP status %d (%s) was unexpected while uploading "
- "descriptor to server '%s:%d'. Possibly the server is "
+ "descriptor to server %s'. Possibly the server is "
"misconfigured?",
- status_code, escaped(reason), conn->base_.address,
- conn->base_.port);
+ status_code, escaped(reason),
+ connection_describe_peer(TO_CONN(conn)));
break;
}
/* return 0 in all cases, since we don't want to mark any
@@ -2696,21 +2720,21 @@ handle_response_upload_vote(dir_connection_t *conn,
switch (status_code) {
case 200: {
- log_notice(LD_DIR,"Uploaded a vote to dirserver %s:%d",
- conn->base_.address, conn->base_.port);
+ log_notice(LD_DIR,"Uploaded my vote to dirserver %s",
+ connection_describe_peer(TO_CONN(conn)));
}
break;
case 400:
log_warn(LD_DIR,"http status 400 (%s) response after uploading "
- "vote to dirserver '%s:%d'. Please correct.",
- escaped(reason), conn->base_.address, conn->base_.port);
+ "vote to dirserver %s. Please correct.",
+ escaped(reason), connection_describe_peer(TO_CONN(conn)));
break;
default:
log_warn(LD_GENERAL,
"HTTP status %d (%s) was unexpected while uploading "
- "vote to server '%s:%d'.",
- status_code, escaped(reason), conn->base_.address,
- conn->base_.port);
+ "vote to server %s.",
+ status_code, escaped(reason),
+ connection_describe_peer(TO_CONN(conn)));
break;
}
/* return 0 in all cases, since we don't want to mark any
@@ -2732,21 +2756,21 @@ handle_response_upload_signatures(dir_connection_t *conn,
switch (status_code) {
case 200: {
- log_notice(LD_DIR,"Uploaded signature(s) to dirserver %s:%d",
- conn->base_.address, conn->base_.port);
+ log_notice(LD_DIR,"Uploaded signature(s) to dirserver %s",
+ connection_describe_peer(TO_CONN(conn)));
}
break;
case 400:
log_warn(LD_DIR,"http status 400 (%s) response after uploading "
- "signatures to dirserver '%s:%d'. Please correct.",
- escaped(reason), conn->base_.address, conn->base_.port);
+ "signatures to dirserver %s. Please correct.",
+ escaped(reason), connection_describe_peer(TO_CONN(conn)));
break;
default:
log_warn(LD_GENERAL,
"HTTP status %d (%s) was unexpected while uploading "
- "signatures to server '%s:%d'.",
- status_code, escaped(reason), conn->base_.address,
- conn->base_.port);
+ "signatures to server %s.",
+ status_code, escaped(reason),
+ connection_describe_peer(TO_CONN(conn)));
break;
}
/* return 0 in all cases, since we don't want to mark any
@@ -2861,10 +2885,10 @@ handle_response_fetch_renddesc_v2(dir_connection_t *conn,
default:
log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
"http status %d (%s) response unexpected while "
- "fetching v2 hidden service descriptor (server '%s:%d'). "
+ "fetching v2 hidden service descriptor (server %s). "
"Retrying at another directory.",
- status_code, escaped(reason), conn->base_.address,
- conn->base_.port);
+ status_code, escaped(reason),
+ connection_describe_peer(TO_CONN(conn)));
SEND_HS_DESC_FAILED_EVENT("UNEXPECTED");
SEND_HS_DESC_FAILED_CONTENT();
break;
@@ -2908,15 +2932,15 @@ handle_response_upload_renddesc_v2(dir_connection_t *conn,
break;
case 400:
log_warn(LD_REND,"http status 400 (%s) response from dirserver "
- "'%s:%d'. Malformed rendezvous descriptor?",
- escaped(reason), conn->base_.address, conn->base_.port);
+ "%s. Malformed rendezvous descriptor?",
+ escaped(reason), connection_describe_peer(TO_CONN(conn)));
SEND_HS_DESC_UPLOAD_FAILED_EVENT("UPLOAD_REJECTED");
break;
default:
log_warn(LD_REND,"http status %d (%s) response unexpected (server "
- "'%s:%d').",
- status_code, escaped(reason), conn->base_.address,
- conn->base_.port);
+ "%s).",
+ status_code, escaped(reason),
+ connection_describe_peer(TO_CONN(conn)));
SEND_HS_DESC_UPLOAD_FAILED_EVENT("UNEXPECTED");
break;
}
@@ -2954,17 +2978,17 @@ handle_response_upload_hsdesc(dir_connection_t *conn,
log_fn(LOG_PROTOCOL_WARN, LD_REND,
"Uploading hidden service descriptor: http "
"status 400 (%s) response from dirserver "
- "'%s:%d'. Malformed hidden service descriptor?",
- escaped(reason), conn->base_.address, conn->base_.port);
+ "%s. Malformed hidden service descriptor?",
+ escaped(reason), connection_describe_peer(TO_CONN(conn)));
hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest,
"UPLOAD_REJECTED");
break;
default:
log_warn(LD_REND, "Uploading hidden service descriptor: http "
"status %d (%s) response unexpected (server "
- "'%s:%d').",
- status_code, escaped(reason), conn->base_.address,
- conn->base_.port);
+ "%s').",
+ status_code, escaped(reason),
+ connection_describe_peer(TO_CONN(conn)));
hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest,
"UNEXPECTED");
break;
@@ -3116,7 +3140,7 @@ connection_dir_close_consensus_fetches(dir_connection_t *except_this_one,
if (d == except_this_one)
continue;
log_info(LD_DIR, "Closing consensus fetch (to %s) since one "
- "has just arrived.", TO_CONN(d)->address);
+ "has just arrived.", connection_describe_peer(TO_CONN(d)));
connection_mark_for_close(TO_CONN(d));
} SMARTLIST_FOREACH_END(d);
smartlist_free(conns_to_close);
diff --git a/src/feature/dirclient/dirclient_modes.c b/src/feature/dirclient/dirclient_modes.c
index 31a3f8af58..db25196213 100644
--- a/src/feature/dirclient/dirclient_modes.c
+++ b/src/feature/dirclient/dirclient_modes.c
@@ -40,15 +40,11 @@ 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)
diff --git a/src/feature/dircommon/consdiff.c b/src/feature/dircommon/consdiff.c
index e42378c44c..988d7f71ab 100644
--- a/src/feature/dircommon/consdiff.c
+++ b/src/feature/dircommon/consdiff.c
@@ -829,7 +829,7 @@ gen_ed_diff(const smartlist_t *cons1_orig, const smartlist_t *cons2,
}
/* Helper: Read a base-10 number between 0 and INT32_MAX from <b>s</b> and
- * store it in <b>num_out</b>. Advance <b>s</b> to the characer immediately
+ * store it in <b>num_out</b>. Advance <b>s</b> to the character immediately
* after the number. Return 0 on success, -1 on failure. */
static int
get_linenum(const char **s, int *num_out)
@@ -1335,7 +1335,7 @@ consensus_join_lines(const smartlist_t *inp)
}
/** Given two consensus documents, try to compute a diff between them. On
- * success, retun a newly allocated string containing that diff. On failure,
+ * success, return a newly allocated string containing that diff. On failure,
* return NULL. */
char *
consensus_diff_generate(const char *cons1, size_t cons1len,
diff --git a/src/feature/dircommon/directory.c b/src/feature/dircommon/directory.c
index b177fe5201..b276ac3441 100644
--- a/src/feature/dircommon/directory.c
+++ b/src/feature/dircommon/directory.c
@@ -79,8 +79,12 @@
* connection_finished_connecting() in connection.c
*/
-/** Convert a connection_t* to a dir_connection_t*; assert if the cast is
- * invalid. */
+/**
+ * Cast a `connection_t *` to a `dir_connection_t *`.
+ *
+ * Exit with an assertion failure if the input is not a
+ * `dir_connection_t`.
+ **/
dir_connection_t *
TO_DIR_CONN(connection_t *c)
{
@@ -88,6 +92,18 @@ TO_DIR_CONN(connection_t *c)
return DOWNCAST(dir_connection_t, c);
}
+/**
+ * Cast a `const connection_t *` to a `const dir_connection_t *`.
+ *
+ * Exit with an assertion failure if the input is not a
+ * `dir_connection_t`.
+ **/
+const dir_connection_t *
+CONST_TO_DIR_CONN(const connection_t *c)
+{
+ return TO_DIR_CONN((connection_t *)c);
+}
+
/** Return false if the directory purpose <b>dir_purpose</b>
* does not require an anonymous (three-hop) connection.
*
@@ -217,7 +233,7 @@ connection_dir_is_anonymous(const dir_connection_t *dir_conn)
return false;
}
- edge_conn = TO_EDGE_CONN((connection_t *) linked_conn);
+ edge_conn = CONST_TO_EDGE_CONN(linked_conn);
circ = edge_conn->on_circuit;
/* Can't be a circuit we initiated and without a circuit, no channel. */
@@ -455,9 +471,9 @@ connection_dir_process_inbuf(dir_connection_t *conn)
if (connection_get_inbuf_len(TO_CONN(conn)) > max_size) {
log_warn(LD_HTTP,
- "Too much data received from directory connection (%s): "
+ "Too much data received from %s: "
"denial of service attempt, or you need to upgrade?",
- conn->base_.address);
+ connection_describe(TO_CONN(conn)));
connection_mark_for_close(TO_CONN(conn));
return -1;
}
@@ -540,8 +556,8 @@ connection_dir_finished_connecting(dir_connection_t *conn)
tor_assert(conn->base_.type == CONN_TYPE_DIR);
tor_assert(conn->base_.state == DIR_CONN_STATE_CONNECTING);
- log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
- conn->base_.address,conn->base_.port);
+ log_debug(LD_HTTP,"Dir connection to %s established.",
+ connection_describe_peer(TO_CONN(conn)));
/* start flushing conn */
conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING;
diff --git a/src/feature/dircommon/directory.h b/src/feature/dircommon/directory.h
index 0f26cdeff9..0aa2ff53ef 100644
--- a/src/feature/dircommon/directory.h
+++ b/src/feature/dircommon/directory.h
@@ -13,6 +13,7 @@
#define TOR_DIRECTORY_H
dir_connection_t *TO_DIR_CONN(connection_t *c);
+const dir_connection_t *CONST_TO_DIR_CONN(const connection_t *c);
#define DIR_CONN_STATE_MIN_ 1
/** State for connection to directory server: waiting for connect(). */
diff --git a/src/feature/dirparse/authcert_parse.c b/src/feature/dirparse/authcert_parse.c
index deb45c12de..b2460f6ace 100644
--- a/src/feature/dirparse/authcert_parse.c
+++ b/src/feature/dirparse/authcert_parse.c
@@ -130,13 +130,13 @@ authority_cert_parse_from_string(const char *s, size_t maxlen,
tor_assert(tok->n_args);
/* XXX++ use some tor_addr parse function below instead. -RD */
if (tor_addr_port_split(LOG_WARN, tok->args[0], &address,
- &cert->dir_port) < 0 ||
+ &cert->ipv4_dirport) < 0 ||
tor_inet_aton(address, &in) == 0) {
log_warn(LD_DIR, "Couldn't parse dir-address in certificate");
tor_free(address);
goto err;
}
- cert->addr = ntohl(in.s_addr);
+ tor_addr_from_in(&cert->ipv4_addr, &in);
tor_free(address);
}
diff --git a/src/feature/dirparse/microdesc_parse.c b/src/feature/dirparse/microdesc_parse.c
index 9231080aaa..31415f3fb7 100644
--- a/src/feature/dirparse/microdesc_parse.c
+++ b/src/feature/dirparse/microdesc_parse.c
@@ -31,7 +31,7 @@
// clang-format off
static token_rule_t microdesc_token_table[] = {
T1_START("onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024),
- T01("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ),
+ T1("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ),
T0N("id", K_ID, GE(2), NO_OBJ ),
T0N("a", K_A, GE(1), NO_OBJ ),
T01("family", K_FAMILY, CONCAT_ARGS, NO_OBJ ),
diff --git a/src/feature/dirparse/ns_parse.c b/src/feature/dirparse/ns_parse.c
index ac9325a608..138d248b08 100644
--- a/src/feature/dirparse/ns_parse.c
+++ b/src/feature/dirparse/ns_parse.c
@@ -13,6 +13,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
+#include "core/or/protover.h"
#include "core/or/versions.h"
#include "feature/client/entrynodes.h"
#include "feature/dirauth/dirvote.h"
@@ -53,7 +54,7 @@ static token_rule_t rtrstatus_token_table[] = {
T01("w", K_W, ARGS, NO_OBJ ),
T0N("m", K_M, CONCAT_ARGS, NO_OBJ ),
T0N("id", K_ID, GE(2), NO_OBJ ),
- T01("pr", K_PROTO, CONCAT_ARGS, NO_OBJ ),
+ T1("pr", K_PROTO, CONCAT_ARGS, NO_OBJ ),
T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
END_OF_TABLE
};
@@ -246,7 +247,7 @@ routerstatus_parse_guardfraction(const char *guardfraction_str,
tor_assert(bool_eq(vote, vote_rs));
- /* If this info comes from a consensus, but we should't apply
+ /* If this info comes from a consensus, but we shouldn't apply
guardfraction, just exit. */
if (is_consensus && !should_apply_guardfraction(NULL)) {
return 0;
@@ -384,12 +385,12 @@ routerstatus_parse_entry_from_string(memarea_t *area,
escaped(tok->args[5+offset]));
goto err;
}
- rs->addr = ntohl(in.s_addr);
+ tor_addr_from_in(&rs->ipv4_addr, &in);
- rs->or_port = (uint16_t) tor_parse_long(tok->args[6+offset],
- 10,0,65535,NULL,NULL);
- rs->dir_port = (uint16_t) tor_parse_long(tok->args[7+offset],
- 10,0,65535,NULL,NULL);
+ rs->ipv4_orport = (uint16_t) tor_parse_long(tok->args[6+offset],
+ 10,0,65535,NULL,NULL);
+ rs->ipv4_dirport = (uint16_t) tor_parse_long(tok->args[7+offset],
+ 10,0,65535,NULL,NULL);
{
smartlist_t *a_lines = find_all_by_keyword(tokens, K_A);
@@ -466,6 +467,10 @@ routerstatus_parse_entry_from_string(memarea_t *area,
}
}
+ // If the protover line is malformed, reject this routerstatus.
+ if (protocols && protover_list_is_invalid(protocols)) {
+ goto err;
+ }
summarize_protover_flags(&rs->pv, protocols, version);
}
@@ -563,7 +568,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
log_info(LD_BUG, "Found an entry in networkstatus with no "
"microdescriptor digest. (Router %s ($%s) at %s:%d.)",
rs->nickname, hex_str(rs->identity_digest, DIGEST_LEN),
- fmt_addr32(rs->addr), rs->or_port);
+ fmt_addr(&rs->ipv4_addr), rs->ipv4_orport);
}
}
@@ -1063,6 +1068,19 @@ extract_shared_random_srvs(networkstatus_t *ns, smartlist_t *tokens)
}
}
+/** Allocate a copy of a protover line, if present. If present but malformed,
+ * set *error to true. */
+static char *
+dup_protocols_string(smartlist_t *tokens, bool *error, directory_keyword kw)
+{
+ directory_token_t *tok = find_opt_by_keyword(tokens, kw);
+ if (!tok)
+ return NULL;
+ if (protover_list_is_invalid(tok->args[0]))
+ *error = true;
+ return tor_strdup(tok->args[0]);
+}
+
/** Parse a v3 networkstatus vote, opinion, or consensus (depending on
* ns_type), from <b>s</b>, and return the result. Return NULL on failure. */
networkstatus_t *
@@ -1184,14 +1202,18 @@ networkstatus_parse_vote_from_string(const char *s,
}
}
- if ((tok = find_opt_by_keyword(tokens, K_RECOMMENDED_CLIENT_PROTOCOLS)))
- ns->recommended_client_protocols = tor_strdup(tok->args[0]);
- if ((tok = find_opt_by_keyword(tokens, K_RECOMMENDED_RELAY_PROTOCOLS)))
- ns->recommended_relay_protocols = tor_strdup(tok->args[0]);
- if ((tok = find_opt_by_keyword(tokens, K_REQUIRED_CLIENT_PROTOCOLS)))
- ns->required_client_protocols = tor_strdup(tok->args[0]);
- if ((tok = find_opt_by_keyword(tokens, K_REQUIRED_RELAY_PROTOCOLS)))
- ns->required_relay_protocols = tor_strdup(tok->args[0]);
+ // Reject the vote if any of the protocols lines are malformed.
+ bool unparseable = false;
+ ns->recommended_client_protocols = dup_protocols_string(tokens, &unparseable,
+ K_RECOMMENDED_CLIENT_PROTOCOLS);
+ ns->recommended_relay_protocols = dup_protocols_string(tokens, &unparseable,
+ K_RECOMMENDED_RELAY_PROTOCOLS);
+ ns->required_client_protocols = dup_protocols_string(tokens, &unparseable,
+ K_REQUIRED_CLIENT_PROTOCOLS);
+ ns->required_relay_protocols = dup_protocols_string(tokens, &unparseable,
+ K_REQUIRED_RELAY_PROTOCOLS);
+ if (unparseable)
+ goto err;
tok = find_by_keyword(tokens, K_VALID_AFTER);
if (parse_iso_time(tok->args[0], &ns->valid_after))
@@ -1354,8 +1376,8 @@ networkstatus_parse_vote_from_string(const char *s,
goto err;
}
if (ns->type != NS_TYPE_CONSENSUS) {
- if (authority_cert_is_blacklisted(ns->cert)) {
- log_warn(LD_DIR, "Rejecting vote signature made with blacklisted "
+ if (authority_cert_is_denylisted(ns->cert)) {
+ log_warn(LD_DIR, "Rejecting vote signature made with denylisted "
"signing key %s",
hex_str(ns->cert->signing_key_digest, DIGEST_LEN));
goto err;
@@ -1367,13 +1389,13 @@ networkstatus_parse_vote_from_string(const char *s,
escaped(tok->args[3]));
goto err;
}
- voter->addr = ntohl(in.s_addr);
+ tor_addr_from_in(&voter->ipv4_addr, &in);
int ok;
- voter->dir_port = (uint16_t)
+ voter->ipv4_dirport = (uint16_t)
tor_parse_long(tok->args[4], 10, 0, 65535, &ok, NULL);
if (!ok)
goto err;
- voter->or_port = (uint16_t)
+ voter->ipv4_orport = (uint16_t)
tor_parse_long(tok->args[5], 10, 0, 65535, &ok, NULL);
if (!ok)
goto err;
@@ -1453,6 +1475,7 @@ networkstatus_parse_vote_from_string(const char *s,
smartlist_add(ns->routerstatus_list, rs);
} else {
vote_routerstatus_free(rs);
+ goto err; // Malformed routerstatus, reject this vote.
}
} else {
routerstatus_t *rs;
@@ -1463,6 +1486,8 @@ networkstatus_parse_vote_from_string(const char *s,
flav))) {
/* Use exponential-backoff scheduling when downloading microdescs */
smartlist_add(ns->routerstatus_list, rs);
+ } else {
+ goto err; // Malformed routerstatus, reject this vote.
}
}
}
diff --git a/src/feature/dirparse/routerparse.c b/src/feature/dirparse/routerparse.c
index 8828a0f97a..3d90c1bc91 100644
--- a/src/feature/dirparse/routerparse.c
+++ b/src/feature/dirparse/routerparse.c
@@ -91,24 +91,24 @@ const token_rule_t routerdesc_token_table[] = {
T01("ipv6-policy", K_IPV6_POLICY, CONCAT_ARGS, NO_OBJ),
T1( "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
T1( "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ),
- T01("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ),
+ T1("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ),
T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
T01("uptime", K_UPTIME, GE(1), NO_OBJ ),
T01("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ ),
T01("platform", K_PLATFORM, CONCAT_ARGS, NO_OBJ ),
- T01("proto", K_PROTO, CONCAT_ARGS, NO_OBJ ),
+ T1("proto", K_PROTO, CONCAT_ARGS, NO_OBJ ),
T01("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
T01("extra-info-digest", K_EXTRA_INFO_DIGEST, GE(1), NO_OBJ ),
T01("hidden-service-dir", K_HIDDEN_SERVICE_DIR, NO_ARGS, NO_OBJ ),
- T01("identity-ed25519", K_IDENTITY_ED25519, NO_ARGS, NEED_OBJ ),
- T01("master-key-ed25519", K_MASTER_KEY_ED25519, GE(1), NO_OBJ ),
- T01("router-sig-ed25519", K_ROUTER_SIG_ED25519, GE(1), NO_OBJ ),
- T01("onion-key-crosscert", K_ONION_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),
- T01("ntor-onion-key-crosscert", K_NTOR_ONION_KEY_CROSSCERT,
+ T1("identity-ed25519", K_IDENTITY_ED25519, NO_ARGS, NEED_OBJ ),
+ T1("master-key-ed25519", K_MASTER_KEY_ED25519, GE(1), NO_OBJ ),
+ T1("router-sig-ed25519", K_ROUTER_SIG_ED25519, GE(1), NO_OBJ ),
+ T1("onion-key-crosscert", K_ONION_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),
+ T1("ntor-onion-key-crosscert", K_NTOR_ONION_KEY_CROSSCERT,
EQ(1), NEED_OBJ ),
T01("allow-single-hop-exits",K_ALLOW_SINGLE_HOP_EXITS, NO_ARGS, NO_OBJ ),
@@ -131,8 +131,8 @@ const token_rule_t routerdesc_token_table[] = {
static token_rule_t extrainfo_token_table[] = {
T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
- T01("identity-ed25519", K_IDENTITY_ED25519, NO_ARGS, NEED_OBJ ),
- T01("router-sig-ed25519", K_ROUTER_SIG_ED25519, GE(1), NO_OBJ ),
+ T1("identity-ed25519", K_IDENTITY_ED25519, NO_ARGS, NEED_OBJ ),
+ T1("router-sig-ed25519", K_ROUTER_SIG_ED25519, GE(1), NO_OBJ ),
T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
@@ -456,6 +456,12 @@ router_parse_entry_from_string(const char *s, const char *end,
}
}
+ if (!tor_memstr(s, end-s, "\nproto ")) {
+ log_debug(LD_DIR, "Found an obsolete router descriptor. "
+ "Rejecting quietly.");
+ goto err;
+ }
+
if (router_get_router_hash(s, end - s, digest) < 0) {
log_warn(LD_DIR, "Couldn't compute router hash.");
goto err;
@@ -519,15 +525,15 @@ router_parse_entry_from_string(const char *s, const char *end,
log_warn(LD_DIR,"Router address is not an IP address.");
goto err;
}
- router->addr = ntohl(in.s_addr);
+ tor_addr_from_in(&router->ipv4_addr, &in);
- router->or_port =
+ router->ipv4_orport =
(uint16_t) tor_parse_long(tok->args[2],10,0,65535,&ok,NULL);
if (!ok) {
log_warn(LD_DIR,"Invalid OR port %s", escaped(tok->args[2]));
goto err;
}
- router->dir_port =
+ router->ipv4_dirport =
(uint16_t) tor_parse_long(tok->args[4],10,0,65535,&ok,NULL);
if (!ok) {
log_warn(LD_DIR,"Invalid dir port %s", escaped(tok->args[4]));
@@ -653,17 +659,18 @@ router_parse_entry_from_string(const char *s, const char *end,
goto err;
}
if (strcmp(ed_cert_tok->object_type, "ED25519 CERT")) {
- log_warn(LD_DIR, "Wrong object type on identity-ed25519 in decriptor");
+ log_warn(LD_DIR, "Wrong object type on identity-ed25519 "
+ "in descriptor");
goto err;
}
if (strcmp(cc_ntor_tok->object_type, "ED25519 CERT")) {
log_warn(LD_DIR, "Wrong object type on ntor-onion-key-crosscert "
- "in decriptor");
+ "in descriptor");
goto err;
}
if (strcmp(cc_tap_tok->object_type, "CROSSCERT")) {
log_warn(LD_DIR, "Wrong object type on onion-key-crosscert "
- "in decriptor");
+ "in descriptor");
goto err;
}
if (strcmp(cc_ntor_tok->args[0], "0") &&
@@ -907,13 +914,14 @@ router_parse_entry_from_string(const char *s, const char *end,
/* This router accepts tunnelled directory requests via begindir if it has
* an open dirport or it included "tunnelled-dir-server". */
- if (find_opt_by_keyword(tokens, K_DIR_TUNNELLED) || router->dir_port > 0) {
+ if (find_opt_by_keyword(tokens, K_DIR_TUNNELLED) ||
+ router->ipv4_dirport > 0) {
router->supports_tunnelled_dir_requests = 1;
}
tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
- if (!router->or_port) {
+ if (!router->ipv4_orport) {
log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
goto err;
}
@@ -989,6 +997,11 @@ extrainfo_parse_entry_from_string(const char *s, const char *end,
while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
--end;
+ if (!tor_memstr(s, end-s, "\nidentity-ed25519")) {
+ log_debug(LD_DIR, "Found an obsolete extrainfo. Rejecting quietly.");
+ goto err;
+ }
+
if (router_get_extrainfo_hash(s, end-s, digest) < 0) {
log_warn(LD_DIR, "Couldn't compute router hash.");
goto err;
@@ -1064,7 +1077,8 @@ extrainfo_parse_entry_from_string(const char *s, const char *end,
goto err;
}
if (strcmp(ed_cert_tok->object_type, "ED25519 CERT")) {
- log_warn(LD_DIR, "Wrong object type on identity-ed25519 in decriptor");
+ log_warn(LD_DIR, "Wrong object type on identity-ed25519 "
+ "in descriptor");
goto err;
}
diff --git a/src/feature/dirparse/sigcommon.c b/src/feature/dirparse/sigcommon.c
index 8b970d7d1f..fb81b2da6e 100644
--- a/src/feature/dirparse/sigcommon.c
+++ b/src/feature/dirparse/sigcommon.c
@@ -139,13 +139,13 @@ signed_digest_equals, (const uint8_t *d1, const uint8_t *d2, size_t len))
* the document when generating log messages. Return 0 on success, negative
* on failure.
*/
-int
-check_signature_token(const char *digest,
+MOCK_IMPL(int,
+check_signature_token,(const char *digest,
ssize_t digest_len,
directory_token_t *tok,
crypto_pk_t *pkey,
int flags,
- const char *doctype)
+ const char *doctype))
{
char *signed_digest;
size_t keysize;
diff --git a/src/feature/dirparse/sigcommon.h b/src/feature/dirparse/sigcommon.h
index c2ed9df494..c7f370f8e8 100644
--- a/src/feature/dirparse/sigcommon.h
+++ b/src/feature/dirparse/sigcommon.h
@@ -20,12 +20,12 @@ int router_get_hash_impl(const char *s, size_t s_len, char *digest,
#define CST_NO_CHECK_OBJTYPE (1<<0)
struct directory_token_t;
-int check_signature_token(const char *digest,
- ssize_t digest_len,
- struct directory_token_t *tok,
- crypto_pk_t *pkey,
- int flags,
- const char *doctype);
+MOCK_DECL(int, check_signature_token,(const char *digest,
+ ssize_t digest_len,
+ struct directory_token_t *tok,
+ crypto_pk_t *pkey,
+ int flags,
+ const char *doctype));
int router_get_hash_impl_helper(const char *s, size_t s_len,
const char *start_str,
diff --git a/src/feature/feature.md b/src/feature/feature.md
index acc3487e55..d9f7bd5c0e 100644
--- a/src/feature/feature.md
+++ b/src/feature/feature.md
@@ -5,3 +5,26 @@ 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.
+Current subdirectories are:
+
+ - \refdir{feature/api} -- Support for making Tor embeddable
+ - \refdir{feature/client} -- Functionality which only Tor clients need
+ - \refdir{feature/control} -- Controller implementation
+ - \refdir{feature/dirauth} -- Directory authority
+ - \refdir{feature/dircache} -- Directory cache
+ - \refdir{feature/dirclient} -- Directory client
+ - \refdir{feature/dircommon} -- Shared code between the other directory modules
+ - \refdir{feature/dirparse} -- Directory parsing code.
+ - \refdir{feature/hibernate} -- Hibernating when Tor is out of bandwidth
+ or shutting down
+ - \refdir{feature/hs} -- v3 onion service implementation
+ - \refdir{feature/hs_common} -- shared code between both onion service
+ implementations
+ - \refdir{feature/keymgt} -- shared code for key management between
+ relays and onion services.
+ - \refdir{feature/nodelist} -- storing and accessing the list of relays on
+ the network.
+ - \refdir{feature/relay} -- code that only relay servers and exit servers
+ need.
+ - \refdir{feature/rend} -- v2 onion service implementation
+ - \refdir{feature/stats} -- statistics and history
diff --git a/src/feature/hibernate/hibernate.h b/src/feature/hibernate/hibernate.h
index 2383658b20..48a03e8239 100644
--- a/src/feature/hibernate/hibernate.h
+++ b/src/feature/hibernate/hibernate.h
@@ -48,7 +48,7 @@ typedef enum {
/** We are hibernating, and we won't wake up till there's more bandwidth to
* use. */
HIBERNATE_STATE_DORMANT=4,
- /** We start out in state default, which means we havent decided which state
+ /** We start out in state default, which means we haven't decided which state
* we're in. */
HIBERNATE_STATE_INITIAL=5
} hibernate_state_t;
diff --git a/src/feature/hs/hs_cache.c b/src/feature/hs/hs_cache.c
index ef5e88e947..9c35936748 100644
--- a/src/feature/hs/hs_cache.c
+++ b/src/feature/hs/hs_cache.c
@@ -353,6 +353,31 @@ static digest256map_t *hs_cache_v3_client;
* objects all related to a specific service. */
static digest256map_t *hs_cache_client_intro_state;
+#define cache_client_desc_free(val) \
+ FREE_AND_NULL(hs_cache_client_descriptor_t, cache_client_desc_free_, (val))
+
+/** Free memory allocated by <b>desc</b>. */
+static void
+cache_client_desc_free_(hs_cache_client_descriptor_t *desc)
+{
+ if (desc == NULL) {
+ return;
+ }
+ hs_descriptor_free(desc->desc);
+ memwipe(&desc->key, 0, sizeof(desc->key));
+ memwipe(desc->encoded_desc, 0, strlen(desc->encoded_desc));
+ tor_free(desc->encoded_desc);
+ tor_free(desc);
+}
+
+/** Helper function: Use by the free all function to clear the client cache */
+static void
+cache_client_desc_free_void(void *ptr)
+{
+ hs_cache_client_descriptor_t *desc = ptr;
+ cache_client_desc_free(desc);
+}
+
/** 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)
@@ -390,7 +415,18 @@ remove_v3_desc_as_client(const hs_cache_client_descriptor_t *desc)
static void
store_v3_desc_as_client(hs_cache_client_descriptor_t *desc)
{
+ hs_cache_client_descriptor_t *cached_desc;
+
tor_assert(desc);
+
+ /* Because the lookup function doesn't return an expired entry, it can linger
+ * in the cache until we clean it up or a new descriptor is stored. So,
+ * before adding, we'll make sure we are not overwriting an old descriptor
+ * (which is OK in terms of semantic) but leads to memory leak. */
+ cached_desc = digest256map_get(hs_cache_v3_client, desc->key.pubkey);
+ if (cached_desc) {
+ cache_client_desc_free(cached_desc);
+ }
digest256map_set(hs_cache_v3_client, desc->key.pubkey, desc);
/* Update cache size with this entry for the OOM handler. */
rend_cache_increment_allocation(cache_get_client_entry_size(desc));
@@ -473,31 +509,6 @@ cache_client_desc_new(const char *desc_str,
return client_desc;
}
-#define cache_client_desc_free(val) \
- FREE_AND_NULL(hs_cache_client_descriptor_t, cache_client_desc_free_, (val))
-
-/** Free memory allocated by <b>desc</b>. */
-static void
-cache_client_desc_free_(hs_cache_client_descriptor_t *desc)
-{
- if (desc == NULL) {
- return;
- }
- hs_descriptor_free(desc->desc);
- memwipe(&desc->key, 0, sizeof(desc->key));
- memwipe(desc->encoded_desc, 0, strlen(desc->encoded_desc));
- tor_free(desc->encoded_desc);
- tor_free(desc);
-}
-
-/** Helper function: Use by the free all function to clear the client cache */
-static void
-cache_client_desc_free_void(void *ptr)
-{
- hs_cache_client_descriptor_t *desc = ptr;
- cache_client_desc_free(desc);
-}
-
/** Return a newly allocated and initialized hs_cache_intro_state_t object. */
static hs_cache_intro_state_t *
cache_intro_state_new(void)
@@ -857,7 +868,7 @@ hs_cache_lookup_as_client(const ed25519_public_key_t *key)
* was not usable but the descriptor was
* still stored.
*
- * Any other codes means indicate where the error occured and the descriptor
+ * Any other codes means indicate where the error occurred and the descriptor
* was not stored. */
hs_desc_decode_status_t
hs_cache_store_as_client(const char *desc_str,
@@ -1022,7 +1033,7 @@ hs_cache_client_intro_state_purge(void)
}
/* 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.
+ * It attempts to decode the descriptor of the given service identity key.
*
* Return true if decoding was successful else false. */
bool
diff --git a/src/feature/hs/hs_cell.c b/src/feature/hs/hs_cell.c
index fc9f4a2654..8bdaa4922a 100644
--- a/src/feature/hs/hs_cell.c
+++ b/src/feature/hs/hs_cell.c
@@ -56,7 +56,7 @@ compute_introduce_mac(const uint8_t *encoded_cell, size_t encoded_cell_len,
/* First, put the encoded cell in the msg. */
memcpy(mac_msg, encoded_cell, encoded_cell_len);
offset += encoded_cell_len;
- /* Second, put the CLIENT_PK + ENCRYPTED_DATA but ommit the MAC field (which
+ /* Second, put the CLIENT_PK + ENCRYPTED_DATA but omit the MAC field (which
* is junk at this point). */
memcpy(mac_msg + offset, encrypted, (encrypted_len - DIGEST256_LEN));
offset += (encrypted_len - DIGEST256_LEN);
@@ -293,7 +293,7 @@ introduce1_set_encrypted_link_spec(trn_cell_introduce_encrypted_t *cell,
}
/** 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. */
+ * sections are below the minimum required for an INTRODUCE1 cell. */
static void
introduce1_set_encrypted_padding(const trn_cell_introduce1_t *cell,
trn_cell_introduce_encrypted_t *enc_cell)
diff --git a/src/feature/hs/hs_cell.h b/src/feature/hs/hs_cell.h
index 2b28c44c50..5889e7c6dd 100644
--- a/src/feature/hs/hs_cell.h
+++ b/src/feature/hs/hs_cell.h
@@ -3,7 +3,7 @@
/**
* \file hs_cell.h
- * \brief Header file containing cell data for the whole HS subsytem.
+ * \brief Header file containing cell data for the whole HS subsystem.
**/
#ifndef TOR_HS_CELL_H
diff --git a/src/feature/hs/hs_circuit.c b/src/feature/hs/hs_circuit.c
index 447f664f81..eaf99cf8b2 100644
--- a/src/feature/hs/hs_circuit.c
+++ b/src/feature/hs/hs_circuit.c
@@ -16,6 +16,7 @@
#include "core/or/policies.h"
#include "core/or/relay.h"
#include "core/or/crypt_path.h"
+#include "core/or/extendinfo.h"
#include "feature/client/circpathbias.h"
#include "feature/hs/hs_cell.h"
#include "feature/hs/hs_circuit.h"
@@ -23,6 +24,7 @@
#include "feature/hs/hs_circuitmap.h"
#include "feature/hs/hs_client.h"
#include "feature/hs/hs_ident.h"
+#include "feature/hs/hs_metrics.h"
#include "feature/hs/hs_service.h"
#include "feature/nodelist/describe.h"
#include "feature/nodelist/nodelist.h"
@@ -428,6 +430,9 @@ launch_rendezvous_point_circuit,(const hs_service_t *service,
safe_str_client(service->onion_address));
goto end;
}
+ /* Update metrics with this new rendezvous circuit launched. */
+ hs_metrics_new_rdv(&service->keys.identity_pk);
+
log_info(LD_REND, "Rendezvous circuit launched to %s with cookie %s "
"for %s service %s",
safe_str_client(extend_info_describe(info)),
@@ -812,7 +817,7 @@ hs_circ_service_intro_has_opened(hs_service_t *service,
tor_assert(desc);
tor_assert(circ);
- /* Cound opened circuits that have sent ESTABLISH_INTRO cells or are already
+ /* Count opened circuits that have sent ESTABLISH_INTRO cells or are already
* established introduction circuits */
num_intro_circ = count_opened_desc_intro_point_circuits(service, desc);
num_needed_circ = service->config.num_intro_points;
@@ -1311,6 +1316,12 @@ hs_circ_cleanup_on_close(circuit_t *circ)
cleanup_on_close_client_circ(circ);
}
+ if (circuit_purpose_is_hs_service(circ->purpose)) {
+ if (circuit_is_hs_v3(circ)) {
+ hs_service_circuit_cleanup_on_close(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. */
diff --git a/src/feature/hs/hs_circuit.h b/src/feature/hs/hs_circuit.h
index 22e936e685..4dd9bf94c5 100644
--- a/src/feature/hs/hs_circuit.h
+++ b/src/feature/hs/hs_circuit.h
@@ -3,7 +3,7 @@
/**
* \file hs_circuit.h
- * \brief Header file containing circuit data for the whole HS subsytem.
+ * \brief Header file containing circuit data for the whole HS subsystem.
**/
#ifndef TOR_HS_CIRCUIT_H
diff --git a/src/feature/hs/hs_circuitmap.c b/src/feature/hs/hs_circuitmap.c
index 466a02de39..e46b008a5c 100644
--- a/src/feature/hs/hs_circuitmap.c
+++ b/src/feature/hs/hs_circuitmap.c
@@ -275,7 +275,7 @@ hs_circuitmap_get_or_circuit(hs_token_type_t type,
/** 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. */
+ * responsibility to free it. */
smartlist_t *
hs_circuitmap_get_all_intro_circ_relay_side(void)
{
diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c
index 0f6109195b..4b4e268542 100644
--- a/src/feature/hs/hs_client.c
+++ b/src/feature/hs/hs_client.c
@@ -16,6 +16,7 @@
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
#include "core/or/connection_edge.h"
+#include "core/or/extendinfo.h"
#include "core/or/reasons.h"
#include "feature/client/circpathbias.h"
#include "feature/dirclient/dirclient.h"
@@ -329,7 +330,7 @@ retry_all_socks_conn_waiting_for_desc(void)
* a descriptor but we do have it in the cache.
*
* This can happen is tor comes back from suspend where it previously
- * had the descriptor but the intro points were not usuable. Once it
+ * had the descriptor but the intro points were not usable. Once it
* came back to life, the intro point failure cache was cleaned up and
* thus the descriptor became usable again leaving us in this code path.
*
@@ -1561,9 +1562,9 @@ client_dir_fetch_unexpected(dir_connection_t *dir_conn, const char *reason,
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);
+ "server %s'. Retrying at another directory.",
+ status_code, escaped(reason),
+ connection_describe_peer(TO_CONN(dir_conn)));
/* Fire control port FAILED event. */
hs_control_desc_event_failed(dir_conn->hs_ident, dir_conn->identity_digest,
"UNEXPECTED");
@@ -1757,7 +1758,7 @@ remove_client_auth_creds_file(const char *filename)
goto end;
}
- log_warn(LD_REND, "Successfuly removed client auth file (%s).",
+ log_warn(LD_REND, "Successfully removed client auth file (%s).",
creds_file_path);
end:
diff --git a/src/feature/hs/hs_client.h b/src/feature/hs/hs_client.h
index 88dede8126..411fa659f2 100644
--- a/src/feature/hs/hs_client.h
+++ b/src/feature/hs/hs_client.h
@@ -3,7 +3,7 @@
/**
* \file hs_client.h
- * \brief Header file containing client data for the HS subsytem.
+ * \brief Header file containing client data for the HS subsystem.
**/
#ifndef TOR_HS_CLIENT_H
@@ -35,12 +35,12 @@ typedef enum {
/* Status code of client auth credential registration */
typedef enum {
- /* We successfuly registered these credentials */
+ /* We successfully 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
+ /* We successfully 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. */
@@ -51,7 +51,7 @@ typedef enum {
/* Status code of client auth credential removal */
typedef enum {
- /* We successfuly removed these credentials */
+ /* We successfully removed these credentials */
REMOVAL_SUCCESS,
/* No need to remove those credentials, because they were not there. */
REMOVAL_SUCCESS_NOT_FOUND,
diff --git a/src/feature/hs/hs_common.c b/src/feature/hs/hs_common.c
index 86d3fcab7d..fa27ac5223 100644
--- a/src/feature/hs/hs_common.c
+++ b/src/feature/hs/hs_common.c
@@ -16,6 +16,7 @@
#include "app/config/config.h"
#include "core/or/circuitbuild.h"
#include "core/or/policies.h"
+#include "core/or/extendinfo.h"
#include "feature/dirauth/shared_random_state.h"
#include "feature/hs/hs_cache.h"
#include "feature/hs/hs_circuitmap.h"
@@ -889,12 +890,14 @@ hs_set_conn_addr_port(const smartlist_t *ports, edge_connection_t *conn)
chosen_port = smartlist_choose(matching_ports);
smartlist_free(matching_ports);
if (chosen_port) {
- if (!(chosen_port->is_unix_addr)) {
- /* save the original destination before we overwrite it */
- if (conn->hs_ident) {
- conn->hs_ident->orig_virtual_port = TO_CONN(conn)->port;
- }
+ /* Remember, v2 doesn't use an hs_ident. */
+ if (conn->hs_ident) {
+ /* There is always a connection identifier at this point. Regardless of a
+ * Unix or TCP port, note the virtual port. */
+ conn->hs_ident->orig_virtual_port = chosen_port->virtual_port;
+ }
+ if (!(chosen_port->is_unix_addr)) {
/* Get a non-AF_UNIX connection ready for connection_exit_connect() */
tor_addr_copy(&TO_CONN(conn)->addr, &chosen_port->real_addr);
TO_CONN(conn)->port = chosen_port->real_port;
@@ -1749,7 +1752,7 @@ hs_get_extend_info_from_lspecs(const smartlist_t *lspecs,
switch (link_specifier_get_ls_type(ls)) {
case LS_IPV4:
/* Skip if we already seen a v4. If direct_conn is true, we skip this
- * block because fascist_firewall_choose_address_ls() will set ap. If
+ * block because reachable_addr_choose_from_ls() will set ap. If
* direct_conn is false, set ap to the first IPv4 address and port in
* the link specifiers.*/
if (have_v4 || direct_conn) continue;
@@ -1781,7 +1784,7 @@ hs_get_extend_info_from_lspecs(const smartlist_t *lspecs,
/* Choose a preferred address first, but fall back to an allowed address. */
if (direct_conn)
- fascist_firewall_choose_address_ls(lspecs, 0, &ap);
+ reachable_addr_choose_from_ls(lspecs, 0, &ap);
/* Legacy ID is mandatory, and we require an IP address. */
if (!tor_addr_port_is_valid_ap(&ap, 0)) {
@@ -1817,7 +1820,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 subsystem. This is called in tor_init() before any
* torrc options are loaded. Only for >= v3. */
void
hs_init(void)
diff --git a/src/feature/hs/hs_common.h b/src/feature/hs/hs_common.h
index 997b7298a6..4a9c7a9918 100644
--- a/src/feature/hs/hs_common.h
+++ b/src/feature/hs/hs_common.h
@@ -3,7 +3,7 @@
/**
* \file hs_common.h
- * \brief Header file containing common data for the whole HS subsytem.
+ * \brief Header file containing common data for the whole HS subsystem.
**/
#ifndef TOR_HS_COMMON_H
diff --git a/src/feature/hs/hs_config.c b/src/feature/hs/hs_config.c
index 0dad8dd6d8..7ffc7ecb96 100644
--- a/src/feature/hs/hs_config.c
+++ b/src/feature/hs/hs_config.c
@@ -16,7 +16,7 @@
* options and then put in a staging list. It will stay there until
* hs_service_load_all_keys() is called. That function is responsible to
* load/generate the keys for the service in the staging list and if
- * successful, transfert the service to the main global service list where
+ * successful, transferred the service to the main global service list where
* at that point it is ready to be used.
*
* Configuration functions are per-version and there is a main generic one for
@@ -362,7 +362,7 @@ config_validate_service(const hs_service_config_t *config)
return -1;
}
-/** Configuration funcion for a version 3 service. The given service
+/** Configuration function for a version 3 service. The given service
* object must be already allocated and passed through
* config_generic_service() prior to calling this function.
*
diff --git a/src/feature/hs/hs_config.h b/src/feature/hs/hs_config.h
index c60b4fbb5d..48c24b1a08 100644
--- a/src/feature/hs/hs_config.h
+++ b/src/feature/hs/hs_config.h
@@ -3,7 +3,7 @@
/**
* \file hs_config.h
- * \brief Header file containing configuration ABI/API for the HS subsytem.
+ * \brief Header file containing configuration ABI/API for the HS subsystem.
**/
#ifndef TOR_HS_CONFIG_H
diff --git a/src/feature/hs/hs_descriptor.c b/src/feature/hs/hs_descriptor.c
index 50a46fb40f..0656224e48 100644
--- a/src/feature/hs/hs_descriptor.c
+++ b/src/feature/hs/hs_descriptor.c
@@ -55,6 +55,7 @@
/* For unit tests.*/
#define HS_DESCRIPTOR_PRIVATE
+#include <stdbool.h>
#include "core/or/or.h"
#include "app/config/config.h"
#include "trunnel/ed25519_cert.h" /* Trunnel interface. */
@@ -185,7 +186,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 descriptor object, build the secret
* input needed for the KDF.
*
* secret_input = SECRET_DATA | subcredential | INT_8(revision_counter)
@@ -404,7 +405,7 @@ encode_enc_key(const hs_desc_intro_point_t *ip)
tor_assert(ip);
/* Base64 encode the encryption key for the "enc-key" field. */
- curve25519_public_to_base64(key_b64, &ip->enc_key);
+ curve25519_public_to_base64(key_b64, &ip->enc_key, true);
if (tor_cert_encode_ed22519(ip->enc_key_cert, &encoded_cert) < 0) {
goto done;
}
@@ -430,7 +431,7 @@ encode_onion_key(const hs_desc_intro_point_t *ip)
tor_assert(ip);
/* Base64 encode the encryption key for the "onion-key" field. */
- curve25519_public_to_base64(key_b64, &ip->onion_key);
+ curve25519_public_to_base64(key_b64, &ip->onion_key, true);
tor_asprintf(&encoded, "%s ntor %s", str_ip_onion_key, key_b64);
return encoded;
@@ -813,7 +814,7 @@ get_outer_encrypted_layer_plaintext(const hs_descriptor_t *desc,
tor_assert(!fast_mem_is_zero((char *) ephemeral_pubkey->public_key,
CURVE25519_PUBKEY_LEN));
- curve25519_public_to_base64(ephemeral_key_base64, ephemeral_pubkey);
+ curve25519_public_to_base64(ephemeral_key_base64, ephemeral_pubkey, true);
smartlist_add_asprintf(lines, "%s %s\n",
str_desc_auth_key, ephemeral_key_base64);
@@ -1406,7 +1407,7 @@ build_descriptor_cookie_keys(const hs_subcredential_t *subcredential,
}
/** Decrypt the descriptor cookie given the descriptor, the auth client,
- * and the client secret key. On sucess, return 0 and a newly allocated
+ * and the client secret key. On success, 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
* NULL. */
@@ -1432,7 +1433,7 @@ decrypt_descriptor_cookie(const hs_descriptor_t *desc,
tor_assert(!fast_mem_is_zero((char *) desc->subcredential.subcred,
DIGEST256_LEN));
- /* Catch potential code-flow cases of an unitialized private key sneaking
+ /* Catch potential code-flow cases of an uninitialized private key sneaking
* into this function. */
if (BUG(fast_mem_is_zero((char *)client_auth_sk, sizeof(*client_auth_sk)))) {
goto done;
@@ -1447,7 +1448,7 @@ decrypt_descriptor_cookie(const hs_descriptor_t *desc,
tor_assert(keystream_length > 0);
/* If the client id of auth client is not the same as the calculcated
- * client id, it means that this auth client is invaild according to the
+ * client id, it means that this auth client is invalid according to the
* client secret key client_auth_sk. */
if (tor_memneq(client->client_id, keystream, HS_DESC_CLIENT_ID_LEN)) {
goto done;
@@ -1480,7 +1481,7 @@ decrypt_descriptor_cookie(const hs_descriptor_t *desc,
* the descriptor object <b>desc</b> and <b>descriptor_cookie</b>
* to generate the right decryption keys; set <b>decrypted_out</b> to
* the plaintext. If <b>is_superencrypted_layer</b> is set, this is
- * the outter encrypted layer of the descriptor.
+ * the outer encrypted layer of the descriptor.
*
* On any error case, including an empty output, return 0 and set
* *<b>decrypted_out</b> to NULL.
@@ -2002,7 +2003,7 @@ desc_sig_is_valid(const char *b64_sig,
/* Signature length check. */
if (strlen(b64_sig) != ED25519_SIG_BASE64_LEN) {
log_warn(LD_REND, "Service descriptor has an invalid signature length."
- "Exptected %d but got %lu",
+ "Expected %d but got %lu",
ED25519_SIG_BASE64_LEN, (unsigned long) strlen(b64_sig));
goto err;
}
diff --git a/src/feature/hs/hs_ident.c b/src/feature/hs/hs_ident.c
index 1d93ff9610..53360f6e9d 100644
--- a/src/feature/hs/hs_ident.c
+++ b/src/feature/hs/hs_ident.c
@@ -4,7 +4,7 @@
/**
* \file hs_ident.c
* \brief Contains circuit and connection identifier code for the whole HS
- * subsytem.
+ * subsystem.
**/
#include "lib/crypt_ops/crypto_util.h"
diff --git a/src/feature/hs/hs_ident.h b/src/feature/hs/hs_ident.h
index f4b9b2432d..0a71602852 100644
--- a/src/feature/hs/hs_ident.h
+++ b/src/feature/hs/hs_ident.h
@@ -4,7 +4,7 @@
/**
* \file hs_ident.h
* \brief Header file containing circuit and connection identifier data for
- * the whole HS subsytem.
+ * the whole HS subsystem.
*
* \details
* This interface is used to uniquely identify a hidden service on a circuit
diff --git a/src/feature/hs/hs_metrics.c b/src/feature/hs/hs_metrics.c
new file mode 100644
index 0000000000..e6d3084f26
--- /dev/null
+++ b/src/feature/hs/hs_metrics.c
@@ -0,0 +1,171 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file hs_metrics.c
+ * @brief Onion service metrics exposed through the MetricsPort
+ **/
+
+#define HS_METRICS_ENTRY_PRIVATE
+
+#include "orconfig.h"
+
+#include "lib/malloc/malloc.h"
+#include "lib/container/smartlist.h"
+#include "lib/metrics/metrics_store.h"
+
+#include "feature/hs/hs_metrics.h"
+#include "feature/hs/hs_metrics_entry.h"
+#include "feature/hs/hs_service.h"
+
+/** Return a static buffer pointer that contains the port as a string.
+ *
+ * Subsequent call to this function invalidates the previous buffer. */
+static const char *
+port_to_str(const uint16_t port)
+{
+ static char buf[8];
+ tor_snprintf(buf, sizeof(buf), "%u", port);
+ return buf;
+}
+
+/** Return a static buffer pointer that contains a formatted label on the form
+ * of key=value.
+ *
+ * Subsequent call to this function invalidates the previous buffer. */
+static const char *
+format_label(const char *key, const char *value)
+{
+ static char buf[128];
+ tor_snprintf(buf, sizeof(buf), "%s=%s", key, value);
+ return buf;
+}
+
+/** Initialize a metrics store for the given service.
+ *
+ * Essentially, this goes over the base_metrics array and adds them all to the
+ * store set with their label(s) if any. */
+static void
+init_store(hs_service_t *service)
+{
+ metrics_store_t *store;
+
+ tor_assert(service);
+
+ store = service->metrics.store;
+
+ for (size_t i = 0; i < base_metrics_size; ++i) {
+ metrics_store_entry_t *entry =
+ metrics_store_add(store, base_metrics[i].type, base_metrics[i].name,
+ base_metrics[i].help);
+
+ /* Add labels to the entry. */
+ metrics_store_entry_add_label(entry,
+ format_label("onion", service->onion_address));
+ if (base_metrics[i].port_as_label && service->config.ports) {
+ SMARTLIST_FOREACH_BEGIN(service->config.ports,
+ const rend_service_port_config_t *, p) {
+ metrics_store_entry_add_label(entry,
+ format_label("port", port_to_str(p->virtual_port)));
+ } SMARTLIST_FOREACH_END(p);
+ }
+ }
+}
+
+/** Update the metrics key entry in the store in the given service. The port,
+ * if non 0, is used to find the correct metrics entry. The value n is the
+ * value used to update the entry. */
+void
+hs_metrics_update_by_service(const hs_metrics_key_t key,
+ hs_service_t *service, const uint16_t port,
+ int64_t n)
+{
+ tor_assert(service);
+
+ /* Get the metrics entry in the store. */
+ smartlist_t *entries = metrics_store_get_all(service->metrics.store,
+ base_metrics[key].name);
+ if (BUG(!entries)) {
+ return;
+ }
+
+ /* We need to find the right metrics entry by finding the port label if any.
+ *
+ * XXX: This is not the most optimal due to the string format. Maybe at some
+ * point turn this into a kvline and a map in a metric entry? */
+ SMARTLIST_FOREACH_BEGIN(entries, metrics_store_entry_t *, entry) {
+ if (port == 0 ||
+ metrics_store_entry_has_label(entry,
+ format_label("port", port_to_str(port)))) {
+ metrics_store_entry_update(entry, n);
+ break;
+ }
+ } SMARTLIST_FOREACH_END(entry);
+}
+
+/** Update the metrics key entry in the store of a service identified by the
+ * given identity public key. The port, if non 0, is used to find the correct
+ * metrics entry. The value n is the value used to update the entry.
+ *
+ * This is used by callsite that have access to the key but not the service
+ * object so an extra lookup is done to find the service. */
+void
+hs_metrics_update_by_ident(const hs_metrics_key_t key,
+ const ed25519_public_key_t *ident_pk,
+ const uint16_t port, int64_t n)
+{
+ hs_service_t *service;
+
+ tor_assert(ident_pk);
+
+ service = hs_service_find(ident_pk);
+ if (!service) {
+ /* This is possible because an onion service client can end up here due to
+ * having an identity key onto a connection _to_ an onion service. We
+ * can't differentiate that from an actual onion service initiated by a
+ * service and thus the only way to know is to lookup the service. */
+ return;
+ }
+ hs_metrics_update_by_service(key, service, port, n);
+}
+
+/** Return a list of all the onion service metrics stores. This is the
+ * function attached to the .get_metrics() member of the subsys_t. */
+const smartlist_t *
+hs_metrics_get_stores(void)
+{
+ /* We can't have the caller to free the returned list so keep it static,
+ * simply update it. */
+ static smartlist_t *stores_list = NULL;
+
+ smartlist_free(stores_list);
+ stores_list = hs_service_get_metrics_stores();
+ return stores_list;
+}
+
+/** Initialize the metrics store in the given service. */
+void
+hs_metrics_service_init(hs_service_t *service)
+{
+ tor_assert(service);
+
+ /* This function is called when we register a service and so it could either
+ * be a new service or a service that was just reloaded through a HUP signal
+ * for instance. Thus, it is possible that the service has already an
+ * initialized store. If so, just return. */
+ if (service->metrics.store) {
+ return;
+ }
+
+ service->metrics.store = metrics_store_new();
+ init_store(service);
+}
+
+/** Free the metrics store in the given service. */
+void
+hs_metrics_service_free(hs_service_t *service)
+{
+ tor_assert(service);
+
+ metrics_store_free(service->metrics.store);
+}
diff --git a/src/feature/hs/hs_metrics.h b/src/feature/hs/hs_metrics.h
new file mode 100644
index 0000000000..506831b3fd
--- /dev/null
+++ b/src/feature/hs/hs_metrics.h
@@ -0,0 +1,70 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file hs_metrics.h
+ * @brief Header for feature/hs/hs_metrics.c
+ **/
+
+#ifndef TOR_FEATURE_HS_HS_METRICS_H
+#define TOR_FEATURE_HS_HS_METRICS_H
+
+#include "lib/container/smartlist.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+
+#define HS_METRICS_ENTRY_PRIVATE
+#include "feature/hs/hs_metrics_entry.h"
+#include "feature/hs/hs_service.h"
+
+/* Init and Free. */
+void hs_metrics_service_init(hs_service_t *service);
+void hs_metrics_service_free(hs_service_t *service);
+
+/* Accessors. */
+const smartlist_t *hs_metrics_get_stores(void);
+
+/* Metrics Update. */
+void hs_metrics_update_by_ident(const hs_metrics_key_t key,
+ const ed25519_public_key_t *ident_pk,
+ const uint16_t port, int64_t n);
+void hs_metrics_update_by_service(const hs_metrics_key_t key,
+ hs_service_t *service, const uint16_t port,
+ int64_t n);
+
+/** New introducion request received. */
+#define hs_metrics_new_introduction(s) \
+ hs_metrics_update_by_service(HS_METRICS_NUM_INTRODUCTIONS, (s), 0, 1)
+
+/** Number of bytes written to the application from the service. */
+#define hs_metrics_app_write_bytes(i, port, n) \
+ hs_metrics_update_by_ident(HS_METRICS_APP_WRITE_BYTES, (i), (port), (n))
+
+/** Number of bytes read from the application to the service. */
+#define hs_metrics_app_read_bytes(i, port, n) \
+ hs_metrics_update_by_ident(HS_METRICS_APP_READ_BYTES, (i), (port), (n))
+
+/** Newly established rendezvous. This is called as soon as the circuit purpose
+ * is REND_JOINED which is when the RENDEZVOUS2 cell is sent. */
+#define hs_metrics_new_established_rdv(s) \
+ hs_metrics_update_by_service(HS_METRICS_NUM_ESTABLISHED_RDV, (s), 0, 1)
+
+/** Established rendezvous closed. This is called when the circuit in
+ * REND_JOINED state is marked for close. */
+#define hs_metrics_close_established_rdv(i) \
+ hs_metrics_update_by_ident(HS_METRICS_NUM_ESTABLISHED_RDV, (i), 0, -1)
+
+/** New rendezvous circuit being launched. */
+#define hs_metrics_new_rdv(i) \
+ hs_metrics_update_by_ident(HS_METRICS_NUM_RDV, (i), 0, 1)
+
+/** New introduction circuit has been established. This is called when the
+ * INTRO_ESTABLISHED has been received by the service. */
+#define hs_metrics_new_established_intro(s) \
+ hs_metrics_update_by_service(HS_METRICS_NUM_ESTABLISHED_INTRO, (s), 0, 1)
+
+/** Established introduction circuit closes. This is called when
+ * INTRO_ESTABLISHED circuit is marked for close. */
+#define hs_metrics_close_established_intro(i) \
+ hs_metrics_update_by_ident(HS_METRICS_NUM_ESTABLISHED_INTRO, (i), 0, 1)
+
+#endif /* !defined(TOR_FEATURE_HS_HS_METRICS_H) */
diff --git a/src/feature/hs/hs_metrics_entry.c b/src/feature/hs/hs_metrics_entry.c
new file mode 100644
index 0000000000..7eb78db5ac
--- /dev/null
+++ b/src/feature/hs/hs_metrics_entry.c
@@ -0,0 +1,65 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file hs_metrics_entry.c
+ * @brief Defines the metrics entry that are collected by an onion service.
+ **/
+
+#define HS_METRICS_ENTRY_PRIVATE
+
+#include "orconfig.h"
+
+#include "lib/cc/compat_compiler.h"
+
+#include "feature/hs/hs_metrics_entry.h"
+
+/** The base metrics that is a static array of metrics that are added to every
+ * single new stores.
+ *
+ * The key member MUST be also the index of the entry in the array. */
+const hs_metrics_entry_t base_metrics[] =
+{
+ {
+ .key = HS_METRICS_NUM_INTRODUCTIONS,
+ .type = METRICS_TYPE_COUNTER,
+ .name = METRICS_NAME(hs_intro_num_total),
+ .help = "Total number of introduction received",
+ .port_as_label = false,
+ },
+ {
+ .key = HS_METRICS_APP_WRITE_BYTES,
+ .type = METRICS_TYPE_COUNTER,
+ .name = METRICS_NAME(hs_app_write_bytes_total),
+ .help = "Total number of bytes written to the application",
+ .port_as_label = true,
+ },
+ {
+ .key = HS_METRICS_APP_READ_BYTES,
+ .type = METRICS_TYPE_COUNTER,
+ .name = METRICS_NAME(hs_app_read_bytes_total),
+ .help = "Total number of bytes read from the application",
+ .port_as_label = true,
+ },
+ {
+ .key = HS_METRICS_NUM_ESTABLISHED_RDV,
+ .type = METRICS_TYPE_GAUGE,
+ .name = METRICS_NAME(hs_rdv_established_count),
+ .help = "Total number of established rendezvous circuit",
+ },
+ {
+ .key = HS_METRICS_NUM_RDV,
+ .type = METRICS_TYPE_COUNTER,
+ .name = METRICS_NAME(hs_rdv_num_total),
+ .help = "Total number of rendezvous circuit created",
+ },
+ {
+ .key = HS_METRICS_NUM_ESTABLISHED_INTRO,
+ .type = METRICS_TYPE_GAUGE,
+ .name = METRICS_NAME(hs_intro_established_count),
+ .help = "Total number of established introduction circuit",
+ },
+};
+
+/** Size of base_metrics array that is number of entries. */
+const size_t base_metrics_size = ARRAY_LENGTH(base_metrics);
diff --git a/src/feature/hs/hs_metrics_entry.h b/src/feature/hs/hs_metrics_entry.h
new file mode 100644
index 0000000000..f68c1ab8e9
--- /dev/null
+++ b/src/feature/hs/hs_metrics_entry.h
@@ -0,0 +1,51 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file hs_metrics_entry.h
+ * @brief Header for feature/hs/hs_metrics_entry.c
+ **/
+
+#ifndef TOR_FEATURE_HS_METRICS_ENTRY_H
+#define TOR_FEATURE_HS_METRICS_ENTRY_H
+
+#ifdef HS_METRICS_ENTRY_PRIVATE
+
+#include "lib/metrics/metrics_common.h"
+
+/** Metrics key which are used as an index in the main base metrics array. */
+typedef enum {
+ /** Number of introduction requests. */
+ HS_METRICS_NUM_INTRODUCTIONS = 0,
+ /** Number of bytes written from onion service to application. */
+ HS_METRICS_APP_WRITE_BYTES = 1,
+ /** Number of bytes read from application to onion service. */
+ HS_METRICS_APP_READ_BYTES = 2,
+ /** Number of established rendezsvous. */
+ HS_METRICS_NUM_ESTABLISHED_RDV = 3,
+ /** Number of rendezsvous circuits created. */
+ HS_METRICS_NUM_RDV = 4,
+ /** Number of established introducton points. */
+ HS_METRICS_NUM_ESTABLISHED_INTRO = 5,
+} hs_metrics_key_t;
+
+/** The metadata of an HS metrics. */
+typedef struct hs_metrics_entry_t {
+ /* Metric key used as a static array index. */
+ hs_metrics_key_t key;
+ /* Metric type. */
+ metrics_type_t type;
+ /* Metrics output name. */
+ const char *name;
+ /* Metrics output help comment. */
+ const char *help;
+ /* True iff a port label should be added to the metrics entry. */
+ bool port_as_label;
+} hs_metrics_entry_t;
+
+extern const hs_metrics_entry_t base_metrics[];
+extern const size_t base_metrics_size;
+
+#endif /* HS_METRICS_ENTRY_PRIVATE */
+
+#endif /* !defined(TOR_FEATURE_HS_METRICS_ENTRY_H) */
diff --git a/src/feature/hs/hs_ob.c b/src/feature/hs/hs_ob.c
index 9499c28d20..1b8ab121a0 100644
--- a/src/feature/hs/hs_ob.c
+++ b/src/feature/hs/hs_ob.c
@@ -120,7 +120,7 @@ get_onion_public_key(const char *value, ed25519_public_key_t *pkey_out)
}
/* We don't want the .onion so we add 2 because size - 1 is copied with
- * strlcpy() in order to accomodate the NUL byte and sizeof() counts the NUL
+ * strlcpy() in order to accommodate the NUL byte and sizeof() counts the NUL
* byte so we need to remove them from the equation. */
strlcpy(address, value, strlen(value) - sizeof(".onion") + 2);
@@ -264,10 +264,10 @@ hs_ob_parse_config_file(hs_service_config_t *config)
/** Compute all possible subcredentials for every onion master key in the given
* service config object. subcredentials_out is allocated and set as an
- * continous array containing all possible values.
+ * continuous array containing all possible values.
*
* On success, return the number of subcredential put in the array which will
- * correspond to an arry of size: n * DIGEST256_LEN where DIGEST256_LEN is the
+ * correspond to an array of size: n * DIGEST256_LEN where DIGEST256_LEN is the
* length of a single subcredential.
*
* If the given configuration object has no OB master keys configured, 0 is
@@ -300,7 +300,7 @@ compute_subcredentials(const hs_service_t *service,
/* Time to build all the subcredentials for each time period: two for each
* instance descriptor plus three for the onionbalance frontend service: the
* previous one (-1), the current one (0) and the next one (1) for each
- * configured key in order to accomodate client and service consensus skew.
+ * configured key in order to accommodate client and service consensus skew.
*
* If the client consensus after_time is at 23:00 but the service one is at
* 01:00, the client will be using the previous time period where the
@@ -356,9 +356,10 @@ compute_subcredentials(const hs_service_t *service,
* If we are not an Onionbalance instance or we are not ready to do so, this
* is a NOP.
*
- * This function is called everytime we build a new descriptor. That's because
- * we want our Onionbalance keys to always use up-to-date subcredentials both
- * for the instance (ourselves) and for the onionbalance frontend.
+ * This function is called every time we build a new descriptor. That's
+ * because we want our Onionbalance keys to always use up-to-date
+ * subcredentials both for the instance (ourselves) and for the onionbalance
+ * frontend.
*/
void
hs_ob_refresh_keys(hs_service_t *service)
diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c
index c29f39c6b4..908ac02044 100644
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -16,6 +16,7 @@
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
+#include "core/or/extendinfo.h"
#include "core/or/relay.h"
#include "feature/client/circpathbias.h"
#include "feature/dirclient/dirclient.h"
@@ -40,6 +41,7 @@
#include "feature/hs/hs_descriptor.h"
#include "feature/hs/hs_ident.h"
#include "feature/hs/hs_intropoint.h"
+#include "feature/hs/hs_metrics.h"
#include "feature/hs/hs_service.h"
#include "feature/hs/hs_stats.h"
#include "feature/hs/hs_ob.h"
@@ -195,6 +197,10 @@ register_service(hs_service_ht *map, hs_service_t *service)
if (map == hs_service_map) {
hs_service_map_has_changed();
}
+ /* Setup metrics. This is done here because in order to initialize metrics,
+ * we require tor to have fully initialized a service so the ports of the
+ * service can be looked at for instance. */
+ hs_metrics_service_init(service);
return 0;
}
@@ -543,7 +549,7 @@ service_intro_point_remove(const hs_service_t *service,
/* Trying all descriptors. */
FOR_EACH_DESCRIPTOR_BEGIN(service, desc) {
/* We'll try to remove the descriptor on both descriptors which is not
- * very expensive to do instead of doing loopup + remove. */
+ * very expensive to do instead of doing lookup + remove. */
digest256map_remove(desc->intro_points.map,
ip->auth_key_kp.pubkey.pubkey);
} FOR_EACH_DESCRIPTOR_END;
@@ -564,7 +570,7 @@ service_intro_point_find(const hs_service_t *service,
*
* Even if we use the same node as intro point in both descriptors, the node
* will have a different intro auth key for each descriptor since we generate
- * a new one everytime we pick an intro point.
+ * a new one every time we pick an intro point.
*
* After #22893 gets implemented, intro points will be moved to be
* per-service instead of per-descriptor so this function will need to
@@ -781,7 +787,7 @@ close_service_rp_circuits(hs_service_t *service)
ed25519_pubkey_eq(&ocirc->hs_ident->identity_pk,
&service->keys.identity_pk)) {
/* Reason is FINISHED because service has been removed and thus the
- * circuit is considered old/uneeded. When freed, it is removed from the
+ * circuit is considered old/unneeded. When freed, it is removed from the
* hs circuitmap. */
circuit_mark_for_close(TO_CIRCUIT(ocirc), END_CIRC_REASON_FINISHED);
}
@@ -799,7 +805,7 @@ close_intro_circuits(hs_service_intropoints_t *intro_points)
origin_circuit_t *ocirc = hs_circ_service_get_intro_circ(ip);
if (ocirc) {
/* Reason is FINISHED because service has been removed and thus the
- * circuit is considered old/uneeded. When freed, the circuit is removed
+ * circuit is considered old/unneeded. When freed, the circuit is removed
* from the HS circuitmap. */
circuit_mark_for_close(TO_CIRCUIT(ocirc), END_CIRC_REASON_FINISHED);
}
@@ -990,7 +996,7 @@ write_address_to_file(const hs_service_t *service, const char *fname_)
tor_asprintf(&addr_buf, "%s.%s\n", service->onion_address, address_tld);
/* Notice here that we use the given "fname_". */
fname = hs_path_from_filename(service->config.directory_path, fname_);
- if (write_str_to_file(fname, addr_buf, 0) < 0) {
+ if (write_str_to_file_if_not_equal(fname, addr_buf)) {
log_warn(LD_REND, "Could not write onion address to hostname file %s",
escaped(fname));
goto end;
@@ -1083,7 +1089,7 @@ load_service_keys(hs_service_t *service)
goto end;
}
- /* Succes. */
+ /* Success. */
ret = 0;
end:
tor_free(fname);
@@ -1587,7 +1593,7 @@ setup_desc_intro_point(const ed25519_keypair_t *signing_kp,
memcpy(&desc_ip->onion_key, &ip->onion_key, sizeof(desc_ip->onion_key));
/* Key and certificate material. */
- desc_ip->auth_key_cert = tor_cert_create(signing_kp,
+ desc_ip->auth_key_cert = tor_cert_create_ed25519(signing_kp,
CERT_TYPE_AUTH_HS_IP_KEY,
&ip->auth_key_kp.pubkey,
nearest_hour,
@@ -1638,7 +1644,7 @@ setup_desc_intro_point(const ed25519_keypair_t *signing_kp,
ed25519_public_key_from_curve25519_public_key(&ed25519_pubkey,
&ip->enc_key_kp.pubkey,
0);
- desc_ip->enc_key_cert = tor_cert_create(signing_kp,
+ desc_ip->enc_key_cert = tor_cert_create_ed25519(signing_kp,
CERT_TYPE_CROSS_HS_IP_KEYS,
&ed25519_pubkey, nearest_hour,
HS_DESC_CERT_LIFETIME,
@@ -1712,12 +1718,13 @@ build_desc_signing_key_cert(hs_service_descriptor_t *desc, time_t now)
/* Fresh certificate for the signing key. */
plaintext->signing_key_cert =
- tor_cert_create(&desc->blinded_kp, CERT_TYPE_SIGNING_HS_DESC,
+ tor_cert_create_ed25519(&desc->blinded_kp, CERT_TYPE_SIGNING_HS_DESC,
&desc->signing_kp.pubkey, now, HS_DESC_CERT_LIFETIME,
CERT_FLAG_INCLUDE_SIGNING_KEY);
/* If the cert creation fails, the descriptor encoding will fail and thus
* ultimately won't be uploaded. We'll get a stack trace to help us learn
- * where the call came from and the tor_cert_create() will log the error. */
+ * where the call came from and the tor_cert_create_ed25519() will log the
+ * error. */
tor_assert_nonfatal(plaintext->signing_key_cert);
}
@@ -2190,7 +2197,7 @@ pick_needed_intro_points(hs_service_t *service,
}
/* Build an exclude list of nodes of our intro point(s). The expiring intro
- * points are OK to pick again because this is afterall a concept of round
+ * points are OK to pick again because this is after all a concept of round
* robin so they are considered valid nodes to pick again. */
DIGEST256MAP_FOREACH(desc->intro_points.map, key,
hs_service_intro_point_t *, ip) {
@@ -2374,7 +2381,7 @@ should_remove_intro_point(hs_service_intro_point_t *ip, time_t now)
tor_assert(ip);
- /* Any one of the following needs to be True to furfill the criteria to
+ /* Any one of the following needs to be True to fulfill the criteria to
* remove an intro point. */
bool has_no_retries = (ip->circuit_retries >
MAX_INTRO_POINT_CIRCUIT_RETRIES);
@@ -2875,6 +2882,9 @@ upload_descriptor_to_hsdir(const hs_service_t *service,
hsdir->hsdir_index.store_first;
char *blinded_pubkey_log_str =
tor_strdup(hex_str((char*)&desc->blinded_kp.pubkey.pubkey, 32));
+ /* This log message is used by Chutney as part of its bootstrap
+ * detection mechanism. Please don't change without first checking
+ * Chutney. */
log_info(LD_REND, "Service %s %s descriptor of revision %" PRIu64
" initiated upload request to %s with index %s (%s)",
safe_str_client(service->onion_address),
@@ -2991,7 +3001,7 @@ upload_descriptor_to_all(const hs_service_t *service,
/* Get our list of responsible HSDir. */
responsible_dirs = smartlist_new();
/* The parameter 0 means that we aren't a client so tell the function to use
- * the spread store consensus paremeter. */
+ * the spread store consensus parameter. */
hs_get_responsible_hsdirs(&desc->blinded_kp.pubkey, desc->time_period_num,
service->desc_next == desc, 0, responsible_dirs);
@@ -3226,7 +3236,7 @@ refresh_service_descriptor(const hs_service_t *service,
hs_service_descriptor_t *desc, time_t now)
{
/* There are few fields that we consider "mutable" in the descriptor meaning
- * we need to update them regurlarly over the lifetime fo the descriptor.
+ * we need to update them regularly over the lifetime for the descriptor.
* The rest are set once and should not be modified.
*
* - Signing key certificate.
@@ -3386,6 +3396,15 @@ service_rendezvous_circ_has_opened(origin_circuit_t *circ)
/* If the cell can't be sent, the circuit will be closed within this
* function. */
hs_circ_service_rp_has_opened(service, circ);
+
+ /* Update metrics that we have an established rendezvous circuit. It is not
+ * entirely true until the client receives the RENDEZVOUS2 cell and starts
+ * sending but if that circuit collapes, we'll decrement the counter thus it
+ * will even out the metric. */
+ if (TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_REND_JOINED) {
+ hs_metrics_new_established_rdv(service);
+ }
+
goto done;
err:
@@ -3437,6 +3456,9 @@ service_handle_intro_established(origin_circuit_t *circ,
goto err;
}
+ /* Update metrics. */
+ hs_metrics_new_established_intro(service);
+
log_info(LD_REND, "Successfully received an INTRO_ESTABLISHED cell "
"on circuit %u for service %s",
TO_CIRCUIT(circ)->n_circ_id,
@@ -3489,6 +3511,8 @@ service_handle_introduce2(origin_circuit_t *circ, const uint8_t *payload,
payload, payload_len) < 0) {
goto err;
}
+ /* Update metrics that a new introduction was successful. */
+ hs_metrics_new_introduction(service);
return 0;
err:
@@ -3510,7 +3534,7 @@ service_add_fnames_to_list(const hs_service_t *service, smartlist_t *list)
s_dir = service->config.directory_path;
/* The hostname file. */
smartlist_add(list, hs_path_from_filename(s_dir, fname_hostname));
- /* The key files splitted in two. */
+ /* The key files split in two. */
tor_snprintf(fname, sizeof(fname), "%s_secret_key", fname_keyfile_prefix);
smartlist_add(list, hs_path_from_filename(s_dir, fname));
tor_snprintf(fname, sizeof(fname), "%s_public_key", fname_keyfile_prefix);
@@ -3572,7 +3596,33 @@ 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
+/** Called when a circuit was just cleaned up. This is done right before the
+ * circuit is marked for close. */
+void
+hs_service_circuit_cleanup_on_close(const circuit_t *circ)
+{
+ tor_assert(circ);
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
+
+ switch (circ->purpose) {
+ case CIRCUIT_PURPOSE_S_INTRO:
+ /* About to close an established introduction circuit. Update the metrics
+ * to reflect how many we have at the moment. */
+ hs_metrics_close_established_intro(
+ &CONST_TO_ORIGIN_CIRCUIT(circ)->hs_ident->identity_pk);
+ break;
+ case CIRCUIT_PURPOSE_S_REND_JOINED:
+ /* About to close an established rendezvous circuit. Update the metrics to
+ * reflect how many we have at the moment. */
+ hs_metrics_close_established_rdv(
+ &CONST_TO_ORIGIN_CIRCUIT(circ)->hs_ident->identity_pk);
+ break;
+ default:
+ break;
+ }
+}
+
+/** This is called every time the service map (v2 or v3) changes that is if an
* element is added or removed. */
void
hs_service_map_has_changed(void)
@@ -3862,7 +3912,7 @@ hs_service_set_conn_addr_port(const origin_circuit_t *circ,
goto err_no_close;
}
- /* Find a virtual port of that service mathcing the one in the connection if
+ /* Find a virtual port of that service matching the one in the connection if
* successful, set the address in the connection. */
if (hs_set_conn_addr_port(service->config.ports, conn) < 0) {
log_info(LD_REND, "No virtual port mapping exists for port %d for "
@@ -3903,7 +3953,7 @@ hs_service_exports_circuit_id(const ed25519_public_key_t *pk)
/** 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. */
+ * used by the sandbox subsystem to allowlist those. */
void
hs_service_lists_fnames_for_sandbox(smartlist_t *file_list,
smartlist_t *dir_list)
@@ -4167,7 +4217,35 @@ 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
+/** Return a newly allocated list of all the service's metrics store. */
+smartlist_t *
+hs_service_get_metrics_stores(void)
+{
+ smartlist_t *list = smartlist_new();
+
+ if (hs_service_map) {
+ FOR_EACH_SERVICE_BEGIN(service) {
+ smartlist_add(list, service->metrics.store);
+ } FOR_EACH_SERVICE_END;
+ }
+
+ return list;
+}
+
+/** Lookup the global service map for the given identitiy public key and
+ * return the service object if found, NULL if not. */
+hs_service_t *
+hs_service_find(const ed25519_public_key_t *identity_pk)
+{
+ tor_assert(identity_pk);
+
+ if (!hs_service_map) {
+ return NULL;
+ }
+ return find_service(hs_service_map, identity_pk);
+}
+
+/** Allocate and initialize 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 *
@@ -4213,6 +4291,9 @@ hs_service_free_(hs_service_t *service)
tor_free(service->state.ob_subcreds);
}
+ /* Free metrics object. */
+ hs_metrics_service_free(service);
+
/* Wipe service keys. */
memwipe(&service->keys.identity_sk, 0, sizeof(service->keys.identity_sk));
diff --git a/src/feature/hs/hs_service.h b/src/feature/hs/hs_service.h
index b5bff5bee5..ec0e83f2c2 100644
--- a/src/feature/hs/hs_service.h
+++ b/src/feature/hs/hs_service.h
@@ -3,7 +3,7 @@
/**
* \file hs_service.h
- * \brief Header file containing service data for the HS subsytem.
+ * \brief Header file containing service data for the HS subsystem.
**/
#ifndef TOR_HS_SERVICE_H
@@ -11,12 +11,13 @@
#include "lib/crypt_ops/crypto_curve25519.h"
#include "lib/crypt_ops/crypto_ed25519.h"
-#include "feature/hs_common/replaycache.h"
+#include "lib/metrics/metrics_store.h"
#include "feature/hs/hs_common.h"
#include "feature/hs/hs_descriptor.h"
#include "feature/hs/hs_ident.h"
#include "feature/hs/hs_intropoint.h"
+#include "feature/hs_common/replaycache.h"
/* Trunnel */
#include "trunnel/hs/cell_establish_intro.h"
@@ -34,6 +35,12 @@
/** Maximum interval for uploading next descriptor (in seconds). */
#define HS_SERVICE_NEXT_UPLOAD_TIME_MAX (120 * 60)
+/** Collected metrics for a specific service. */
+typedef struct hs_service_metrics_t {
+ /** Store containing the metrics values. */
+ metrics_store_t *store;
+} hs_service_metrics_t;
+
/** Service side introduction point. */
typedef struct hs_service_intro_point_t {
/** Top level intropoint "shared" data between client/service. */
@@ -114,9 +121,9 @@ typedef struct hs_service_intropoints_t {
*
* Mutable elements are initialized when we build the descriptor but they are
* also altered during the lifetime of the descriptor. They could be
- * _refreshed_ everytime we upload the descriptor (which happens multiple times
- * over the lifetime of the descriptor), or through periodic events. We do this
- * for elements like the descriptor revision counter and various
+ * _refreshed_ every time we upload the descriptor (which happens multiple
+ * times over the lifetime of the descriptor), or through periodic events. We
+ * do this for elements like the descriptor revision counter and various
* certificates. See refresh_service_descriptor() and
* update_service_descriptor_intro_points().
*/
@@ -292,7 +299,7 @@ typedef struct hs_service_state_t {
/** 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
- * purposes so we don't have to build it everytime. */
+ * purposes so we don't have to build it every time. */
char onion_address[HS_SERVICE_ADDR_LEN_BASE32 + 1];
/** Hashtable node: use to look up the service by its master public identity
@@ -312,6 +319,9 @@ typedef struct hs_service_t {
hs_service_descriptor_t *desc_current;
/** Next descriptor. */
hs_service_descriptor_t *desc_next;
+
+ /** Metrics. */
+ hs_service_metrics_t metrics;
} hs_service_t;
/** For the service global hash map, we define a specific type for it which
@@ -335,6 +345,7 @@ void hs_service_free_(hs_service_t *service);
**/
#define hs_service_free(s) FREE_AND_NULL(hs_service_t, hs_service_free_, (s))
+hs_service_t *hs_service_find(const ed25519_public_key_t *ident_pk);
MOCK_DECL(unsigned int, hs_service_get_num_services,(void));
void hs_service_stage_services(const smartlist_t *service_list);
int hs_service_load_all_keys(void);
@@ -343,6 +354,7 @@ void hs_service_lists_fnames_for_sandbox(smartlist_t *file_list,
smartlist_t *dir_list);
int hs_service_set_conn_addr_port(const origin_circuit_t *circ,
edge_connection_t *conn);
+smartlist_t *hs_service_get_metrics_stores(void);
void hs_service_map_has_changed(void);
void hs_service_dir_info_changed(void);
@@ -374,6 +386,7 @@ hs_circuit_id_protocol_t
hs_service_exports_circuit_id(const ed25519_public_key_t *pk);
void hs_service_dump_stats(int severity);
+void hs_service_circuit_cleanup_on_close(const circuit_t *circ);
#ifdef HS_SERVICE_PRIVATE
diff --git a/src/feature/hs/hs_sys.c b/src/feature/hs/hs_sys.c
new file mode 100644
index 0000000000..6524dc3e4e
--- /dev/null
+++ b/src/feature/hs/hs_sys.c
@@ -0,0 +1,36 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file hs_sys.c
+ * @brief Setup and tear down the HS subsystem.
+ **/
+
+#include "lib/subsys/subsys.h"
+
+#include "feature/hs/hs_metrics.h"
+#include "feature/hs/hs_sys.h"
+
+static int
+subsys_hs_initialize(void)
+{
+ return 0;
+}
+
+static void
+subsys_hs_shutdown(void)
+{
+}
+
+const subsys_fns_t sys_hs = {
+ SUBSYS_DECLARE_LOCATION(),
+
+ .name = "hs",
+ .supported = true,
+ .level = HS_SUBSYS_LEVEL,
+
+ .initialize = subsys_hs_initialize,
+ .shutdown = subsys_hs_shutdown,
+
+ .get_metrics = hs_metrics_get_stores,
+};
diff --git a/src/feature/hs/hs_sys.h b/src/feature/hs/hs_sys.h
new file mode 100644
index 0000000000..4427b59b9c
--- /dev/null
+++ b/src/feature/hs/hs_sys.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file hs_sys.h
+ * @brief Header for feature/hs/hs_sys.c
+ **/
+
+#ifndef TOR_FEATURE_HS_HS_SYS_H
+#define TOR_FEATURE_HS_HS_SYS_H
+
+extern const struct subsys_fns_t sys_hs;
+
+/**
+ * Subsystem level for the metrics system.
+ *
+ * Defined here so that it can be shared between the real and stub
+ * definitions.
+ **/
+#define HS_SUBSYS_LEVEL (51)
+
+#endif /* !defined(TOR_FEATURE_HS_HS_SYS_H) */
diff --git a/src/feature/hs/include.am b/src/feature/hs/include.am
index af1dc65585..c55abd3d47 100644
--- a/src/feature/hs/include.am
+++ b/src/feature/hs/include.am
@@ -13,9 +13,12 @@ LIBTOR_APP_A_SOURCES += \
src/feature/hs/hs_dos.c \
src/feature/hs/hs_ident.c \
src/feature/hs/hs_intropoint.c \
+ src/feature/hs/hs_metrics.c \
src/feature/hs/hs_ob.c \
src/feature/hs/hs_service.c \
- src/feature/hs/hs_stats.c
+ src/feature/hs/hs_stats.c \
+ src/feature/hs/hs_sys.c \
+ src/feature/hs/hs_metrics_entry.c
# ADD_C_FILE: INSERT HEADERS HERE.
noinst_HEADERS += \
@@ -31,9 +34,12 @@ noinst_HEADERS += \
src/feature/hs/hs_dos.h \
src/feature/hs/hs_ident.h \
src/feature/hs/hs_intropoint.h \
+ src/feature/hs/hs_metrics.h \
src/feature/hs/hs_ob.h \
src/feature/hs/hs_opts_st.h \
src/feature/hs/hs_options.inc \
src/feature/hs/hs_service.h \
src/feature/hs/hs_stats.h \
- src/feature/hs/hsdir_index_st.h
+ src/feature/hs/hsdir_index_st.h \
+ src/feature/hs/hs_sys.h \
+ src/feature/hs/hs_metrics_entry.h
diff --git a/src/feature/keymgt/loadkey.c b/src/feature/keymgt/loadkey.c
index 7958bd964f..6ea3df492d 100644
--- a/src/feature/keymgt/loadkey.c
+++ b/src/feature/keymgt/loadkey.c
@@ -638,7 +638,7 @@ ed_key_init_from_file(const char *fname, uint32_t flags,
bad_cert = 1;
} else if (signing_key && cert->signing_key_included &&
! ed25519_pubkey_eq(&signing_key->pubkey, &cert->signing_key)) {
- tor_log(severity, LD_OR, "Certificate signed by unexpectd key!");
+ tor_log(severity, LD_OR, "Certificate signed by unexpected key!");
bad_cert = 1;
}
@@ -661,7 +661,7 @@ ed_key_init_from_file(const char *fname, uint32_t flags,
uint32_t cert_flags = 0;
if (flags & INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT)
cert_flags |= CERT_FLAG_INCLUDE_SIGNING_KEY;
- cert = tor_cert_create(signing_key, cert_type,
+ cert = tor_cert_create_ed25519(signing_key, cert_type,
&keypair->pubkey,
now, lifetime,
cert_flags);
@@ -739,7 +739,7 @@ ed_key_new(const ed25519_keypair_t *signing_key,
uint32_t cert_flags = 0;
if (flags & INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT)
cert_flags |= CERT_FLAG_INCLUDE_SIGNING_KEY;
- tor_cert_t *cert = tor_cert_create(signing_key, cert_type,
+ tor_cert_t *cert = tor_cert_create_ed25519(signing_key, cert_type,
&keypair->pubkey,
now, lifetime,
cert_flags);
diff --git a/src/feature/metrics/.may_include b/src/feature/metrics/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/metrics/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/metrics/include.am b/src/feature/metrics/include.am
new file mode 100644
index 0000000000..0e875f43ad
--- /dev/null
+++ b/src/feature/metrics/include.am
@@ -0,0 +1,10 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/metrics/metrics.c \
+ src/feature/metrics/metrics_sys.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/metrics/metrics.h \
+ src/feature/metrics/metrics_sys.h
diff --git a/src/feature/metrics/metrics.c b/src/feature/metrics/metrics.c
new file mode 100644
index 0000000000..9a72fe7145
--- /dev/null
+++ b/src/feature/metrics/metrics.c
@@ -0,0 +1,280 @@
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file metrics.c
+ * @brief Metrics subsystem.
+ **/
+
+#include "orconfig.h"
+
+#include "core/or/or.h"
+
+#include "lib/encoding/confline.h"
+#include "lib/log/util_bug.h"
+#include "lib/malloc/malloc.h"
+#include "lib/metrics/metrics_store.h"
+#include "lib/net/resolve.h"
+#include "lib/string/printf.h"
+#include "lib/net/nettypes.h"
+#include "lib/net/address.h"
+
+#include "core/mainloop/connection.h"
+#include "core/or/connection_or.h"
+#include "core/or/connection_st.h"
+#include "core/or/policies.h"
+#include "core/or/port_cfg_st.h"
+#include "core/proto/proto_http.h"
+
+#include "feature/dircommon/directory.h"
+#include "feature/metrics/metrics.h"
+
+#include "app/config/config.h"
+#include "app/main/subsysmgr.h"
+
+/** Metrics format driver set by the MetricsPort option. */
+static metrics_format_t the_format = METRICS_FORMAT_PROMETHEUS;
+
+/** Return true iff the given peer address is allowed by our MetricsPortPolicy
+ * option that is is in that list. */
+static bool
+metrics_request_allowed(const tor_addr_t *peer_addr)
+{
+ tor_assert(peer_addr);
+
+ return metrics_policy_permits_address(peer_addr);
+}
+
+/** Helper: For a metrics port connection, write the HTTP response header
+ * using the data length passed. */
+static void
+write_metrics_http_response(const size_t data_len, connection_t *conn)
+{
+ char date[RFC1123_TIME_LEN+1];
+ buf_t *buf = buf_new_with_capacity(128 + data_len);
+
+ format_rfc1123_time(date, approx_time());
+ buf_add_printf(buf, "HTTP/1.0 200 OK\r\nDate: %s\r\n", date);
+ buf_add_printf(buf, "Content-Type: text/plain; charset=utf-8\r\n");
+ buf_add_printf(buf, "Content-Length: %" TOR_PRIuSZ "\r\n", data_len);
+ buf_add_string(buf, "\r\n");
+
+ connection_buf_add_buf(conn, buf);
+ buf_free(buf);
+}
+
+/** Return newly allocated buffer containing the output of all subsystems
+ * having metrics.
+ *
+ * This is used to output the content on the MetricsPort. */
+buf_t *
+metrics_get_output(const metrics_format_t fmt)
+{
+ buf_t *data = buf_new();
+
+ /* Go over all subsystems that exposes a metrics store. */
+ for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+ const smartlist_t *stores;
+ const subsys_fns_t *sys = tor_subsystems[i];
+
+ /* Skip unsupported subsystems. */
+ if (!sys->supported) {
+ continue;
+ }
+
+ if (sys->get_metrics && (stores = sys->get_metrics())) {
+ SMARTLIST_FOREACH_BEGIN(stores, const metrics_store_t *, store) {
+ metrics_store_get_output(fmt, store, data);
+ } SMARTLIST_FOREACH_END(store);
+ }
+ }
+
+ return data;
+}
+
+/** Process what is in the inbuf of this connection of type metrics.
+ *
+ * Return 0 on success else -1 on error for which the connection is marked for
+ * close. */
+int
+metrics_connection_process_inbuf(connection_t *conn)
+{
+ int ret = -1;
+ char *headers = NULL, *command = NULL, *url = NULL;
+ const char *errmsg = NULL;
+
+ tor_assert(conn);
+ tor_assert(conn->type == CONN_TYPE_METRICS);
+
+ if (!metrics_request_allowed(&conn->addr)) {
+ /* Close connection. Don't bother returning anything if you are not
+ * allowed by being on the policy list. */
+ errmsg = NULL;
+ goto err;
+ }
+
+ const int http_status =
+ connection_fetch_from_buf_http(conn, &headers, 1024, NULL, NULL, 1024, 0);
+ if (http_status < 0) {
+ errmsg = "HTTP/1.0 400 Bad Request\r\n\r\n";
+ goto err;
+ } else if (http_status == 0) {
+ /* no HTTP request yet. */
+ ret = 0;
+ goto done;
+ }
+
+ const int cmd_status = parse_http_command(headers, &command, &url);
+ if (cmd_status < 0) {
+ errmsg = "HTTP/1.0 400 Bad Request\r\n\r\n";
+ goto err;
+ } else if (strcmpstart(command, "GET")) {
+ errmsg = "HTTP/1.0 405 Method Not Allowed\r\n\r\n";
+ goto err;
+ }
+ tor_assert(url);
+
+ /* Where we expect the query to come for. */
+#define EXPECTED_URL_PATH "/metrics"
+#define EXPECTED_URL_PATH_LEN (sizeof(EXPECTED_URL_PATH) - 1) /* No NUL */
+
+ if (!strcmpstart(url, EXPECTED_URL_PATH) &&
+ strlen(url) == EXPECTED_URL_PATH_LEN) {
+ buf_t *data = metrics_get_output(the_format);
+
+ write_metrics_http_response(buf_datalen(data), conn);
+ connection_buf_add_buf(conn, data);
+ buf_free(data);
+ } else {
+ errmsg = "HTTP/1.0 404 Not Found\r\n\r\n";
+ goto err;
+ }
+
+ ret = 0;
+ goto done;
+
+ err:
+ if (errmsg) {
+ log_info(LD_EDGE, "HTTP metrics error: saying %s", escaped(errmsg));
+ connection_buf_add(errmsg, strlen(errmsg), conn);
+ }
+ connection_mark_and_flush(conn);
+
+ done:
+ tor_free(headers);
+ tor_free(command);
+ tor_free(url);
+
+ return ret;
+}
+
+/** Parse metrics ports from options. On success, add the port to the ports
+ * list and return 0. On failure, set err_msg_out to a newly allocated string
+ * describing the problem and return -1. */
+int
+metrics_parse_ports(or_options_t *options, smartlist_t *ports,
+ char **err_msg_out)
+{
+ int num_elems, ok = 0, ret = -1;
+ const char *addrport_str = NULL, *fmt_str = NULL;
+ smartlist_t *elems = NULL;
+ port_cfg_t *cfg = NULL;
+
+ tor_assert(options);
+ tor_assert(ports);
+
+ /* No metrics port to configure, just move on . */
+ if (!options->MetricsPort_lines) {
+ return 0;
+ }
+
+ elems = smartlist_new();
+
+ /* Split between the protocol and the address/port. */
+ num_elems = smartlist_split_string(elems,
+ options->MetricsPort_lines->value, " ",
+ SPLIT_SKIP_SPACE | SPLIT_IGNORE_BLANK, 2);
+ if (num_elems < 1) {
+ *err_msg_out = tor_strdup("MetricsPort is missing port.");
+ goto end;
+ }
+
+ addrport_str = smartlist_get(elems, 0);
+ if (num_elems >= 2) {
+ /* Parse the format if any. */
+ fmt_str = smartlist_get(elems, 1);
+ if (!strcasecmp(fmt_str, "prometheus")) {
+ the_format = METRICS_FORMAT_PROMETHEUS;
+ } else {
+ tor_asprintf(err_msg_out, "MetricsPort unknown format: %s", fmt_str);
+ goto end;
+ }
+ }
+
+ /* Port configuration with default address. */
+ cfg = port_cfg_new(0);
+ cfg->type = CONN_TYPE_METRICS_LISTENER;
+
+ /* Parse the port first. Then an address if any can be found. */
+ cfg->port = (int) tor_parse_long(addrport_str, 10, 0, 65535, &ok, NULL);
+ if (ok) {
+ tor_addr_parse(&cfg->addr, "127.0.0.1");
+ } else {
+ /* We probably have a host:port situation */
+ if (tor_addr_port_lookup(addrport_str, &cfg->addr,
+ (uint16_t *) &cfg->port) < 0) {
+ *err_msg_out = tor_strdup("MetricsPort address/port failed to parse or "
+ "resolve.");
+ goto end;
+ }
+ }
+ /* Add it to the ports list. */
+ smartlist_add(ports, cfg);
+
+ /* It is set. MetricsPort doesn't support the NoListen options or such that
+ * would prevent from being a real listener port. */
+ options->MetricsPort_set = 1;
+
+ /* Success. */
+ ret = 0;
+
+ end:
+ if (ret != 0) {
+ port_cfg_free(cfg);
+ }
+ SMARTLIST_FOREACH(elems, char *, e, tor_free(e));
+ smartlist_free(elems);
+ return ret;
+}
+
+/** Called when conn has gotten its socket closed. */
+int
+metrics_connection_reached_eof(connection_t *conn)
+{
+ tor_assert(conn);
+
+ log_info(LD_EDGE, "Metrics connection reached EOF. Closing.");
+ connection_mark_for_close(conn);
+ return 0;
+}
+
+/** Called when conn has no more bytes left on its outbuf. Return 0 indicating
+ * success. */
+int
+metrics_connection_finished_flushing(connection_t *conn)
+{
+ tor_assert(conn);
+ return 0;
+}
+
+/** Initialize the subsystem. */
+void
+metrics_init(void)
+{
+}
+
+/** Cleanup and free any global memory of this subsystem. */
+void
+metrics_cleanup(void)
+{
+}
diff --git a/src/feature/metrics/metrics.h b/src/feature/metrics/metrics.h
new file mode 100644
index 0000000000..e072519d10
--- /dev/null
+++ b/src/feature/metrics/metrics.h
@@ -0,0 +1,37 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file metrics.h
+ * @brief Header for feature/metrics/metrics.c
+ **/
+
+#ifndef TOR_FEATURE_METRICS_METRICS_H
+#define TOR_FEATURE_METRICS_METRICS_H
+
+#include "lib/buf/buffers.h"
+#include "lib/container/smartlist.h"
+
+#include "app/config/or_options_st.h"
+
+#include "lib/metrics/metrics_common.h"
+
+struct connection_t;
+
+/* Initializer / Cleanup. */
+void metrics_init(void);
+void metrics_cleanup(void);
+
+/* Accessors. */
+buf_t *metrics_get_output(const metrics_format_t fmt);
+
+/* Connection. */
+int metrics_connection_process_inbuf(struct connection_t *conn);
+int metrics_connection_reached_eof(struct connection_t *conn);
+int metrics_connection_finished_flushing(struct connection_t *conn);
+
+/* Configuration. */
+int metrics_parse_ports(or_options_t *options, smartlist_t *ports,
+ char **err_msg_out);
+
+#endif /* !defined(TOR_FEATURE_METRICS_METRICS_H) */
diff --git a/src/feature/metrics/metrics_sys.c b/src/feature/metrics/metrics_sys.c
new file mode 100644
index 0000000000..419318068e
--- /dev/null
+++ b/src/feature/metrics/metrics_sys.c
@@ -0,0 +1,37 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file metrics_sys.c
+ * @brief Setup and tear down the metrics subsystem.
+ **/
+
+#include "lib/subsys/subsys.h"
+
+#include "feature/metrics/metrics.h"
+#include "feature/metrics/metrics_sys.h"
+
+static int
+subsys_metrics_initialize(void)
+{
+ metrics_init();
+ return 0;
+}
+
+static void
+subsys_metrics_shutdown(void)
+{
+ metrics_cleanup();
+}
+
+const subsys_fns_t sys_metrics = {
+ SUBSYS_DECLARE_LOCATION(),
+
+ .name = "metrics",
+ .supported = true,
+ .level = METRICS_SUBSYS_LEVEL,
+
+ .initialize = subsys_metrics_initialize,
+ .shutdown = subsys_metrics_shutdown,
+};
+
diff --git a/src/feature/metrics/metrics_sys.h b/src/feature/metrics/metrics_sys.h
new file mode 100644
index 0000000000..30c1b14836
--- /dev/null
+++ b/src/feature/metrics/metrics_sys.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file metrics_sys.h
+ * @brief Header for feature/metrics/metrics_sys.c
+ **/
+
+#ifndef TOR_FEATURE_METRICS_METRICS_SYS_H
+#define TOR_FEATURE_METRICS_METRICS_SYS_H
+
+extern const struct subsys_fns_t sys_metrics;
+
+/**
+ * Subsystem level for the metrics system.
+ *
+ * Defined here so that it can be shared between the real and stub
+ * definitions.
+ **/
+#define METRICS_SUBSYS_LEVEL (99)
+
+#endif /* !defined(TOR_FEATURE_METRICS_METRICS_SYS_H) */
diff --git a/src/feature/nodelist/authcert.c b/src/feature/nodelist/authcert.c
index 97e44d53e3..c5b31be9e3 100644
--- a/src/feature/nodelist/authcert.c
+++ b/src/feature/nodelist/authcert.c
@@ -460,19 +460,15 @@ trusted_dirs_load_certs_from_string(const char *contents, int source,
if (ds && cert->cache_info.published_on > ds->addr_current_at) {
/* Check to see whether we should update our view of the authority's
* address. */
- if (cert->addr && cert->dir_port &&
- (ds->addr != cert->addr ||
- ds->dir_port != cert->dir_port)) {
- char *a = tor_dup_ip(cert->addr);
- if (a) {
- log_notice(LD_DIR, "Updating address for directory authority %s "
- "from %s:%d to %s:%d based on certificate.",
- ds->nickname, ds->address, (int)ds->dir_port,
- a, cert->dir_port);
- tor_free(a);
- }
- ds->addr = cert->addr;
- ds->dir_port = cert->dir_port;
+ if (!tor_addr_is_null(&cert->ipv4_addr) && cert->ipv4_dirport &&
+ (!tor_addr_eq(&ds->ipv4_addr, &cert->ipv4_addr) ||
+ ds->ipv4_dirport != cert->ipv4_dirport)) {
+ log_notice(LD_DIR, "Updating address for directory authority %s "
+ "from %s:%"PRIu16" to %s:%"PRIu16" based on certificate.",
+ ds->nickname, ds->address, ds->ipv4_dirport,
+ fmt_addr(&cert->ipv4_addr), cert->ipv4_dirport);
+ tor_addr_copy(&ds->ipv4_addr, &cert->ipv4_addr);
+ ds->ipv4_dirport = cert->ipv4_dirport;
}
ds->addr_current_at = cert->cache_info.published_on;
}
@@ -745,7 +741,7 @@ static const char *BAD_SIGNING_KEYS[] = {
* which, because of the old openssl heartbleed vulnerability, should
* never be trusted. */
int
-authority_cert_is_blacklisted(const authority_cert_t *cert)
+authority_cert_is_denylisted(const authority_cert_t *cert)
{
char hex_digest[HEX_DIGEST_LEN+1];
int i;
@@ -812,7 +808,7 @@ authority_certs_fetch_resource_impl(const char *resource,
/* clients always make OR connections to bridges */
tor_addr_port_t or_ap;
/* we are willing to use a non-preferred address if we need to */
- fascist_firewall_choose_address_node(node, FIREWALL_OR_CONNECTION, 0,
+ reachable_addr_choose_from_node(node, FIREWALL_OR_CONNECTION, 0,
&or_ap);
req = directory_request_new(DIR_PURPOSE_FETCH_CERTIFICATE);
diff --git a/src/feature/nodelist/authcert.h b/src/feature/nodelist/authcert.h
index 33065589ba..4c3d79ceed 100644
--- a/src/feature/nodelist/authcert.h
+++ b/src/feature/nodelist/authcert.h
@@ -41,7 +41,7 @@ void authority_cert_dl_failed(const char *id_digest,
void authority_certs_fetch_missing(networkstatus_t *status, time_t now,
const char *dir_hint);
int authority_cert_dl_looks_uncertain(const char *id_digest);
-int authority_cert_is_blacklisted(const authority_cert_t *cert);
+int authority_cert_is_denylisted(const authority_cert_t *cert);
void authority_cert_free_(authority_cert_t *cert);
#define authority_cert_free(cert) \
diff --git a/src/feature/nodelist/authority_cert_st.h b/src/feature/nodelist/authority_cert_st.h
index 9145b12bbf..aa9831d12e 100644
--- a/src/feature/nodelist/authority_cert_st.h
+++ b/src/feature/nodelist/authority_cert_st.h
@@ -27,10 +27,10 @@ struct authority_cert_t {
char signing_key_digest[DIGEST_LEN];
/** The listed expiration time of this certificate. */
time_t expires;
- /** This authority's IPv4 address, in host order. */
- uint32_t addr;
+ /** This authority's IPv4 address. */
+ tor_addr_t ipv4_addr;
/** This authority's directory port. */
- uint16_t dir_port;
+ uint16_t ipv4_dirport;
};
#endif /* !defined(AUTHORITY_CERT_ST_H) */
diff --git a/src/feature/nodelist/describe.c b/src/feature/nodelist/describe.c
index 00896d5a44..b6a0fe74f7 100644
--- a/src/feature/nodelist/describe.c
+++ b/src/feature/nodelist/describe.c
@@ -12,7 +12,12 @@
#define DESCRIBE_PRIVATE
#include "core/or/or.h"
+#include "core/or/extendinfo.h"
#include "feature/nodelist/describe.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerinfo.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_format.h"
#include "core/or/extend_info_st.h"
#include "feature/nodelist/node_st.h"
@@ -25,29 +30,30 @@
* <b>id_digest</b>, nickname <b>nickname</b>, and addresses <b>addr32h</b> and
* <b>addr</b>.
*
- * The <b>nickname</b> and <b>addr</b> fields are optional and may be set to
- * NULL or the null address. The <b>addr32h</b> field is optional and may be
- * set to 0.
+ * The <b>nickname</b>, <b>ipv6_addr</b> and <b>ipv4_addr</b> fields are
+ * optional and may be set to NULL or the null address.
*
* Return a pointer to the front of <b>buf</b>.
* If buf is NULL, return a string constant describing the error.
*/
STATIC const char *
format_node_description(char *buf,
- const char *id_digest,
+ const char *rsa_id_digest,
+ const ed25519_public_key_t *ed25519_id,
const char *nickname,
- const tor_addr_t *addr,
- uint32_t addr32h)
+ const tor_addr_t *ipv4_addr,
+ const tor_addr_t *ipv6_addr)
{
size_t rv = 0;
- bool has_addr = addr && !tor_addr_is_null(addr);
+ bool has_ipv6 = ipv6_addr && !tor_addr_is_null(ipv6_addr);
+ bool valid_ipv4 = false;
if (!buf)
return "<NULL BUFFER>";
memset(buf, 0, NODE_DESC_BUF_LEN);
- if (!id_digest) {
+ if (!rsa_id_digest) {
/* strlcpy() returns the length of the source string it attempted to copy,
* ignoring any required truncation due to the buffer length. */
rv = strlcpy(buf, "<NULL ID DIGEST>", NODE_DESC_BUF_LEN);
@@ -65,7 +71,7 @@ format_node_description(char *buf,
memset(hex_digest, 0, sizeof(hex_digest));
base16_encode(hex_digest, sizeof(hex_digest),
- id_digest, DIGEST_LEN);
+ rsa_id_digest, DIGEST_LEN);
rv = strlcat(buf, hex_digest, NODE_DESC_BUF_LEN);
tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
}
@@ -76,39 +82,47 @@ format_node_description(char *buf,
rv = strlcat(buf, nickname, NODE_DESC_BUF_LEN);
tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
}
- if (addr32h || has_addr) {
- rv = strlcat(buf, " at ", NODE_DESC_BUF_LEN);
+ if (ed25519_id) {
+ char ed_base64[ED25519_BASE64_LEN+1];
+ ed25519_public_to_base64(ed_base64, ed25519_id);
+ rv = strlcat(buf, " [", NODE_DESC_BUF_LEN);
+ tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
+ rv = strlcat(buf, ed_base64, NODE_DESC_BUF_LEN);
+ tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
+ rv = strlcat(buf, "]", NODE_DESC_BUF_LEN);
tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
}
- if (addr32h) {
- int ntoa_rv = 0;
- char ipv4_addr_str[INET_NTOA_BUF_LEN];
- memset(ipv4_addr_str, 0, sizeof(ipv4_addr_str));
- struct in_addr in;
- memset(&in, 0, sizeof(in));
-
- in.s_addr = htonl(addr32h);
- ntoa_rv = tor_inet_ntoa(&in, ipv4_addr_str, sizeof(ipv4_addr_str));
- tor_assert_nonfatal(ntoa_rv >= 0);
-
- rv = strlcat(buf, ipv4_addr_str, NODE_DESC_BUF_LEN);
+ if (ipv4_addr || has_ipv6) {
+ rv = strlcat(buf, " at ", NODE_DESC_BUF_LEN);
tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
}
+ if (ipv4_addr) {
+ const char *str_rv = NULL;
+ char addr_str[TOR_ADDR_BUF_LEN];
+ memset(addr_str, 0, sizeof(addr_str));
+
+ str_rv = tor_addr_to_str(addr_str, ipv4_addr, sizeof(addr_str), 0);
+ if (str_rv) {
+ rv = strlcat(buf, addr_str, NODE_DESC_BUF_LEN);
+ tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
+ valid_ipv4 = true;
+ }
+ }
/* Both addresses are valid */
- if (addr32h && has_addr) {
+ if (valid_ipv4 && has_ipv6) {
rv = strlcat(buf, " and ", NODE_DESC_BUF_LEN);
tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
}
- if (has_addr) {
+ if (has_ipv6) {
const char *str_rv = NULL;
char addr_str[TOR_ADDR_BUF_LEN];
memset(addr_str, 0, sizeof(addr_str));
- str_rv = tor_addr_to_str(addr_str, addr, sizeof(addr_str), 1);
- tor_assert_nonfatal(str_rv == addr_str);
-
- rv = strlcat(buf, addr_str, NODE_DESC_BUF_LEN);
- tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
+ str_rv = tor_addr_to_str(addr_str, ipv6_addr, sizeof(addr_str), 1);
+ if (str_rv) {
+ rv = strlcat(buf, addr_str, NODE_DESC_BUF_LEN);
+ tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
+ }
}
return buf;
@@ -127,11 +141,14 @@ router_describe(const routerinfo_t *ri)
if (!ri)
return "<null>";
+ const ed25519_public_key_t *ed25519_id = routerinfo_get_ed25519_id(ri);
+
return format_node_description(buf,
ri->cache_info.identity_digest,
+ ed25519_id,
ri->nickname,
- &ri->ipv6_addr,
- ri->addr);
+ &ri->ipv4_addr,
+ &ri->ipv6_addr);
}
/** Return a human-readable description of the node_t <b>node</b>.
@@ -144,15 +161,14 @@ node_describe(const node_t *node)
{
static char buf[NODE_DESC_BUF_LEN];
const char *nickname = NULL;
- uint32_t addr32h = 0;
- const tor_addr_t *ipv6_addr = NULL;
+ const tor_addr_t *ipv6_addr = NULL, *ipv4_addr = NULL;
if (!node)
return "<null>";
if (node->rs) {
nickname = node->rs->nickname;
- addr32h = node->rs->addr;
+ ipv4_addr = &node->rs->ipv4_addr;
ipv6_addr = &node->rs->ipv6_addr;
/* Support consensus versions less than 28, when IPv6 addresses were in
* microdescs. This code can be removed when 0.2.9 is no longer supported,
@@ -162,17 +178,20 @@ node_describe(const node_t *node)
}
} else if (node->ri) {
nickname = node->ri->nickname;
- addr32h = node->ri->addr;
+ ipv4_addr = &node->ri->ipv4_addr;
ipv6_addr = &node->ri->ipv6_addr;
} else {
return "<null rs and ri>";
}
+ const ed25519_public_key_t *ed25519_id = node_get_ed25519_id(node);
+
return format_node_description(buf,
node->identity,
+ ed25519_id,
nickname,
- ipv6_addr,
- addr32h);
+ ipv4_addr,
+ ipv6_addr);
}
/** Return a human-readable description of the routerstatus_t <b>rs</b>.
@@ -190,9 +209,10 @@ routerstatus_describe(const routerstatus_t *rs)
return format_node_description(buf,
rs->identity_digest,
+ NULL,
rs->nickname,
- &rs->ipv6_addr,
- rs->addr);
+ &rs->ipv4_addr,
+ &rs->ipv6_addr);
}
/** Return a human-readable description of the extend_info_t <b>ei</b>.
@@ -208,11 +228,21 @@ extend_info_describe(const extend_info_t *ei)
if (!ei)
return "<null>";
+ const tor_addr_port_t *ap4 = extend_info_get_orport(ei, AF_INET);
+ const tor_addr_port_t *ap6 = extend_info_get_orport(ei, AF_INET6);
+ const tor_addr_t *addr4 = ap4 ? &ap4->addr : NULL;
+ const tor_addr_t *addr6 = ap6 ? &ap6->addr : NULL;
+
+ const ed25519_public_key_t *ed25519_id = &ei->ed_identity;
+ if (ed25519_public_key_is_zero(ed25519_id))
+ ed25519_id = NULL;
+
return format_node_description(buf,
ei->identity_digest,
+ ed25519_id,
ei->nickname,
- &ei->addr,
- 0);
+ addr4,
+ addr6);
}
/** Set <b>buf</b> (which must have MAX_VERBOSE_NICKNAME_LEN+1 bytes) to the
diff --git a/src/feature/nodelist/describe.h b/src/feature/nodelist/describe.h
index d0fa1af263..898b5c943b 100644
--- a/src/feature/nodelist/describe.h
+++ b/src/feature/nodelist/describe.h
@@ -35,22 +35,28 @@ void router_get_verbose_nickname(char *buf, const routerinfo_t *router);
/**
* Longest allowed output of format_node_description, plus 1 character for
* NUL. This allows space for:
- * "$FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF~xxxxxxxxxxxxxxxxxxx at"
+ * "$FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF~xxxxxxxxxxxxxxxxxxx "
+ * "[+++++++++++++++++++++++++++++++++++++++++++] at"
* " 255.255.255.255 and [ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255]"
* plus a terminating NUL.
*/
#define NODE_DESC_BUF_LEN \
- (MAX_VERBOSE_NICKNAME_LEN+4+IPV4_BUF_LEN_NO_NUL+5+TOR_ADDR_BUF_LEN)
+ (MAX_VERBOSE_NICKNAME_LEN+4 \
+ + ED25519_BASE64_LEN+3 \
+ + IPV4_BUF_LEN_NO_NUL+5 \
+ + TOR_ADDR_BUF_LEN)
#endif /* defined(DESCRIBE_PRIVATE) || defined(TOR_UNIT_TESTS) */
#ifdef TOR_UNIT_TESTS
+struct ed25519_public_key_t;
STATIC const char *format_node_description(char *buf,
- const char *id_digest,
- const char *nickname,
- const tor_addr_t *addr,
- uint32_t addr32h);
+ const char *rsa_id_digest,
+ const struct ed25519_public_key_t *ed25519_id,
+ const char *nickname,
+ const tor_addr_t *ipv4_addr,
+ const tor_addr_t *ipv6_addr);
#endif /* defined(TOR_UNIT_TESTS) */
diff --git a/src/feature/nodelist/dirlist.c b/src/feature/nodelist/dirlist.c
index 4317491043..423c4106e2 100644
--- a/src/feature/nodelist/dirlist.c
+++ b/src/feature/nodelist/dirlist.c
@@ -55,15 +55,13 @@ static smartlist_t *fallback_dir_servers = NULL;
static void
add_trusted_dir_to_nodelist_addr_set(const dir_server_t *dir)
{
- tor_addr_t tmp_addr;
-
tor_assert(dir);
tor_assert(dir->is_authority);
/* Add IPv4 and then IPv6 if applicable. For authorities, we add the ORPort
* and DirPort so re-entry into the network back to them is not possible. */
- tor_addr_from_ipv4h(&tmp_addr, dir->addr);
- nodelist_add_addr_to_address_set(&tmp_addr, dir->or_port, dir->dir_port);
+ nodelist_add_addr_to_address_set(&dir->ipv4_addr, dir->ipv4_orport,
+ dir->ipv4_dirport);
if (!tor_addr_is_null(&dir->ipv6_addr)) {
/* IPv6 DirPort is not a thing yet for authorities. */
nodelist_add_addr_to_address_set(&dir->ipv6_addr, dir->ipv6_orport, 0);
@@ -71,7 +69,7 @@ add_trusted_dir_to_nodelist_addr_set(const dir_server_t *dir)
}
/** Go over the trusted directory server list and add their address(es) to the
- * nodelist address set. This is called everytime a new consensus is set. */
+ * nodelist address set. This is called every time a new consensus is set. */
MOCK_IMPL(void,
dirlist_add_trusted_dir_addresses, (void))
{
@@ -241,8 +239,8 @@ mark_all_dirservers_up(smartlist_t *server_list)
/** Return true iff <b>digest</b> is the digest of the identity key of a
* trusted directory matching at least one bit of <b>type</b>. If <b>type</b>
* is zero (NO_DIRINFO), or ALL_DIRINFO, any authority is okay. */
-int
-router_digest_is_trusted_dir_type(const char *digest, dirinfo_type_t type)
+MOCK_IMPL(int, router_digest_is_trusted_dir_type,
+ (const char *digest, dirinfo_type_t type))
{
if (!trusted_dir_servers)
return 0;
@@ -255,6 +253,34 @@ router_digest_is_trusted_dir_type(const char *digest, dirinfo_type_t type)
return 0;
}
+/** Return true iff the given address matches a trusted directory that matches
+ * at least one bit of type.
+ *
+ * If type is NO_DIRINFO or ALL_DIRINFO, any authority is matched. */
+bool
+router_addr_is_trusted_dir_type(const tor_addr_t *addr, dirinfo_type_t type)
+{
+ int family = tor_addr_family(addr);
+
+ if (!trusted_dir_servers) {
+ return false;
+ }
+
+ SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, dir_server_t *, ent) {
+ /* Ignore entries that don't match the given type. */
+ if (type != NO_DIRINFO && (type & ent->type) == 0) {
+ continue;
+ }
+ /* Match IPv4 or IPv6 address. */
+ if ((family == AF_INET && tor_addr_eq(addr, &ent->ipv4_addr)) ||
+ (family == AF_INET6 && tor_addr_eq(addr, &ent->ipv6_addr))) {
+ return true;
+ }
+ } SMARTLIST_FOREACH_END(ent);
+
+ return false;
+}
+
/** Create a directory server at <b>address</b>:<b>port</b>, with OR identity
* key <b>digest</b> which has DIGEST_LEN bytes. If <b>address</b> is NULL,
* add ourself. If <b>is_authority</b>, this is a directory authority. Return
@@ -262,16 +288,15 @@ router_digest_is_trusted_dir_type(const char *digest, dirinfo_type_t type)
static dir_server_t *
dir_server_new(int is_authority,
const char *nickname,
- const tor_addr_t *addr,
+ const tor_addr_t *ipv4_addr,
const char *hostname,
- uint16_t dir_port, uint16_t or_port,
+ uint16_t ipv4_dirport, uint16_t ipv4_orport,
const tor_addr_port_t *addrport_ipv6,
const char *digest, const char *v3_auth_digest,
dirinfo_type_t type,
double weight)
{
dir_server_t *ent;
- uint32_t a;
char *hostname_ = NULL;
tor_assert(digest);
@@ -279,27 +304,26 @@ dir_server_new(int is_authority,
if (weight < 0)
return NULL;
- if (tor_addr_family(addr) == AF_INET)
- a = tor_addr_to_ipv4h(addr);
- else
+ if (!ipv4_addr) {
return NULL;
+ }
if (!hostname)
- hostname_ = tor_addr_to_str_dup(addr);
+ hostname_ = tor_addr_to_str_dup(ipv4_addr);
else
hostname_ = tor_strdup(hostname);
ent = tor_malloc_zero(sizeof(dir_server_t));
ent->nickname = nickname ? tor_strdup(nickname) : NULL;
ent->address = hostname_;
- ent->addr = a;
- ent->dir_port = dir_port;
- ent->or_port = or_port;
+ tor_addr_copy(&ent->ipv4_addr, ipv4_addr);
+ ent->ipv4_dirport = ipv4_dirport;
+ ent->ipv4_orport = ipv4_orport;
ent->is_running = 1;
ent->is_authority = is_authority;
ent->type = type;
ent->weight = weight;
- if (addrport_ipv6) {
+ if (addrport_ipv6 && tor_addr_port_is_valid_ap(addrport_ipv6, 0)) {
if (tor_addr_family(&addrport_ipv6->addr) != AF_INET6) {
log_warn(LD_BUG, "Hey, I got a non-ipv6 addr as addrport_ipv6.");
tor_addr_make_unspec(&ent->ipv6_addr);
@@ -316,13 +340,13 @@ dir_server_new(int is_authority,
memcpy(ent->v3_identity_digest, v3_auth_digest, DIGEST_LEN);
if (nickname)
- tor_asprintf(&ent->description, "directory server \"%s\" at %s:%d",
- nickname, hostname_, (int)dir_port);
+ tor_asprintf(&ent->description, "directory server \"%s\" at %s:%" PRIu16,
+ nickname, hostname_, ipv4_dirport);
else
- tor_asprintf(&ent->description, "directory server at %s:%d",
- hostname_, (int)dir_port);
+ tor_asprintf(&ent->description, "directory server at %s:%" PRIu16,
+ hostname_, ipv4_dirport);
- ent->fake_status.addr = ent->addr;
+ tor_addr_copy(&ent->fake_status.ipv4_addr, &ent->ipv4_addr);
tor_addr_copy(&ent->fake_status.ipv6_addr, &ent->ipv6_addr);
memcpy(ent->fake_status.identity_digest, digest, DIGEST_LEN);
if (nickname)
@@ -330,44 +354,43 @@ dir_server_new(int is_authority,
sizeof(ent->fake_status.nickname));
else
ent->fake_status.nickname[0] = '\0';
- ent->fake_status.dir_port = ent->dir_port;
- ent->fake_status.or_port = ent->or_port;
+ ent->fake_status.ipv4_dirport = ent->ipv4_dirport;
+ ent->fake_status.ipv4_orport = ent->ipv4_orport;
ent->fake_status.ipv6_orport = ent->ipv6_orport;
return ent;
}
-/** Create an authoritative directory server at
- * <b>address</b>:<b>port</b>, with identity key <b>digest</b>. If
- * <b>address</b> is NULL, add ourself. Return the new trusted directory
- * server entry on success or NULL if we couldn't add it. */
+/** Create an authoritative directory server at <b>address</b>:<b>port</b>,
+ * with identity key <b>digest</b>. If <b>ipv4_addr_str</b> is NULL, add
+ * ourself. Return the new trusted directory server entry on success or NULL
+ * if we couldn't add it. */
dir_server_t *
trusted_dir_server_new(const char *nickname, const char *address,
- uint16_t dir_port, uint16_t or_port,
+ uint16_t ipv4_dirport, uint16_t ipv4_orport,
const tor_addr_port_t *ipv6_addrport,
const char *digest, const char *v3_auth_digest,
dirinfo_type_t type, double weight)
{
- uint32_t a;
- tor_addr_t addr;
+ tor_addr_t ipv4_addr;
char *hostname=NULL;
dir_server_t *result;
if (!address) { /* The address is us; we should guess. */
- if (resolve_my_address(LOG_WARN, get_options(),
- &a, NULL, &hostname) < 0) {
+ if (!find_my_address(get_options(), AF_INET, LOG_WARN, &ipv4_addr,
+ NULL, &hostname)) {
log_warn(LD_CONFIG,
"Couldn't find a suitable address when adding ourself as a "
"trusted directory server.");
return NULL;
}
if (!hostname)
- hostname = tor_dup_ip(a);
+ hostname = tor_addr_to_str_dup(&ipv4_addr);
if (!hostname)
return NULL;
} else {
- if (tor_lookup_hostname(address, &a)) {
+ if (tor_addr_lookup(address, AF_INET, &ipv4_addr)) {
log_warn(LD_CONFIG,
"Unable to lookup address for directory server at '%s'",
address);
@@ -375,10 +398,9 @@ trusted_dir_server_new(const char *nickname, const char *address,
}
hostname = tor_strdup(address);
}
- tor_addr_from_ipv4h(&addr, a);
- result = dir_server_new(1, nickname, &addr, hostname,
- dir_port, or_port,
+ result = dir_server_new(1, nickname, &ipv4_addr, hostname,
+ ipv4_dirport, ipv4_orport,
ipv6_addrport,
digest,
v3_auth_digest, type, weight);
@@ -390,15 +412,13 @@ trusted_dir_server_new(const char *nickname, const char *address,
* <b>addr</b>:<b>or_port</b>/<b>dir_port</b>, with identity key digest
* <b>id_digest</b> */
dir_server_t *
-fallback_dir_server_new(const tor_addr_t *addr,
- uint16_t dir_port, uint16_t or_port,
+fallback_dir_server_new(const tor_addr_t *ipv4_addr,
+ uint16_t ipv4_dirport, uint16_t ipv4_orport,
const tor_addr_port_t *addrport_ipv6,
const char *id_digest, double weight)
{
- return dir_server_new(0, NULL, addr, NULL, dir_port, or_port,
- addrport_ipv6,
- id_digest,
- NULL, ALL_DIRINFO, weight);
+ return dir_server_new(0, NULL, ipv4_addr, NULL, ipv4_dirport, ipv4_orport,
+ addrport_ipv6, id_digest, NULL, ALL_DIRINFO, weight);
}
/** Add a directory server to the global list(s). */
diff --git a/src/feature/nodelist/dirlist.h b/src/feature/nodelist/dirlist.h
index 9201e76a9c..ae3debf4e5 100644
--- a/src/feature/nodelist/dirlist.h
+++ b/src/feature/nodelist/dirlist.h
@@ -25,8 +25,14 @@ int router_digest_is_fallback_dir(const char *digest);
MOCK_DECL(dir_server_t *, trusteddirserver_get_by_v3_auth_digest,
(const char *d));
-int router_digest_is_trusted_dir_type(const char *digest,
- dirinfo_type_t type);
+MOCK_DECL(int, router_digest_is_trusted_dir_type,
+ (const char *digest, dirinfo_type_t type));
+
+bool router_addr_is_trusted_dir_type(const tor_addr_t *addr,
+ dirinfo_type_t type);
+#define router_addr_is_trusted_dir(d) \
+ router_addr_is_trusted_dir_type((d), NO_DIRINFO)
+
#define router_digest_is_trusted_dir(d) \
router_digest_is_trusted_dir_type((d), NO_DIRINFO)
diff --git a/src/feature/nodelist/fmt_routerstatus.c b/src/feature/nodelist/fmt_routerstatus.c
index ca4a312639..252b2e61fe 100644
--- a/src/feature/nodelist/fmt_routerstatus.c
+++ b/src/feature/nodelist/fmt_routerstatus.c
@@ -53,7 +53,7 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version,
char digest64[BASE64_DIGEST_LEN+1];
smartlist_t *chunks = smartlist_new();
- const char *ip_str = fmt_addr32(rs->addr);
+ const char *ip_str = fmt_addr(&rs->ipv4_addr);
if (ip_str[0] == '\0')
goto err;
@@ -62,15 +62,15 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version,
digest_to_base64(digest64, rs->descriptor_digest);
smartlist_add_asprintf(chunks,
- "r %s %s %s%s%s %s %d %d\n",
+ "r %s %s %s%s%s %s %" PRIu16 " %" PRIu16 "\n",
rs->nickname,
identity64,
(format==NS_V3_CONSENSUS_MICRODESC)?"":digest64,
(format==NS_V3_CONSENSUS_MICRODESC)?"":" ",
published,
ip_str,
- (int)rs->or_port,
- (int)rs->dir_port);
+ rs->ipv4_orport,
+ rs->ipv4_dirport);
/* TODO: Maybe we want to pass in what we need to build the rest of
* this here, instead of in the caller. Then we could use the
diff --git a/src/feature/nodelist/microdesc.c b/src/feature/nodelist/microdesc.c
index cf7732b8dc..01dccd160b 100644
--- a/src/feature/nodelist/microdesc.c
+++ b/src/feature/nodelist/microdesc.c
@@ -129,8 +129,9 @@ microdesc_note_outdated_dirserver(const char *relay_digest)
tor_assert(outdated_dirserver_list);
/* If the list grows too big, clean it up */
- if (BUG(smartlist_len(outdated_dirserver_list) >
- TOO_MANY_OUTDATED_DIRSERVERS)) {
+ if (smartlist_len(outdated_dirserver_list) > TOO_MANY_OUTDATED_DIRSERVERS) {
+ log_info(LD_GENERAL,"Too many outdated directory servers (%d). Resetting.",
+ smartlist_len(outdated_dirserver_list));
microdesc_reset_outdated_dirservers_list();
}
diff --git a/src/feature/nodelist/networkstatus.c b/src/feature/nodelist/networkstatus.c
index e07d58c91c..80940e6092 100644
--- a/src/feature/nodelist/networkstatus.c
+++ b/src/feature/nodelist/networkstatus.c
@@ -471,8 +471,8 @@ networkstatus_check_document_signature(const networkstatus_t *consensus,
DIGEST_LEN))
return -1;
- if (authority_cert_is_blacklisted(cert)) {
- /* We implement blacklisting for authority signing keys by treating
+ if (authority_cert_is_denylisted(cert)) {
+ /* We implement denylisting for authority signing keys by treating
* all their signatures as always bad. That way we don't get into
* crazy loops of dropping and re-fetching signatures. */
log_warn(LD_DIR, "Ignoring a consensus signature made with deprecated"
@@ -608,25 +608,25 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus,
SMARTLIST_FOREACH(unrecognized, networkstatus_voter_info_t *, voter,
{
tor_log(severity, LD_DIR, "Consensus includes unrecognized authority "
- "'%s' at %s:%d (contact %s; identity %s)",
- voter->nickname, voter->address, (int)voter->dir_port,
+ "'%s' at %s:%" PRIu16 " (contact %s; identity %s)",
+ voter->nickname, voter->address, voter->ipv4_dirport,
voter->contact?voter->contact:"n/a",
hex_str(voter->identity_digest, DIGEST_LEN));
});
SMARTLIST_FOREACH(need_certs_from, networkstatus_voter_info_t *, voter,
{
tor_log(severity, LD_DIR, "Looks like we need to download a new "
- "certificate from authority '%s' at %s:%d (contact %s; "
- "identity %s)",
- voter->nickname, voter->address, (int)voter->dir_port,
+ "certificate from authority '%s' at %s:%" PRIu16
+ " (contact %s; identity %s)",
+ voter->nickname, voter->address, voter->ipv4_dirport,
voter->contact?voter->contact:"n/a",
hex_str(voter->identity_digest, DIGEST_LEN));
});
SMARTLIST_FOREACH(missing_authorities, dir_server_t *, ds,
{
tor_log(severity, LD_DIR, "Consensus does not include configured "
- "authority '%s' at %s:%d (identity %s)",
- ds->nickname, ds->address, (int)ds->dir_port,
+ "authority '%s' at %s:%" PRIu16 " (identity %s)",
+ ds->nickname, ds->address, ds->ipv4_dirport,
hex_str(ds->v3_identity_digest, DIGEST_LEN));
});
{
@@ -1594,9 +1594,9 @@ routerstatus_has_visibly_changed(const routerstatus_t *a,
return strcmp(a->nickname, b->nickname) ||
fast_memneq(a->descriptor_digest, b->descriptor_digest, DIGEST_LEN) ||
- a->addr != b->addr ||
- a->or_port != b->or_port ||
- a->dir_port != b->dir_port ||
+ !tor_addr_eq(&a->ipv4_addr, &b->ipv4_addr) ||
+ a->ipv4_orport != b->ipv4_orport ||
+ a->ipv4_dirport != b->ipv4_dirport ||
a->is_authority != b->is_authority ||
a->is_exit != b->is_exit ||
a->is_stable != b->is_stable ||
@@ -1670,7 +1670,35 @@ notify_before_networkstatus_changes(const networkstatus_t *old_c,
static void
notify_after_networkstatus_changes(void)
{
+ const networkstatus_t *c = networkstatus_get_latest_consensus();
+ const or_options_t *options = get_options();
+ const time_t now = approx_time();
+
scheduler_notify_networkstatus_changed();
+
+ /* The "current" consensus has just been set and it is a usable flavor so
+ * the first thing we need to do is recalculate the voting schedule static
+ * object so we can use the timings in there needed by some subsystems
+ * such as hidden service and shared random. */
+ dirauth_sched_recalculate_timing(options, now);
+ reschedule_dirvote(options);
+
+ nodelist_set_consensus(c);
+
+ update_consensus_networkstatus_fetch_time(now);
+
+ /* Change the cell EWMA settings */
+ cmux_ewma_set_options(options, c);
+
+ /* XXXX this call might be unnecessary here: can changing the
+ * current consensus really alter our view of any OR's rate limits? */
+ connection_or_update_token_buckets(get_connection_array(), options);
+
+ circuit_build_times_new_consensus_params(
+ get_circuit_build_times_mutable(), c);
+ channelpadding_new_consensus_params(c);
+ circpad_new_consensus_params(c);
+ router_new_consensus_params(c);
}
/** Copy all the ancillary information (like router download status and so on)
@@ -2115,29 +2143,6 @@ networkstatus_set_current_consensus(const char *consensus,
/* Notify that we just changed the consensus so the current global value
* can be looked at. */
notify_after_networkstatus_changes();
-
- /* The "current" consensus has just been set and it is a usable flavor so
- * the first thing we need to do is recalculate the voting schedule static
- * object so we can use the timings in there needed by some subsystems
- * such as hidden service and shared random. */
- dirauth_sched_recalculate_timing(options, now);
- reschedule_dirvote(options);
-
- nodelist_set_consensus(c);
-
- update_consensus_networkstatus_fetch_time(now);
-
- /* Change the cell EWMA settings */
- cmux_ewma_set_options(options, c);
-
- /* XXXX this call might be unnecessary here: can changing the
- * current consensus really alter our view of any OR's rate limits? */
- connection_or_update_token_buckets(get_connection_array(), options);
-
- circuit_build_times_new_consensus_params(
- get_circuit_build_times_mutable(), c);
- channelpadding_new_consensus_params(c);
- circpad_new_consensus_params(c);
}
/* Reset the failure count only if this consensus is actually valid. */
@@ -2387,10 +2392,10 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
memcpy(rs->identity_digest, node->identity, DIGEST_LEN);
memcpy(rs->descriptor_digest, ri->cache_info.signed_descriptor_digest,
DIGEST_LEN);
- rs->addr = ri->addr;
+ tor_addr_copy(&rs->ipv4_addr, &ri->ipv4_addr);
strlcpy(rs->nickname, ri->nickname, sizeof(rs->nickname));
- rs->or_port = ri->or_port;
- rs->dir_port = ri->dir_port;
+ rs->ipv4_orport = ri->ipv4_orport;
+ rs->ipv4_dirport = ri->ipv4_dirport;
rs->is_v2_dir = ri->supports_tunnelled_dir_requests;
tor_addr_copy(&rs->ipv6_addr, &ri->ipv6_addr);
@@ -2439,7 +2444,12 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now)
return answer;
}
-/* DOCDOC get_net_param_from_list */
+/**
+ * Search through a smartlist of "key=int32" strings for a value beginning
+ * with "param_name=". If one is found, clip it to be between min_val and
+ * max_val inclusive and return it. If one is not found, return
+ * default_val.
+ ***/
static int32_t
get_net_param_from_list(smartlist_t *net_params, const char *param_name,
int32_t default_val, int32_t min_val, int32_t max_val)
@@ -2713,6 +2723,13 @@ networkstatus_check_required_protocols(const networkstatus_t *ns,
const bool consensus_postdates_this_release =
ns->valid_after >= tor_get_approx_release_date();
+ if (! consensus_postdates_this_release) {
+ // We can't meaningfully warn about this case: This consensus is from
+ // before we were released, so whatever is says about required or
+ // recommended versions may no longer be true.
+ return 0;
+ }
+
tor_assert(warning_out);
if (client_mode) {
@@ -2730,7 +2747,7 @@ networkstatus_check_required_protocols(const networkstatus_t *ns,
"%s on the Tor network. The missing protocols are: %s",
func, missing);
tor_free(missing);
- return consensus_postdates_this_release ? 1 : 0;
+ return 1;
}
if (! protover_all_supported(recommended, &missing)) {
diff --git a/src/feature/nodelist/networkstatus_voter_info_st.h b/src/feature/nodelist/networkstatus_voter_info_st.h
index b4d0b1dd17..a0fba2e1b5 100644
--- a/src/feature/nodelist/networkstatus_voter_info_st.h
+++ b/src/feature/nodelist/networkstatus_voter_info_st.h
@@ -21,9 +21,9 @@ struct networkstatus_voter_info_t {
* consensuses, we treat legacy keys as additional signers. */
char legacy_id_digest[DIGEST_LEN];
char *address; /**< Address of this voter, in string format. */
- uint32_t addr; /**< Address of this voter, in IPv4, in host order. */
- uint16_t dir_port; /**< Directory port of this voter */
- uint16_t or_port; /**< OR port of this voter */
+ tor_addr_t ipv4_addr;
+ uint16_t ipv4_dirport; /**< Directory port of this voter */
+ uint16_t ipv4_orport; /**< OR port of this voter */
char *contact; /**< Contact information for this voter. */
char vote_digest[DIGEST_LEN]; /**< Digest of this voter's vote, as signed. */
diff --git a/src/feature/nodelist/node_select.c b/src/feature/nodelist/node_select.c
index e831248413..ecb70aef14 100644
--- a/src/feature/nodelist/node_select.c
+++ b/src/feature/nodelist/node_select.c
@@ -141,7 +141,7 @@ router_pick_dirserver_generic(smartlist_t *sourcelist,
#define RETRY_ALTERNATE_IP_VERSION(retry_label) \
STMT_BEGIN \
if (result == NULL && try_ip_pref && options->ClientUseIPv4 \
- && fascist_firewall_use_ipv6(options) && !server_mode(options) \
+ && reachable_addr_use_ipv6(options) && !server_mode(options) \
&& !n_busy) { \
n_excluded = 0; \
n_busy = 0; \
@@ -212,18 +212,20 @@ router_picked_poor_directory_log(const routerstatus_t *rs)
log_debug(LD_DIR, "Wanted to make an outgoing directory connection, but "
"we couldn't find a directory that fit our criteria. "
"Perhaps we will succeed next time with less strict criteria.");
- } else if (!fascist_firewall_allows_rs(rs, FIREWALL_OR_CONNECTION, 1)
- && !fascist_firewall_allows_rs(rs, FIREWALL_DIR_CONNECTION, 1)
+ } else if (!reachable_addr_allows_rs(rs, FIREWALL_OR_CONNECTION, 1)
+ && !reachable_addr_allows_rs(rs, FIREWALL_DIR_CONNECTION, 1)
) {
/* This is rare, and might be interesting to users trying to diagnose
* connection issues on dual-stack machines. */
+ char *ipv4_str = tor_addr_to_str_dup(&rs->ipv4_addr);
log_info(LD_DIR, "Selected a directory %s with non-preferred OR and Dir "
"addresses for launching an outgoing connection: "
"IPv4 %s OR %d Dir %d IPv6 %s OR %d Dir %d",
routerstatus_describe(rs),
- fmt_addr32(rs->addr), rs->or_port,
- rs->dir_port, fmt_addr(&rs->ipv6_addr),
- rs->ipv6_orport, rs->dir_port);
+ ipv4_str, rs->ipv4_orport,
+ rs->ipv4_dirport, fmt_addr(&rs->ipv6_addr),
+ rs->ipv6_orport, rs->ipv4_dirport);
+ tor_free(ipv4_str);
}
}
@@ -266,7 +268,7 @@ router_is_already_dir_fetching(const tor_addr_port_t *ap, int serverdesc,
* If so, return 1, if not, return 0.
*/
static int
-router_is_already_dir_fetching_(uint32_t ipv4_addr,
+router_is_already_dir_fetching_(const tor_addr_t *ipv4_addr,
const tor_addr_t *ipv6_addr,
uint16_t dir_port,
int serverdesc,
@@ -275,7 +277,7 @@ router_is_already_dir_fetching_(uint32_t ipv4_addr,
tor_addr_port_t ipv4_dir_ap, ipv6_dir_ap;
/* Assume IPv6 DirPort is the same as IPv4 DirPort */
- tor_addr_from_ipv4h(&ipv4_dir_ap.addr, ipv4_addr);
+ tor_addr_copy(&ipv4_dir_ap.addr, ipv4_addr);
ipv4_dir_ap.port = dir_port;
tor_addr_copy(&ipv6_dir_ap.addr, ipv6_addr);
ipv6_dir_ap.port = dir_port;
@@ -321,8 +323,12 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags,
overloaded_direct = smartlist_new();
overloaded_tunnel = smartlist_new();
- 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 skip_or_fw = router_or_conn_should_skip_reachable_address_check(
+ options,
+ try_ip_pref);
+ const int skip_dir_fw = router_dir_conn_should_skip_reachable_address_check(
+ options,
+ try_ip_pref);
const int must_have_or = dirclient_must_use_begindir(options);
/* Find all the running dirservers we know about. */
@@ -348,9 +354,9 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags,
continue;
}
- if (router_is_already_dir_fetching_(status->addr,
+ if (router_is_already_dir_fetching_(&status->ipv4_addr,
&status->ipv6_addr,
- status->dir_port,
+ status->ipv4_dirport,
no_serverdesc_fetching,
no_microdesc_fetching)) {
++n_busy;
@@ -368,12 +374,12 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags,
* we try routers that only have one address both times.)
*/
if (!fascistfirewall || skip_or_fw ||
- fascist_firewall_allows_node(node, FIREWALL_OR_CONNECTION,
+ reachable_addr_allows_node(node, FIREWALL_OR_CONNECTION,
try_ip_pref))
smartlist_add(is_trusted ? trusted_tunnel :
is_overloaded ? overloaded_tunnel : tunnel, (void*)node);
else if (!must_have_or && (skip_dir_fw ||
- fascist_firewall_allows_node(node, FIREWALL_DIR_CONNECTION,
+ reachable_addr_allows_node(node, FIREWALL_DIR_CONNECTION,
try_ip_pref)))
smartlist_add(is_trusted ? trusted_direct :
is_overloaded ? overloaded_direct : direct, (void*)node);
@@ -926,64 +932,67 @@ nodelist_subtract(smartlist_t *sl, const smartlist_t *excluded)
bitarray_free(excluded_idx);
}
-/** Return a random running node from the nodelist. Never
- * pick a node that is in
- * <b>excludedsmartlist</b>, or which matches <b>excludedset</b>,
- * even if they are the only nodes available.
- * If <b>CRN_NEED_UPTIME</b> is set in flags and any router has more than
- * a minimum uptime, return one of those.
- * If <b>CRN_NEED_CAPACITY</b> is set in flags, weight your choice by the
- * advertised capacity of each router.
- * If <b>CRN_NEED_GUARD</b> is set in flags, consider only Guard routers.
- * If <b>CRN_WEIGHT_AS_EXIT</b> is set in flags, we weight bandwidths as if
- * picking an exit node, otherwise we weight bandwidths for picking a relay
- * node (that is, possibly discounting exit nodes).
- * If <b>CRN_NEED_DESC</b> is set in flags, we only consider nodes that
- * have a routerinfo or microdescriptor -- that is, enough info to be
- * used to build a circuit.
- * If <b>CRN_PREF_ADDR</b> is set in flags, we only consider nodes that
- * have an address that is preferred by the ClientPreferIPv6ORPort setting
- * (regardless of this flag, we exclude nodes that aren't allowed by the
- * firewall, including ClientUseIPv4 0 and fascist_firewall_use_ipv6() == 0).
+/* Node selection helper for router_choose_random_node().
+ *
+ * Populates a node list based on <b>flags</b>, ignoring nodes in
+ * <b>excludednodes</b> and <b>excludedset</b>. Chooses the node based on
+ * <b>rule</b>. */
+static const node_t *
+router_choose_random_node_helper(smartlist_t *excludednodes,
+ routerset_t *excludedset,
+ router_crn_flags_t flags,
+ bandwidth_weight_rule_t rule)
+{
+ smartlist_t *sl=smartlist_new();
+ const node_t *choice = NULL;
+
+ router_add_running_nodes_to_smartlist(sl, flags);
+ log_debug(LD_CIRC,
+ "We found %d running nodes.",
+ smartlist_len(sl));
+
+ nodelist_subtract(sl, excludednodes);
+
+ if (excludedset) {
+ routerset_subtract_nodes(sl,excludedset);
+ log_debug(LD_CIRC,
+ "We removed excludedset, leaving %d nodes.",
+ smartlist_len(sl));
+ }
+
+ // Always weight by bandwidth
+ choice = node_sl_choose_by_bandwidth(sl, rule);
+
+ smartlist_free(sl);
+
+ return choice;
+}
+
+/** Return a random running node from the nodelist. Never pick a node that is
+ * in <b>excludedsmartlist</b>, or which matches <b>excludedset</b>, even if
+ * they are the only nodes available.
+ *
+ * <b>flags</b> is a set of CRN_* flags, see
+ * router_add_running_nodes_to_smartlist() for details.
*/
const node_t *
router_choose_random_node(smartlist_t *excludedsmartlist,
routerset_t *excludedset,
router_crn_flags_t flags)
-{ /* XXXX MOVE */
- const int need_uptime = (flags & CRN_NEED_UPTIME) != 0;
- const int need_capacity = (flags & CRN_NEED_CAPACITY) != 0;
- const int need_guard = (flags & CRN_NEED_GUARD) != 0;
- const int weight_for_exit = (flags & CRN_WEIGHT_AS_EXIT) != 0;
- const int need_desc = (flags & CRN_NEED_DESC) != 0;
- const int pref_addr = (flags & CRN_PREF_ADDR) != 0;
- const int direct_conn = (flags & CRN_DIRECT_CONN) != 0;
- const int rendezvous_v3 = (flags & CRN_RENDEZVOUS_V3) != 0;
-
- const smartlist_t *node_list = nodelist_get_list();
- smartlist_t *sl=smartlist_new(),
- *excludednodes=smartlist_new();
+{
+ /* A limited set of flags, used for fallback node selection.
+ */
+ const bool need_uptime = (flags & CRN_NEED_UPTIME) != 0;
+ const bool need_capacity = (flags & CRN_NEED_CAPACITY) != 0;
+ const bool need_guard = (flags & CRN_NEED_GUARD) != 0;
+ const bool pref_addr = (flags & CRN_PREF_ADDR) != 0;
+
+ smartlist_t *excludednodes=smartlist_new();
const node_t *choice = NULL;
const routerinfo_t *r;
bandwidth_weight_rule_t rule;
- tor_assert(!(weight_for_exit && need_guard));
- rule = weight_for_exit ? WEIGHT_FOR_EXIT :
- (need_guard ? WEIGHT_FOR_GUARD : WEIGHT_FOR_MID);
-
- SMARTLIST_FOREACH_BEGIN(node_list, const node_t *, node) {
- if (node_allows_single_hop_exits(node)) {
- /* Exclude relays that allow single hop exit circuits. This is an
- * obsolete option since 0.2.9.2-alpha and done by default in
- * 0.3.1.0-alpha. */
- smartlist_add(excludednodes, (node_t*)node);
- } else if (rendezvous_v3 &&
- !node_supports_v3_rendezvous_point(node)) {
- /* Exclude relays that do not support to rendezvous for a hidden service
- * version 3. */
- smartlist_add(excludednodes, (node_t*)node);
- }
- } SMARTLIST_FOREACH_END(node);
+ rule = (need_guard ? WEIGHT_FOR_GUARD : WEIGHT_FOR_MID);
/* If the node_t is not found we won't be to exclude ourself but we
* won't be able to pick ourself in router_choose_random_node() so
@@ -991,41 +1000,30 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
if ((r = router_get_my_routerinfo()))
routerlist_add_node_and_family(excludednodes, r);
- router_add_running_nodes_to_smartlist(sl, need_uptime, need_capacity,
- need_guard, need_desc, pref_addr,
- direct_conn);
- log_debug(LD_CIRC,
- "We found %d running nodes.",
- smartlist_len(sl));
-
if (excludedsmartlist) {
smartlist_add_all(excludednodes, excludedsmartlist);
}
- nodelist_subtract(sl, excludednodes);
- if (excludedset) {
- routerset_subtract_nodes(sl,excludedset);
- log_debug(LD_CIRC,
- "We removed excludedset, leaving %d nodes.",
- smartlist_len(sl));
- }
+ choice = router_choose_random_node_helper(excludednodes,
+ excludedset,
+ flags,
+ rule);
- // Always weight by bandwidth
- choice = node_sl_choose_by_bandwidth(sl, rule);
-
- smartlist_free(sl);
if (!choice && (need_uptime || need_capacity || need_guard || pref_addr)) {
- /* try once more -- recurse but with fewer restrictions. */
+ /* try once more, with fewer restrictions. */
log_info(LD_CIRC,
- "We couldn't find any live%s%s%s routers; falling back "
+ "We couldn't find any live%s%s%s%s routers; falling back "
"to list of all routers.",
need_capacity?", fast":"",
need_uptime?", stable":"",
- need_guard?", guard":"");
+ need_guard?", guard":"",
+ pref_addr?", preferred address":"");
flags &= ~ (CRN_NEED_UPTIME|CRN_NEED_CAPACITY|CRN_NEED_GUARD|
CRN_PREF_ADDR);
- choice = router_choose_random_node(
- excludedsmartlist, excludedset, flags);
+ choice = router_choose_random_node_helper(excludednodes,
+ excludedset,
+ flags,
+ rule);
}
smartlist_free(excludednodes);
if (!choice) {
@@ -1120,8 +1118,12 @@ router_pick_trusteddirserver_impl(const smartlist_t *sourcelist,
overloaded_direct = smartlist_new();
overloaded_tunnel = smartlist_new();
- 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 skip_or_fw = router_or_conn_should_skip_reachable_address_check(
+ options,
+ try_ip_pref);
+ const int skip_dir_fw = router_dir_conn_should_skip_reachable_address_check(
+ options,
+ try_ip_pref);
const int must_have_or = dirclient_must_use_begindir(options);
SMARTLIST_FOREACH_BEGIN(sourcelist, const dir_server_t *, d)
@@ -1143,9 +1145,9 @@ router_pick_trusteddirserver_impl(const smartlist_t *sourcelist,
continue;
}
- if (router_is_already_dir_fetching_(d->addr,
+ if (router_is_already_dir_fetching_(&d->ipv4_addr,
&d->ipv6_addr,
- d->dir_port,
+ d->ipv4_dirport,
no_serverdesc_fetching,
no_microdesc_fetching)) {
++n_busy;
@@ -1160,11 +1162,11 @@ router_pick_trusteddirserver_impl(const smartlist_t *sourcelist,
* we try routers that only have one address both times.)
*/
if (!fascistfirewall || skip_or_fw ||
- fascist_firewall_allows_dir_server(d, FIREWALL_OR_CONNECTION,
+ reachable_addr_allows_dir_server(d, FIREWALL_OR_CONNECTION,
try_ip_pref))
smartlist_add(is_overloaded ? overloaded_tunnel : tunnel, (void*)d);
else if (!must_have_or && (skip_dir_fw ||
- fascist_firewall_allows_dir_server(d, FIREWALL_DIR_CONNECTION,
+ reachable_addr_allows_dir_server(d, FIREWALL_DIR_CONNECTION,
try_ip_pref)))
smartlist_add(is_overloaded ? overloaded_direct : direct, (void*)d);
}
diff --git a/src/feature/nodelist/node_select.h b/src/feature/nodelist/node_select.h
index 2e67f990f6..1776d8ea1a 100644
--- a/src/feature/nodelist/node_select.h
+++ b/src/feature/nodelist/node_select.h
@@ -14,20 +14,26 @@
/** Flags to be passed to control router_choose_random_node() to indicate what
* kind of nodes to pick according to what algorithm. */
typedef enum router_crn_flags_t {
+ /* Try to choose stable nodes. */
CRN_NEED_UPTIME = 1<<0,
+ /* Try to choose nodes with a reasonable amount of bandwidth. */
CRN_NEED_CAPACITY = 1<<1,
- CRN_NEED_GUARD = 1<<2,
- /* XXXX not used, apparently. */
- CRN_WEIGHT_AS_EXIT = 1<<5,
- CRN_NEED_DESC = 1<<6,
- /* On clients, only provide nodes that satisfy ClientPreferIPv6OR */
- CRN_PREF_ADDR = 1<<7,
+ /* Only choose nodes if we have downloaded their descriptor or
+ * microdescriptor. */
+ CRN_NEED_DESC = 1<<2,
+ /* Choose nodes that can be used as Guard relays. */
+ CRN_NEED_GUARD = 1<<3,
/* On clients, only provide nodes that we can connect to directly, based on
- * our firewall rules */
- CRN_DIRECT_CONN = 1<<8,
- /* On clients, only provide nodes with HSRend >= 2 protocol version which
- * is required for hidden service version >= 3. */
- CRN_RENDEZVOUS_V3 = 1<<9,
+ * our firewall rules. */
+ CRN_DIRECT_CONN = 1<<4,
+ /* On clients, if choosing a node for a direct connection, only provide
+ * nodes that satisfy ClientPreferIPv6OR. */
+ CRN_PREF_ADDR = 1<<5,
+ /* On clients, only provide nodes with HSRend=2 protocol version which
+ * is required for hidden service version 3. */
+ CRN_RENDEZVOUS_V3 = 1<<6,
+ /* On clients, only provide nodes that can initiate IPv6 extends. */
+ CRN_INITIATE_IPV6_EXTEND = 1<<7,
} router_crn_flags_t;
/** Possible ways to weight routers when choosing one randomly. See
diff --git a/src/feature/nodelist/node_st.h b/src/feature/nodelist/node_st.h
index b1ec4db202..3769f9dc84 100644
--- a/src/feature/nodelist/node_st.h
+++ b/src/feature/nodelist/node_st.h
@@ -84,12 +84,11 @@ struct node_t {
/* Local info: derived. */
- /** True if the IPv6 OR port is preferred over the IPv4 OR port.
- * XX/teor - can this become out of date if the torrc changes? */
+ /** True if the IPv6 OR port is preferred over the IPv4 OR port. */
unsigned int ipv6_preferred:1;
/** According to the geoip db what country is this router in? */
- /* XXXprop186 what is this suppose to mean with multiple OR ports? */
+ /* IPv6: what is this supposed to mean with multiple OR ports? */
country_t country;
/* The below items are used only by authdirservers for
diff --git a/src/feature/nodelist/nodelist.c b/src/feature/nodelist/nodelist.c
index 7ebc4f5fda..03b158e68d 100644
--- a/src/feature/nodelist/nodelist.c
+++ b/src/feature/nodelist/nodelist.c
@@ -127,7 +127,7 @@ typedef struct nodelist_t {
*
* Whenever a node's routerinfo or microdescriptor is about to change,
* you should remove it from this map with node_remove_from_ed25519_map().
- * Whenever a node's routerinfo or microdescriptor has just chaned,
+ * Whenever a node's routerinfo or microdescriptor has just changed,
* you should add it to this map with node_add_to_ed25519_map().
*/
HT_HEAD(nodelist_ed_map, node_t) nodes_by_ed_id;
@@ -451,8 +451,6 @@ node_addrs_changed(node_t *node)
static void
node_add_to_address_set(const node_t *node)
{
- tor_addr_t tmp_addr;
-
if (!the_nodelist ||
!the_nodelist->node_addrs || !the_nodelist->reentry_set)
return;
@@ -465,19 +463,17 @@ node_add_to_address_set(const node_t *node)
* test succeeds and thus the 0 value for the DirPort. */
if (node->rs) {
- if (node->rs->addr) {
- tor_addr_from_ipv4h(&tmp_addr, node->rs->addr);
- nodelist_add_addr_to_address_set(&tmp_addr, node->rs->or_port, 0);
- }
+ if (!tor_addr_is_null(&node->rs->ipv4_addr))
+ nodelist_add_addr_to_address_set(&node->rs->ipv4_addr,
+ node->rs->ipv4_orport, 0);
if (!tor_addr_is_null(&node->rs->ipv6_addr))
nodelist_add_addr_to_address_set(&node->rs->ipv6_addr,
node->rs->ipv6_orport, 0);
}
if (node->ri) {
- if (node->ri->addr) {
- tor_addr_from_ipv4h(&tmp_addr, node->ri->addr);
- nodelist_add_addr_to_address_set(&tmp_addr, node->ri->or_port, 0);
- }
+ if (!tor_addr_is_null(&node->ri->ipv4_addr))
+ nodelist_add_addr_to_address_set(&node->ri->ipv4_addr,
+ node->ri->ipv4_orport, 0);
if (!tor_addr_is_null(&node->ri->ipv6_addr))
nodelist_add_addr_to_address_set(&node->ri->ipv6_addr,
node->ri->ipv6_orport, 0);
@@ -531,7 +527,7 @@ nodelist_add_addr_to_address_set(const tor_addr_t *addr,
uint16_t or_port, uint16_t dir_port)
{
if (BUG(!addr) || tor_addr_is_null(addr) ||
- (!tor_addr_is_v4(addr) && tor_addr_family(addr) != AF_INET6) ||
+ (!tor_addr_is_v4(addr) && !tor_addr_is_v6(addr)) ||
!the_nodelist || !the_nodelist->node_addrs ||
!the_nodelist->reentry_set) {
return;
@@ -691,7 +687,7 @@ get_estimated_address_per_node, (void))
* and grab microdescriptors into nodes as appropriate.
*/
void
-nodelist_set_consensus(networkstatus_t *ns)
+nodelist_set_consensus(const networkstatus_t *ns)
{
const or_options_t *options = get_options();
int authdir = authdir_mode_v3(options);
@@ -749,7 +745,7 @@ nodelist_set_consensus(networkstatus_t *ns)
node->is_bad_exit = rs->is_bad_exit;
node->is_hs_dir = rs->is_hs_dir;
node->ipv6_preferred = 0;
- if (fascist_firewall_prefer_ipv6_orport(options) &&
+ if (reachable_addr_prefer_ipv6_orport(options) &&
(tor_addr_is_null(&rs->ipv6_addr) == 0 ||
(node->md && tor_addr_is_null(&node->md->ipv6_addr) == 0)))
node->ipv6_preferred = 1;
@@ -1028,7 +1024,7 @@ nodelist_assert_ok(void)
/** Ensure that the nodelist has been created with the most recent consensus.
* If that's not the case, make it so. */
void
-nodelist_ensure_freshness(networkstatus_t *ns)
+nodelist_ensure_freshness(const networkstatus_t *ns)
{
tor_assert(ns);
@@ -1209,7 +1205,7 @@ node_ed25519_id_matches(const node_t *node, const ed25519_public_key_t *id)
/** Dummy object that should be unreturnable. Used to ensure that
* node_get_protover_summary_flags() always returns non-NULL. */
static const protover_summary_flags_t zero_protover_flags = {
- 0,0,0,0,0,0,0,0,0
+ 0,0,0,0,0,0,0,0,0,0,0,0
};
/** Return the protover_summary_flags for a given node. */
@@ -1234,9 +1230,9 @@ node_get_protover_summary_flags(const node_t *node)
* by ed25519 ID during the link handshake. If <b>compatible_with_us</b>,
* it needs to be using a link authentication method that we understand.
* If not, any plausible link authentication method will do. */
-MOCK_IMPL(int,
+MOCK_IMPL(bool,
node_supports_ed25519_link_authentication,(const node_t *node,
- int compatible_with_us))
+ bool compatible_with_us))
{
if (! node_get_ed25519_id(node))
return 0;
@@ -1251,7 +1247,7 @@ node_supports_ed25519_link_authentication,(const node_t *node,
/** Return true iff <b>node</b> supports the hidden service directory version
* 3 protocol (proposal 224). */
-int
+bool
node_supports_v3_hsdir(const node_t *node)
{
tor_assert(node);
@@ -1261,7 +1257,7 @@ node_supports_v3_hsdir(const node_t *node)
/** Return true iff <b>node</b> supports ed25519 authentication as an hidden
* service introduction point.*/
-int
+bool
node_supports_ed25519_hs_intro(const node_t *node)
{
tor_assert(node);
@@ -1269,9 +1265,24 @@ node_supports_ed25519_hs_intro(const node_t *node)
return node_get_protover_summary_flags(node)->supports_ed25519_hs_intro;
}
+/** Return true iff <b>node</b> can be a rendezvous point for hidden
+ * service version 3 (HSRend=2). */
+bool
+node_supports_v3_rendezvous_point(const node_t *node)
+{
+ tor_assert(node);
+
+ /* We can't use a v3 rendezvous point without the curve25519 onion pk. */
+ if (!node_get_curve25519_onion_key(node)) {
+ return 0;
+ }
+
+ return node_get_protover_summary_flags(node)->supports_v3_rendezvous_point;
+}
+
/** Return true iff <b>node</b> supports the DoS ESTABLISH_INTRO cell
- * extenstion. */
-int
+ * extension. */
+bool
node_supports_establish_intro_dos_extension(const node_t *node)
{
tor_assert(node);
@@ -1280,19 +1291,54 @@ node_supports_establish_intro_dos_extension(const node_t *node)
supports_establish_intro_dos_extension;
}
-/** Return true iff <b>node</b> supports to be a rendezvous point for hidden
- * service version 3 (HSRend=2). */
-int
-node_supports_v3_rendezvous_point(const node_t *node)
+/** Return true iff <b>node</b> can initiate IPv6 extends (Relay=3).
+ *
+ * This check should only be performed by client path selection code.
+ *
+ * Extending relays should check their own IPv6 support using
+ * router_can_extend_over_ipv6(). Like other extends, they should not verify
+ * the link specifiers in the extend cell against the consensus, because it
+ * may be out of date. */
+bool
+node_supports_initiating_ipv6_extends(const node_t *node)
{
tor_assert(node);
- /* We can't use a v3 rendezvous point without the curve25519 onion pk. */
- if (!node_get_curve25519_onion_key(node)) {
+ /* Relays can't initiate an IPv6 extend, unless they have an IPv6 ORPort. */
+ if (!node_has_ipv6_orport(node)) {
return 0;
}
- return node_get_protover_summary_flags(node)->supports_v3_rendezvous_point;
+ /* Initiating relays also need to support the relevant protocol version. */
+ return
+ node_get_protover_summary_flags(node)->supports_initiating_ipv6_extends;
+}
+
+/** Return true iff <b>node</b> can accept IPv6 extends (Relay=2 or Relay=3)
+ * from other relays. If <b>need_canonical_ipv6_conn</b> is true, also check
+ * if the relay supports canonical IPv6 connections (Relay=3 only).
+ *
+ * This check should only be performed by client path selection code.
+ */
+bool
+node_supports_accepting_ipv6_extends(const node_t *node,
+ bool need_canonical_ipv6_conn)
+{
+ tor_assert(node);
+
+ /* Relays can't accept an IPv6 extend, unless they have an IPv6 ORPort. */
+ if (!node_has_ipv6_orport(node)) {
+ return 0;
+ }
+
+ /* Accepting relays also need to support the relevant protocol version. */
+ if (need_canonical_ipv6_conn) {
+ return
+ node_get_protover_summary_flags(node)->supports_canonical_ipv6_conns;
+ } else {
+ return
+ node_get_protover_summary_flags(node)->supports_accepting_ipv6_extends;
+ }
}
/** Return the RSA ID key's SHA1 digest for the provided node. */
@@ -1567,32 +1613,14 @@ node_exit_policy_is_exact(const node_t *node, sa_family_t family)
* "addr" is an IPv4 host-order address and port_field is a uint16_t.
* r is typically a routerinfo_t or routerstatus_t.
*/
-#define SL_ADD_NEW_IPV4_AP(r, port_field, sl, valid) \
- STMT_BEGIN \
- if (tor_addr_port_is_valid_ipv4h((r)->addr, (r)->port_field, 0)) { \
- valid = 1; \
- tor_addr_port_t *ap = tor_malloc(sizeof(tor_addr_port_t)); \
- tor_addr_from_ipv4h(&ap->addr, (r)->addr); \
- ap->port = (r)->port_field; \
- smartlist_add((sl), ap); \
- } \
- STMT_END
-
-/* Check if the "addr" and port_field fields from r are a valid non-listening
- * address/port. If so, set valid to true and add a newly allocated
- * tor_addr_port_t containing "addr" and port_field to sl.
- * "addr" is a tor_addr_t and port_field is a uint16_t.
- * r is typically a routerinfo_t or routerstatus_t.
- */
-#define SL_ADD_NEW_IPV6_AP(r, port_field, sl, valid) \
- STMT_BEGIN \
- if (tor_addr_port_is_valid(&(r)->ipv6_addr, (r)->port_field, 0)) { \
- valid = 1; \
- tor_addr_port_t *ap = tor_malloc(sizeof(tor_addr_port_t)); \
- tor_addr_copy(&ap->addr, &(r)->ipv6_addr); \
- ap->port = (r)->port_field; \
- smartlist_add((sl), ap); \
- } \
+#define SL_ADD_NEW_AP(r, addr_field, port_field, sl, valid) \
+ STMT_BEGIN \
+ if (tor_addr_port_is_valid(&(r)->addr_field, (r)->port_field, 0)) { \
+ valid = 1; \
+ tor_addr_port_t *ap = tor_addr_port_new(&(r)->addr_field, \
+ (r)->port_field); \
+ smartlist_add((sl), ap); \
+ } \
STMT_END
/** Return list of tor_addr_port_t with all OR ports (in the sense IP
@@ -1611,33 +1639,32 @@ node_get_all_orports(const node_t *node)
/* Find a valid IPv4 address and port */
if (node->ri != NULL) {
- SL_ADD_NEW_IPV4_AP(node->ri, or_port, sl, valid);
+ SL_ADD_NEW_AP(node->ri, ipv4_addr, ipv4_orport, sl, valid);
}
/* If we didn't find a valid address/port in the ri, try the rs */
if (!valid && node->rs != NULL) {
- SL_ADD_NEW_IPV4_AP(node->rs, or_port, sl, valid);
+ SL_ADD_NEW_AP(node->rs, ipv4_addr, ipv4_orport, sl, valid);
}
/* Find a valid IPv6 address and port */
valid = 0;
if (node->ri != NULL) {
- SL_ADD_NEW_IPV6_AP(node->ri, ipv6_orport, sl, valid);
+ SL_ADD_NEW_AP(node->ri, ipv6_addr, ipv6_orport, sl, valid);
}
if (!valid && node->rs != NULL) {
- SL_ADD_NEW_IPV6_AP(node->rs, ipv6_orport, sl, valid);
+ SL_ADD_NEW_AP(node->rs, ipv6_addr, ipv6_orport, sl, valid);
}
if (!valid && node->md != NULL) {
- SL_ADD_NEW_IPV6_AP(node->md, ipv6_orport, sl, valid);
+ SL_ADD_NEW_AP(node->md, ipv6_addr, ipv6_orport, sl, valid);
}
return sl;
}
-#undef SL_ADD_NEW_IPV4_AP
-#undef SL_ADD_NEW_IPV6_AP
+#undef SL_ADD_NEW_AP
/** Wrapper around node_get_prim_orport for backward
compatibility. */
@@ -1649,21 +1676,20 @@ node_get_addr(const node_t *node, tor_addr_t *addr_out)
tor_addr_copy(addr_out, &ap.addr);
}
-/** Return the host-order IPv4 address for <b>node</b>, or 0 if it doesn't
- * seem to have one. */
-uint32_t
-node_get_prim_addr_ipv4h(const node_t *node)
+/** Return the IPv4 address for <b>node</b>, or NULL if none found. */
+static const tor_addr_t *
+node_get_prim_addr_ipv4(const node_t *node)
{
/* Don't check the ORPort or DirPort, as this function isn't port-specific,
* and the node might have a valid IPv4 address, yet have a zero
* ORPort or DirPort.
*/
- if (node->ri && tor_addr_is_valid_ipv4h(node->ri->addr, 0)) {
- return node->ri->addr;
- } else if (node->rs && tor_addr_is_valid_ipv4h(node->rs->addr, 0)) {
- return node->rs->addr;
+ if (node->ri && tor_addr_is_valid(&node->ri->ipv4_addr, 0)) {
+ return &node->ri->ipv4_addr;
+ } else if (node->rs && tor_addr_is_valid(&node->rs->ipv4_addr, 0)) {
+ return &node->rs->ipv4_addr;
}
- return 0;
+ return NULL;
}
/** Copy a string representation of an IP address for <b>node</b> into
@@ -1671,12 +1697,10 @@ node_get_prim_addr_ipv4h(const node_t *node)
void
node_get_address_string(const node_t *node, char *buf, size_t len)
{
- uint32_t ipv4_addr = node_get_prim_addr_ipv4h(node);
+ const tor_addr_t *ipv4_addr = node_get_prim_addr_ipv4(node);
- if (tor_addr_is_valid_ipv4h(ipv4_addr, 0)) {
- tor_addr_t addr;
- tor_addr_from_ipv4h(&addr, ipv4_addr);
- tor_addr_to_str(buf, &addr, len, 0);
+ if (ipv4_addr) {
+ tor_addr_to_str(buf, ipv4_addr, len, 0);
} else if (len > 0) {
buf[0] = '\0';
}
@@ -1761,7 +1785,7 @@ node_has_ipv6_dirport(const node_t *node)
* ii) the router has no IPv4 OR address.
*
* If you don't have a node, consider looking it up.
- * If there is no node, use fascist_firewall_prefer_ipv6_orport().
+ * If there is no node, use reachable_addr_prefer_ipv6_orport().
*/
int
node_ipv6_or_preferred(const node_t *node)
@@ -1771,10 +1795,10 @@ node_ipv6_or_preferred(const node_t *node)
node_assert_ok(node);
/* XX/teor - node->ipv6_preferred is set from
- * fascist_firewall_prefer_ipv6_orport() each time the consensus is loaded.
+ * reachable_addr_prefer_ipv6_orport() each time the consensus is loaded.
*/
node_get_prim_orport(node, &ipv4_addr);
- if (!fascist_firewall_use_ipv6(options)) {
+ if (!reachable_addr_use_ipv6(options)) {
return 0;
} else if (node->ipv6_preferred ||
!tor_addr_port_is_valid_ap(&ipv4_addr, 0)) {
@@ -1783,12 +1807,12 @@ node_ipv6_or_preferred(const node_t *node)
return 0;
}
-#define RETURN_IPV4_AP(r, port_field, ap_out) \
- STMT_BEGIN \
- if (r && tor_addr_port_is_valid_ipv4h((r)->addr, (r)->port_field, 0)) { \
- tor_addr_from_ipv4h(&(ap_out)->addr, (r)->addr); \
- (ap_out)->port = (r)->port_field; \
- } \
+#define RETURN_IPV4_AP(r, port_field, ap_out) \
+ STMT_BEGIN \
+ if (r && tor_addr_port_is_valid(&(r)->ipv4_addr, (r)->port_field, 0)) { \
+ tor_addr_copy(&(ap_out)->addr, &(r)->ipv4_addr); \
+ (ap_out)->port = (r)->port_field; \
+ } \
STMT_END
/** Copy the primary (IPv4) OR port (IP address and TCP port) for <b>node</b>
@@ -1807,8 +1831,8 @@ node_get_prim_orport(const node_t *node, tor_addr_port_t *ap_out)
/* Check ri first, because rewrite_node_address_for_bridge() updates
* node->ri with the configured bridge address. */
- RETURN_IPV4_AP(node->ri, or_port, ap_out);
- RETURN_IPV4_AP(node->rs, or_port, ap_out);
+ RETURN_IPV4_AP(node->ri, ipv4_orport, ap_out);
+ RETURN_IPV4_AP(node->rs, ipv4_orport, ap_out);
/* Microdescriptors only have an IPv6 address */
}
@@ -1869,7 +1893,7 @@ node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out)
* or
* ii) our preference is for IPv6 Dir addresses.
*
- * If there is no node, use fascist_firewall_prefer_ipv6_dirport().
+ * If there is no node, use reachable_addr_prefer_ipv6_dirport().
*/
int
node_ipv6_dir_preferred(const node_t *node)
@@ -1878,15 +1902,15 @@ node_ipv6_dir_preferred(const node_t *node)
tor_addr_port_t ipv4_addr;
node_assert_ok(node);
- /* node->ipv6_preferred is set from fascist_firewall_prefer_ipv6_orport(),
+ /* node->ipv6_preferred is set from reachable_addr_prefer_ipv6_orport(),
* so we can't use it to determine DirPort IPv6 preference.
* This means that bridge clients will use IPv4 DirPorts by default.
*/
node_get_prim_dirport(node, &ipv4_addr);
- if (!fascist_firewall_use_ipv6(options)) {
+ if (!reachable_addr_use_ipv6(options)) {
return 0;
} else if (!tor_addr_port_is_valid_ap(&ipv4_addr, 0)
- || fascist_firewall_prefer_ipv6_dirport(get_options())) {
+ || reachable_addr_prefer_ipv6_dirport(get_options())) {
return node_has_ipv6_dirport(node);
}
return 0;
@@ -1908,8 +1932,8 @@ node_get_prim_dirport(const node_t *node, tor_addr_port_t *ap_out)
/* Check ri first, because rewrite_node_address_for_bridge() updates
* node->ri with the configured bridge address. */
- RETURN_IPV4_AP(node->ri, dir_port, ap_out);
- RETURN_IPV4_AP(node->rs, dir_port, ap_out);
+ RETURN_IPV4_AP(node->ri, ipv4_dirport, ap_out);
+ RETURN_IPV4_AP(node->rs, ipv4_dirport, ap_out);
/* Microdescriptors only have an IPv6 address */
}
@@ -1946,13 +1970,13 @@ node_get_pref_ipv6_dirport(const node_t *node, tor_addr_port_t *ap_out)
/* Assume IPv4 and IPv6 dirports are the same */
if (node->ri && tor_addr_port_is_valid(&node->ri->ipv6_addr,
- node->ri->dir_port, 0)) {
+ node->ri->ipv4_dirport, 0)) {
tor_addr_copy(&ap_out->addr, &node->ri->ipv6_addr);
- ap_out->port = node->ri->dir_port;
+ ap_out->port = node->ri->ipv4_dirport;
} else if (node->rs && tor_addr_port_is_valid(&node->rs->ipv6_addr,
- node->rs->dir_port, 0)) {
+ node->rs->ipv4_dirport, 0)) {
tor_addr_copy(&ap_out->addr, &node->rs->ipv6_addr);
- ap_out->port = node->rs->dir_port;
+ ap_out->port = node->rs->ipv4_dirport;
} else {
tor_addr_make_null(&ap_out->addr, AF_INET6);
ap_out->port = 0;
@@ -2004,7 +2028,7 @@ node_get_curve25519_onion_key(const node_t *node)
/* Return a newly allocacted RSA onion public key taken from the given node.
*
* Return NULL if node is NULL or no RSA onion public key can be found. It is
- * the caller responsability to free the returned object. */
+ * the caller responsibility to free the returned object. */
crypto_pk_t *
node_get_rsa_onion_key(const node_t *node)
{
@@ -2037,15 +2061,21 @@ node_get_rsa_onion_key(const node_t *node)
void
node_set_country(node_t *node)
{
- tor_addr_t addr = TOR_ADDR_NULL;
+ const tor_addr_t *ipv4_addr = NULL;
/* XXXXipv6 */
if (node->rs)
- tor_addr_from_ipv4h(&addr, node->rs->addr);
+ ipv4_addr = &node->rs->ipv4_addr;
else if (node->ri)
- tor_addr_from_ipv4h(&addr, node->ri->addr);
+ ipv4_addr = &node->ri->ipv4_addr;
- node->country = geoip_get_country_by_addr(&addr);
+ /* IPv4 is mandatory for a relay so this should not happen unless we are
+ * attempting to set the country code on a node without a descriptor. */
+ if (BUG(!ipv4_addr)) {
+ node->country = -1;
+ return;
+ }
+ node->country = geoip_get_country_by_addr(ipv4_addr);
}
/** Set the country code of all routers in the routerlist. */
@@ -2060,7 +2090,7 @@ nodelist_refresh_countries(void)
/** Return true iff router1 and router2 have similar enough network addresses
* that we should treat them as being in the same family */
int
-addrs_in_same_network_family(const tor_addr_t *a1,
+router_addrs_in_same_network(const tor_addr_t *a1,
const tor_addr_t *a2)
{
if (tor_addr_is_null(a1) || tor_addr_is_null(a2))
@@ -2176,8 +2206,8 @@ nodes_in_same_family(const node_t *node1, const node_t *node2)
node_get_pref_ipv6_orport(node1, &ap6_1);
node_get_pref_ipv6_orport(node2, &ap6_2);
- if (addrs_in_same_network_family(&a1, &a2) ||
- addrs_in_same_network_family(&ap6_1.addr, &ap6_2.addr))
+ if (router_addrs_in_same_network(&a1, &a2) ||
+ router_addrs_in_same_network(&ap6_1.addr, &ap6_2.addr))
return 1;
}
@@ -2235,8 +2265,8 @@ nodelist_add_node_and_family(smartlist_t *sl, const node_t *node)
tor_addr_port_t ap6;
node_get_addr(node2, &a);
node_get_pref_ipv6_orport(node2, &ap6);
- if (addrs_in_same_network_family(&a, &node_addr) ||
- addrs_in_same_network_family(&ap6.addr, &node_ap6.addr))
+ if (router_addrs_in_same_network(&a, &node_addr) ||
+ router_addrs_in_same_network(&ap6.addr, &node_ap6.addr))
smartlist_add(sl, (void*)node2);
} SMARTLIST_FOREACH_END(node2);
}
@@ -2276,21 +2306,18 @@ nodelist_add_node_and_family(smartlist_t *sl, const node_t *node)
const node_t *
router_find_exact_exit_enclave(const char *address, uint16_t port)
{/*XXXX MOVE*/
- uint32_t addr;
struct in_addr in;
- tor_addr_t a;
+ tor_addr_t ipv4_addr;
const or_options_t *options = get_options();
if (!tor_inet_aton(address, &in))
return NULL; /* it's not an IP already */
- addr = ntohl(in.s_addr);
-
- tor_addr_from_ipv4h(&a, addr);
+ tor_addr_from_in(&ipv4_addr, &in);
SMARTLIST_FOREACH(nodelist_get_list(), const node_t *, node, {
- if (node_get_addr_ipv4h(node) == addr &&
+ if (tor_addr_eq(node_get_prim_addr_ipv4(node), &ipv4_addr) &&
node->is_running &&
- compare_tor_addr_to_node_policy(&a, port, node) ==
+ compare_tor_addr_to_node_policy(&ipv4_addr, port, node) ==
ADDR_POLICY_ACCEPTED &&
!routerset_contains_node(options->ExcludeExitNodesUnion_, node))
return node;
diff --git a/src/feature/nodelist/nodelist.h b/src/feature/nodelist/nodelist.h
index 0e06326a9c..44b8918b06 100644
--- a/src/feature/nodelist/nodelist.h
+++ b/src/feature/nodelist/nodelist.h
@@ -32,8 +32,8 @@ const node_t *node_get_by_hex_id(const char *identity_digest,
unsigned flags);
node_t *nodelist_set_routerinfo(routerinfo_t *ri, routerinfo_t **ri_old_out);
node_t *nodelist_add_microdesc(microdesc_t *md);
-void nodelist_set_consensus(networkstatus_t *ns);
-void nodelist_ensure_freshness(networkstatus_t *ns);
+void nodelist_set_consensus(const networkstatus_t *ns);
+void nodelist_ensure_freshness(const networkstatus_t *ns);
int nodelist_probably_contains_address(const tor_addr_t *addr);
bool nodelist_reentry_contains(const tor_addr_t *addr, uint16_t port);
void nodelist_add_addr_to_address_set(const tor_addr_t *addr,
@@ -68,20 +68,23 @@ smartlist_t *node_get_all_orports(const node_t *node);
int node_allows_single_hop_exits(const node_t *node);
const char *node_get_nickname(const node_t *node);
const char *node_get_platform(const node_t *node);
-uint32_t node_get_prim_addr_ipv4h(const node_t *node);
void node_get_address_string(const node_t *node, char *cp, size_t len);
long node_get_declared_uptime(const node_t *node);
MOCK_DECL(const struct ed25519_public_key_t *,node_get_ed25519_id,
(const node_t *node));
int node_ed25519_id_matches(const node_t *node,
const struct ed25519_public_key_t *id);
-MOCK_DECL(int,node_supports_ed25519_link_authentication,
+MOCK_DECL(bool,node_supports_ed25519_link_authentication,
(const node_t *node,
- int compatible_with_us));
-int node_supports_v3_hsdir(const node_t *node);
-int node_supports_ed25519_hs_intro(const node_t *node);
-int node_supports_v3_rendezvous_point(const node_t *node);
-int node_supports_establish_intro_dos_extension(const node_t *node);
+ bool compatible_with_us));
+bool node_supports_v3_hsdir(const node_t *node);
+bool node_supports_ed25519_hs_intro(const node_t *node);
+bool node_supports_v3_rendezvous_point(const node_t *node);
+bool node_supports_establish_intro_dos_extension(const node_t *node);
+bool node_supports_initiating_ipv6_extends(const node_t *node);
+bool node_supports_accepting_ipv6_extends(const node_t *node,
+ bool need_canonical_ipv6_conn);
+
const uint8_t *node_get_rsa_id_digest(const node_t *node);
MOCK_DECL(smartlist_t *,node_get_link_specifier_smartlist,(const node_t *node,
bool direct_conn));
@@ -111,7 +114,6 @@ MOCK_DECL(const smartlist_t *, nodelist_get_list, (void));
/* Temporary during transition to multiple addresses. */
void node_get_addr(const node_t *node, tor_addr_t *addr_out);
-#define node_get_addr_ipv4h(n) node_get_prim_addr_ipv4h((n))
void nodelist_refresh_countries(void);
void node_set_country(node_t *node);
@@ -125,7 +127,7 @@ int node_is_unreliable(const node_t *router, int need_uptime,
int router_exit_policy_all_nodes_reject(const tor_addr_t *addr, uint16_t port,
int need_uptime);
void router_set_status(const char *digest, int up);
-int addrs_in_same_network_family(const tor_addr_t *a1,
+int router_addrs_in_same_network(const tor_addr_t *a1,
const tor_addr_t *a2);
/** router_have_minimum_dir_info tests to see if we have enough
diff --git a/src/feature/nodelist/routerinfo.c b/src/feature/nodelist/routerinfo.c
index 0bf2a977f5..eb8eb74daa 100644
--- a/src/feature/nodelist/routerinfo.c
+++ b/src/feature/nodelist/routerinfo.c
@@ -13,26 +13,50 @@
#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerinfo.h"
+#include "feature/nodelist/torcert.h"
#include "feature/nodelist/node_st.h"
#include "feature/nodelist/routerinfo_st.h"
-/** Copy the primary (IPv4) OR port (IP address and TCP port) for
- * <b>router</b> into *<b>ap_out</b>. */
-void
-router_get_prim_orport(const routerinfo_t *router, tor_addr_port_t *ap_out)
+/** Copy the OR port (IP address and TCP port) for <b>router</b> and
+ * <b>family</b> into *<b>ap_out</b>.
+ *
+ * If the requested ORPort does not exist, sets *<b>ap_out</b> to the null
+ * address and port, and returns -1. Otherwise, returns 0. */
+int
+router_get_orport(const routerinfo_t *router,
+ tor_addr_port_t *ap_out,
+ int family)
{
tor_assert(ap_out != NULL);
- tor_addr_from_ipv4h(&ap_out->addr, router->addr);
- ap_out->port = router->or_port;
+ if (family == AF_INET) {
+ tor_addr_copy(&ap_out->addr, &router->ipv4_addr);
+ ap_out->port = router->ipv4_orport;
+ return 0;
+ } else if (family == AF_INET6) {
+ /* IPv6 addresses are optional, so check if it is valid. */
+ if (tor_addr_port_is_valid(&router->ipv6_addr, router->ipv6_orport, 0)) {
+ tor_addr_copy(&ap_out->addr, &router->ipv6_addr);
+ ap_out->port = router->ipv6_orport;
+ return 0;
+ } else {
+ tor_addr_port_make_null_ap(ap_out, AF_INET6);
+ return -1;
+ }
+ } else {
+ /* Unsupported address family */
+ tor_assert_nonfatal_unreached();
+ tor_addr_port_make_null_ap(ap_out, AF_UNSPEC);
+ return -1;
+ }
}
int
router_has_orport(const routerinfo_t *router, const tor_addr_port_t *orport)
{
return
- (tor_addr_eq_ipv4h(&orport->addr, router->addr) &&
- orport->port == router->or_port) ||
+ (tor_addr_eq(&orport->addr, &router->ipv4_addr) &&
+ orport->port == router->ipv4_orport) ||
(tor_addr_eq(&orport->addr, &router->ipv6_addr) &&
orport->port == router->ipv6_orport);
}
@@ -52,6 +76,21 @@ router_get_all_orports(const routerinfo_t *ri)
return node_get_all_orports(&fake_node);
}
+/** Return the Ed25519 identity key for this routerinfo, or NULL if it
+ * doesn't have one. */
+const ed25519_public_key_t *
+routerinfo_get_ed25519_id(const routerinfo_t *ri)
+{
+ if (BUG(! ri))
+ return NULL;
+
+ const tor_cert_t *cert = ri->cache_info.signing_key_cert;
+ if (cert && ! ed25519_public_key_is_zero(&cert->signing_key))
+ return &cert->signing_key;
+ else
+ return NULL;
+}
+
/** Given a router purpose, convert it to a string. Don't call this on
* ROUTER_PURPOSE_UNKNOWN: The whole point of that value is that we don't
* know its string representation. */
diff --git a/src/feature/nodelist/routerinfo.h b/src/feature/nodelist/routerinfo.h
index 604e478999..bc78beb402 100644
--- a/src/feature/nodelist/routerinfo.h
+++ b/src/feature/nodelist/routerinfo.h
@@ -12,11 +12,16 @@
#ifndef TOR_ROUTERINFO_H
#define TOR_ROUTERINFO_H
-void router_get_prim_orport(const routerinfo_t *router,
- tor_addr_port_t *addr_port_out);
+int router_get_orport(const routerinfo_t *router,
+ tor_addr_port_t *addr_port_out,
+ int family);
int router_has_orport(const routerinfo_t *router,
const tor_addr_port_t *orport);
+struct ed25519_public_key_t;
+const struct ed25519_public_key_t *routerinfo_get_ed25519_id(
+ const routerinfo_t *ri);
+
smartlist_t *router_get_all_orports(const routerinfo_t *ri);
const char *router_purpose_to_string(uint8_t p);
diff --git a/src/feature/nodelist/routerinfo_st.h b/src/feature/nodelist/routerinfo_st.h
index 36ead50e33..7197c88c18 100644
--- a/src/feature/nodelist/routerinfo_st.h
+++ b/src/feature/nodelist/routerinfo_st.h
@@ -21,9 +21,10 @@ struct routerinfo_t {
signed_descriptor_t cache_info;
char *nickname; /**< Human-readable OR name. */
- uint32_t addr; /**< IPv4 address of OR, in host order. */
- uint16_t or_port; /**< Port for TLS connections. */
- uint16_t dir_port; /**< Port for HTTP directory connections. */
+ /** A router's IPv4 address. */
+ tor_addr_t ipv4_addr;
+ uint16_t ipv4_orport;
+ uint16_t ipv4_dirport;
/** A router's IPv6 address, if it has one. */
tor_addr_t ipv6_addr;
diff --git a/src/feature/nodelist/routerlist.c b/src/feature/nodelist/routerlist.c
index 96bea5a670..a1a348edb9 100644
--- a/src/feature/nodelist/routerlist.c
+++ b/src/feature/nodelist/routerlist.c
@@ -65,6 +65,9 @@
#include "app/config/config.h"
#include "core/mainloop/connection.h"
#include "core/mainloop/mainloop.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "core/or/extendinfo.h"
#include "core/or/policies.h"
#include "feature/client/bridges.h"
#include "feature/control/control_events.h"
@@ -89,6 +92,7 @@
#include "feature/nodelist/routerset.h"
#include "feature/nodelist/torcert.h"
#include "feature/relay/routermode.h"
+#include "feature/relay/relay_find_addr.h"
#include "feature/stats/rephist.h"
#include "lib/crypt_ops/crypto_format.h"
#include "lib/crypt_ops/crypto_rand.h"
@@ -136,8 +140,6 @@ static int signed_desc_digest_is_recognized(signed_descriptor_t *desc);
static const char *signed_descriptor_get_body_impl(
const signed_descriptor_t *desc,
int with_annotations);
-static void launch_dummy_descriptor_download_as_needed(time_t now,
- const or_options_t *options);
/****************************************************************************/
@@ -465,11 +467,20 @@ router_reload_router_list(void)
return 0;
}
-/* When iterating through the routerlist, can OR address/port preference
- * and reachability checks be skipped?
+/* When selecting a router for a direct connection, can OR address/port
+ * preference and reachability checks be skipped?
+ *
+ * Servers never check ReachableAddresses or ClientPreferIPv6. Returns
+ * true for servers.
+ *
+ * Otherwise, if <b>try_ip_pref</b> is true, returns false. Used to make
+ * clients check ClientPreferIPv6, even if ReachableAddresses is not set.
+ * Finally, return true if ReachableAddresses is set.
*/
int
-router_skip_or_reachability(const or_options_t *options, int try_ip_pref)
+router_or_conn_should_skip_reachable_address_check(
+ const or_options_t *options,
+ int try_ip_pref)
{
/* Servers always have and prefer IPv4.
* And if clients are checking against the firewall for reachability only,
@@ -477,11 +488,15 @@ router_skip_or_reachability(const or_options_t *options, int try_ip_pref)
return server_mode(options) || (!try_ip_pref && !firewall_is_fascist_or());
}
-/* When iterating through the routerlist, can Dir address/port preference
+/* When selecting a router for a direct connection, can Dir address/port
* and reachability checks be skipped?
+ *
+ * This function is obsolete, because clients only use ORPorts.
*/
int
-router_skip_dir_reachability(const or_options_t *options, int try_ip_pref)
+router_dir_conn_should_skip_reachable_address_check(
+ const or_options_t *options,
+ int try_ip_pref)
{
/* Servers always have and prefer IPv4.
* And if clients are checking against the firewall for reachability only,
@@ -493,45 +508,115 @@ router_skip_dir_reachability(const or_options_t *options, int try_ip_pref)
int
routers_have_same_or_addrs(const routerinfo_t *r1, const routerinfo_t *r2)
{
- return r1->addr == r2->addr && r1->or_port == r2->or_port &&
+ return tor_addr_eq(&r1->ipv4_addr, &r2->ipv4_addr) &&
+ r1->ipv4_orport == r2->ipv4_orport &&
tor_addr_eq(&r1->ipv6_addr, &r2->ipv6_addr) &&
r1->ipv6_orport == r2->ipv6_orport;
}
+/* Returns true if <b>node</b> can be chosen based on <b>flags</b>.
+ *
+ * The following conditions are applied to all nodes:
+ * - is running;
+ * - is valid;
+ * - supports EXTEND2 cells;
+ * - has an ntor circuit crypto key; and
+ * - does not allow single-hop exits.
+ *
+ * If the node has a routerinfo, we're checking for a direct connection, and
+ * we're using bridges, the following condition is applied:
+ * - has a bridge-purpose routerinfo;
+ * and for all other nodes:
+ * - has a general-purpose routerinfo (or no routerinfo).
+ *
+ * Nodes that don't have a routerinfo must be general-purpose nodes, because
+ * routerstatuses and microdescriptors only come via consensuses.
+ *
+ * The <b>flags</b> check that <b>node</b>:
+ * - <b>CRN_NEED_UPTIME</b>: has more than a minimum uptime;
+ * - <b>CRN_NEED_CAPACITY</b>: has more than a minimum capacity;
+ * - <b>CRN_NEED_GUARD</b>: is a Guard;
+ * - <b>CRN_NEED_DESC</b>: has a routerinfo or microdescriptor -- that is,
+ * enough info to be used to build a circuit;
+ * - <b>CRN_DIRECT_CONN</b>: is suitable for direct connections. Checks
+ * for the relevant descriptors. Checks the address
+ * against ReachableAddresses, ClientUseIPv4 0, and
+ * reachable_addr_use_ipv6() == 0);
+ * - <b>CRN_PREF_ADDR</b>: if we are connecting directly to the node, it has
+ * an address that is preferred by the
+ * ClientPreferIPv6ORPort setting;
+ * - <b>CRN_RENDEZVOUS_V3</b>: can become a v3 onion service rendezvous point;
+ * - <b>CRN_INITIATE_IPV6_EXTEND</b>: can initiate IPv6 extends.
+ */
+bool
+router_can_choose_node(const node_t *node, int flags)
+{
+ /* The full set of flags used for node selection. */
+ const bool need_uptime = (flags & CRN_NEED_UPTIME) != 0;
+ const bool need_capacity = (flags & CRN_NEED_CAPACITY) != 0;
+ const bool need_guard = (flags & CRN_NEED_GUARD) != 0;
+ const bool need_desc = (flags & CRN_NEED_DESC) != 0;
+ const bool pref_addr = (flags & CRN_PREF_ADDR) != 0;
+ const bool direct_conn = (flags & CRN_DIRECT_CONN) != 0;
+ const bool rendezvous_v3 = (flags & CRN_RENDEZVOUS_V3) != 0;
+ const bool initiate_ipv6_extend = (flags & CRN_INITIATE_IPV6_EXTEND) != 0;
+
+ const or_options_t *options = get_options();
+ const bool check_reach =
+ !router_or_conn_should_skip_reachable_address_check(options, pref_addr);
+ const bool direct_bridge = direct_conn && options->UseBridges;
+
+ if (!node->is_running || !node->is_valid)
+ return false;
+ if (need_desc && !node_has_preferred_descriptor(node, direct_conn))
+ return false;
+ if (node->ri) {
+ if (direct_bridge && node->ri->purpose != ROUTER_PURPOSE_BRIDGE)
+ return false;
+ else if (node->ri->purpose != ROUTER_PURPOSE_GENERAL)
+ return false;
+ }
+ if (node_is_unreliable(node, need_uptime, need_capacity, need_guard))
+ return false;
+ /* Don't choose nodes if we are certain they can't do EXTEND2 cells */
+ if (node->rs && !routerstatus_version_supports_extend2_cells(node->rs, 1))
+ return false;
+ /* Don't choose nodes if we are certain they can't do ntor. */
+ if ((node->ri || node->md) && !node_has_curve25519_onion_key(node))
+ return false;
+ /* Exclude relays that allow single hop exit circuits. This is an
+ * obsolete option since 0.2.9.2-alpha and done by default in
+ * 0.3.1.0-alpha. */
+ if (node_allows_single_hop_exits(node))
+ return false;
+ /* Exclude relays that can not become a rendezvous for a hidden service
+ * version 3. */
+ if (rendezvous_v3 &&
+ !node_supports_v3_rendezvous_point(node))
+ return false;
+ /* Choose a node with an OR address that matches the firewall rules */
+ if (direct_conn && check_reach &&
+ !reachable_addr_allows_node(node,
+ FIREWALL_OR_CONNECTION,
+ pref_addr))
+ return false;
+ if (initiate_ipv6_extend && !node_supports_initiating_ipv6_extends(node))
+ return false;
+
+ return true;
+}
+
/** Add every suitable node from our nodelist to <b>sl</b>, so that
- * we can pick a node for a circuit.
+ * we can pick a node for a circuit based on <b>flags</b>.
+ *
+ * See router_can_choose_node() for details of <b>flags</b>.
*/
void
-router_add_running_nodes_to_smartlist(smartlist_t *sl, int need_uptime,
- int need_capacity, int need_guard,
- int need_desc, int pref_addr,
- int direct_conn)
-{
- const int check_reach = !router_skip_or_reachability(get_options(),
- pref_addr);
- /* XXXX MOVE */
+router_add_running_nodes_to_smartlist(smartlist_t *sl, int flags)
+{
SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
- if (!node->is_running || !node->is_valid)
- continue;
- if (need_desc && !node_has_preferred_descriptor(node, direct_conn))
- continue;
- if (node->ri && node->ri->purpose != ROUTER_PURPOSE_GENERAL)
- continue;
- if (node_is_unreliable(node, need_uptime, need_capacity, need_guard))
- continue;
- /* Don't choose nodes if we are certain they can't do EXTEND2 cells */
- if (node->rs && !routerstatus_version_supports_extend2_cells(node->rs, 1))
- continue;
- /* Don't choose nodes if we are certain they can't do ntor. */
- if ((node->ri || node->md) && !node_has_curve25519_onion_key(node))
- continue;
- /* Choose a node with an OR address that matches the firewall rules */
- if (direct_conn && check_reach &&
- !fascist_firewall_allows_node(node,
- FIREWALL_OR_CONNECTION,
- pref_addr))
+ if (!router_can_choose_node(node, flags))
continue;
-
smartlist_add(sl, (void *)node);
} SMARTLIST_FOREACH_END(node);
}
@@ -2222,7 +2307,6 @@ update_all_descriptor_downloads(time_t now)
return;
update_router_descriptor_downloads(now);
update_microdesc_downloads(now);
- launch_dummy_descriptor_download_as_needed(now, get_options());
}
/** Clear all our timeouts for fetching v3 directory stuff, and then
@@ -2676,39 +2760,6 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
smartlist_free(no_longer_old);
}
-/** How often should we launch a server/authority request to be sure of getting
- * a guess for our IP? */
-/*XXXX+ this info should come from netinfo cells or something, or we should
- * do this only when we aren't seeing incoming data. see bug 652. */
-#define DUMMY_DOWNLOAD_INTERVAL (20*60)
-
-/** As needed, launch a dummy router descriptor fetch to see if our
- * address has changed. */
-static void
-launch_dummy_descriptor_download_as_needed(time_t now,
- const or_options_t *options)
-{
- static time_t last_dummy_download = 0;
- /* XXXX+ we could be smarter here; see notes on bug 652. */
- /* If we're a server that doesn't have a configured address, we rely on
- * directory fetches to learn when our address changes. So if we haven't
- * tried to get any routerdescs in a long time, try a dummy fetch now. */
- if (!options->Address &&
- server_mode(options) &&
- last_descriptor_download_attempted + DUMMY_DOWNLOAD_INTERVAL < now &&
- last_dummy_download + DUMMY_DOWNLOAD_INTERVAL < now) {
- last_dummy_download = now;
- /* XX/teor - do we want an authority here, because they are less likely
- * to give us the wrong address? (See #17782)
- * I'm leaving the previous behaviour intact, because I don't like
- * the idea of some relays contacting an authority every 20 minutes. */
- directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC,
- ROUTER_PURPOSE_GENERAL, "authority.z",
- PDS_RETRY_IF_NO_SERVERS,
- DL_WANT_ANY_DIRSERVER);
- }
-}
-
/** Launch downloads for router status as needed. */
void
update_router_descriptor_downloads(time_t now)
@@ -2882,12 +2933,12 @@ router_differences_are_cosmetic(const routerinfo_t *r1, const routerinfo_t *r2)
}
/* If any key fields differ, they're different. */
- if (r1->addr != r2->addr ||
+ if (!tor_addr_eq(&r1->ipv4_addr, &r2->ipv4_addr) ||
strcasecmp(r1->nickname, r2->nickname) ||
- r1->or_port != r2->or_port ||
+ r1->ipv4_orport != r2->ipv4_orport ||
!tor_addr_eq(&r1->ipv6_addr, &r2->ipv6_addr) ||
r1->ipv6_orport != r2->ipv6_orport ||
- r1->dir_port != r2->dir_port ||
+ r1->ipv4_dirport != r2->ipv4_dirport ||
r1->purpose != r2->purpose ||
r1->onion_pkey_len != r2->onion_pkey_len ||
!tor_memeq(r1->onion_pkey, r2->onion_pkey, r1->onion_pkey_len) ||
diff --git a/src/feature/nodelist/routerlist.h b/src/feature/nodelist/routerlist.h
index 81a2343540..98472b2771 100644
--- a/src/feature/nodelist/routerlist.h
+++ b/src/feature/nodelist/routerlist.h
@@ -50,14 +50,16 @@ typedef enum was_router_added_t {
int router_reload_router_list(void);
-int router_skip_or_reachability(const or_options_t *options, int try_ip_pref);
-int router_skip_dir_reachability(const or_options_t *options, int try_ip_pref);
+int router_or_conn_should_skip_reachable_address_check(
+ const or_options_t *options,
+ int try_ip_pref);
+int router_dir_conn_should_skip_reachable_address_check(
+ const or_options_t *options,
+ int try_ip_pref);
void router_reset_status_download_failures(void);
int routers_have_same_or_addrs(const routerinfo_t *r1, const routerinfo_t *r2);
-void router_add_running_nodes_to_smartlist(smartlist_t *sl, int need_uptime,
- int need_capacity, int need_guard,
- int need_desc, int pref_addr,
- int direct_conn);
+bool router_can_choose_node(const node_t *node, int flags);
+void router_add_running_nodes_to_smartlist(smartlist_t *sl, int flags);
const routerinfo_t *routerlist_find_my_routerinfo(void);
uint32_t router_get_advertised_bandwidth(const routerinfo_t *router);
diff --git a/src/feature/nodelist/routerset.c b/src/feature/nodelist/routerset.c
index 2e06ecbf04..0d123956d9 100644
--- a/src/feature/nodelist/routerset.c
+++ b/src/feature/nodelist/routerset.c
@@ -56,6 +56,7 @@ routerset_new(void)
result->digests = digestmap_new();
result->policies = smartlist_new();
result->country_names = smartlist_new();
+ result->fragile = 0;
return result;
}
@@ -223,11 +224,11 @@ routerset_len(const routerset_t *set)
*
* (If country is -1, then we take the country
* from addr.) */
-STATIC int
-routerset_contains(const routerset_t *set, const tor_addr_t *addr,
- uint16_t orport,
- const char *nickname, const char *id_digest,
- country_t country)
+static int
+routerset_contains2(const routerset_t *set, const tor_addr_t *addr,
+ uint16_t orport, const tor_addr_t *addr2,
+ uint16_t orport2, const char *nickname,
+ const char *id_digest, country_t country)
{
if (!set || !set->list)
return 0;
@@ -238,6 +239,9 @@ routerset_contains(const routerset_t *set, const tor_addr_t *addr,
if (addr && compare_tor_addr_to_addr_policy(addr, orport, set->policies)
== ADDR_POLICY_REJECTED)
return 3;
+ if (addr2 && compare_tor_addr_to_addr_policy(addr2, orport2, set->policies)
+ == ADDR_POLICY_REJECTED)
+ return 3;
if (set->countries) {
if (country < 0 && addr)
country = geoip_get_country_by_addr(addr);
@@ -249,6 +253,17 @@ routerset_contains(const routerset_t *set, const tor_addr_t *addr,
return 0;
}
+/** Helper. Like routerset_contains2() but for a single IP/port combo.
+ */
+STATIC int
+routerset_contains(const routerset_t *set, const tor_addr_t *addr,
+ uint16_t orport, const char *nickname,
+ const char *id_digest, country_t country)
+{
+ return routerset_contains2(set, addr, orport, NULL, 0,
+ nickname, id_digest, country);
+}
+
/** If *<b>setp</b> includes at least one country code, or if
* <b>only_some_cc_set</b> is 0, add the ?? and A1 country codes to
* *<b>setp</b>, creating it as needed. Return true iff *<b>setp</b> changed.
@@ -292,12 +307,19 @@ routerset_add_unknown_ccs(routerset_t **setp, int only_if_some_cc_set)
int
routerset_contains_extendinfo(const routerset_t *set, const extend_info_t *ei)
{
- return routerset_contains(set,
- &ei->addr,
- ei->port,
- ei->nickname,
- ei->identity_digest,
- -1 /*country*/);
+ const tor_addr_port_t *ap1 = NULL, *ap2 = NULL;
+ if (! tor_addr_is_null(&ei->orports[0].addr))
+ ap1 = &ei->orports[0];
+ if (! tor_addr_is_null(&ei->orports[1].addr))
+ ap2 = &ei->orports[1];
+ return routerset_contains2(set,
+ ap1 ? &ap1->addr : NULL,
+ ap1 ? ap1->port : 0,
+ ap2 ? &ap2->addr : NULL,
+ ap2 ? ap2->port : 0,
+ ei->nickname,
+ ei->identity_digest,
+ -1 /*country*/);
}
/** Return true iff <b>ri</b> is in <b>set</b>. If country is <b>-1</b>, we
@@ -306,14 +328,9 @@ int
routerset_contains_router(const routerset_t *set, const routerinfo_t *ri,
country_t country)
{
- tor_addr_t addr;
- tor_addr_from_ipv4h(&addr, ri->addr);
- return routerset_contains(set,
- &addr,
- ri->or_port,
- ri->nickname,
- ri->cache_info.identity_digest,
- country);
+ return routerset_contains2(set, &ri->ipv4_addr, ri->ipv4_orport,
+ &ri->ipv6_addr, ri->ipv6_orport, ri->nickname,
+ ri->cache_info.identity_digest, country);
}
/** Return true iff <b>rs</b> is in <b>set</b>. If country is <b>-1</b>, we
@@ -323,11 +340,9 @@ routerset_contains_routerstatus(const routerset_t *set,
const routerstatus_t *rs,
country_t country)
{
- tor_addr_t addr;
- tor_addr_from_ipv4h(&addr, rs->addr);
return routerset_contains(set,
- &addr,
- rs->or_port,
+ &rs->ipv4_addr,
+ rs->ipv4_orport,
rs->nickname,
rs->identity_digest,
country);
@@ -485,21 +500,32 @@ routerset_kv_parse(void *target, const config_line_t *line, char **errmsg,
const void *params)
{
(void)params;
- routerset_t **p = (routerset_t**)target;
- routerset_free(*p); // clear the old value, if any.
+ routerset_t **lines = target;
+
+ if (*lines && (*lines)->fragile) {
+ if (line->command == CONFIG_LINE_APPEND) {
+ (*lines)->fragile = 0;
+ } else {
+ routerset_free(*lines); // Represent empty sets as NULL
+ }
+ }
+
+ int ret;
routerset_t *rs = routerset_new();
if (routerset_parse(rs, line->value, line->key) < 0) {
- routerset_free(rs);
*errmsg = tor_strdup("Invalid router list.");
- return -1;
+ ret = -1;
} else {
- if (routerset_is_empty(rs)) {
- /* Represent empty sets as NULL. */
- routerset_free(rs);
+ if (!routerset_is_empty(rs)) {
+ if (!*lines) {
+ *lines = routerset_new();
+ }
+ routerset_union(*lines, rs);
}
- *p = rs;
- return 0;
+ ret = 0;
}
+ routerset_free(rs);
+ return ret;
}
/**
@@ -550,6 +576,15 @@ routerset_copy(void *dest, const void *src, const void *params)
return 0;
}
+static void
+routerset_mark_fragile(void *target, const void *params)
+{
+ (void)params;
+ routerset_t **ptr = (routerset_t **)target;
+ if (*ptr)
+ (*ptr)->fragile = 1;
+}
+
/**
* Function table to implement a routerset_t-based configuration type.
**/
@@ -557,7 +592,8 @@ static const var_type_fns_t routerset_type_fns = {
.kv_parse = routerset_kv_parse,
.encode = routerset_encode,
.clear = routerset_clear,
- .copy = routerset_copy
+ .copy = routerset_copy,
+ .mark_fragile = routerset_mark_fragile,
};
/**
@@ -571,5 +607,6 @@ static const var_type_fns_t routerset_type_fns = {
**/
const var_type_def_t ROUTERSET_type_defn = {
.name = "RouterList",
- .fns = &routerset_type_fns
+ .fns = &routerset_type_fns,
+ .flags = CFLG_NOREPLACE
};
diff --git a/src/feature/nodelist/routerset.h b/src/feature/nodelist/routerset.h
index 0e4fedf64e..18a0e31ba7 100644
--- a/src/feature/nodelist/routerset.h
+++ b/src/feature/nodelist/routerset.h
@@ -88,6 +88,10 @@ struct routerset_t {
* routerset_refresh_countries() whenever the geoip country list is
* reloaded. */
bitarray_t *countries;
+ /** If true, subsequent assignments to this routerset should replace
+ * it, not extend it. Set only on the first item in a routerset in an
+ * or_options_t. */
+ unsigned int fragile:1;
};
#endif /* defined(ROUTERSET_PRIVATE) */
#endif /* !defined(TOR_ROUTERSET_H) */
diff --git a/src/feature/nodelist/routerstatus_st.h b/src/feature/nodelist/routerstatus_st.h
index 735c754b31..254ba73f7f 100644
--- a/src/feature/nodelist/routerstatus_st.h
+++ b/src/feature/nodelist/routerstatus_st.h
@@ -29,9 +29,9 @@ struct routerstatus_t {
/** Digest of the router's most recent descriptor or microdescriptor.
* If it's a descriptor, we only use the first DIGEST_LEN bytes. */
char descriptor_digest[DIGEST256_LEN];
- uint32_t addr; /**< IPv4 address for this router, in host order. */
- uint16_t or_port; /**< IPv4 OR port for this router. */
- uint16_t dir_port; /**< Directory port for this router. */
+ tor_addr_t ipv4_addr;
+ uint16_t ipv4_orport; /**< IPv4 OR port for this router. */
+ uint16_t ipv4_dirport; /**< Directory port for this router. */
tor_addr_t ipv6_addr; /**< IPv6 address for this router. */
uint16_t ipv6_orport; /**< IPv6 OR port for this router. */
unsigned int is_authority:1; /**< True iff this router is an authority. */
diff --git a/src/feature/nodelist/torcert.c b/src/feature/nodelist/torcert.c
index 89cc9c88fb..dc36626122 100644
--- a/src/feature/nodelist/torcert.c
+++ b/src/feature/nodelist/torcert.c
@@ -37,11 +37,11 @@
#include "core/or/or_handshake_certs_st.h"
-/** Helper for tor_cert_create(): signs any 32 bytes, not just an ed25519
- * key.
+/** As tor_cert_create(), but accept an arbitrary signed_key_type as the
+ * subject key -- not just an ed25519 key.
*/
-static tor_cert_t *
-tor_cert_sign_impl(const ed25519_keypair_t *signing_key,
+tor_cert_t *
+tor_cert_create_raw(const ed25519_keypair_t *signing_key,
uint8_t cert_type,
uint8_t signed_key_type,
const uint8_t signed_key_info[32],
@@ -128,13 +128,13 @@ tor_cert_sign_impl(const ed25519_keypair_t *signing_key,
* the public part of <b>signing_key</b> in the certificate.
*/
tor_cert_t *
-tor_cert_create(const ed25519_keypair_t *signing_key,
+tor_cert_create_ed25519(const ed25519_keypair_t *signing_key,
uint8_t cert_type,
const ed25519_public_key_t *signed_key,
time_t now, time_t lifetime,
uint32_t flags)
{
- return tor_cert_sign_impl(signing_key, cert_type,
+ return tor_cert_create_raw(signing_key, cert_type,
SIGNED_KEY_TYPE_ED25519, signed_key->pubkey,
now, lifetime, flags);
}
diff --git a/src/feature/nodelist/torcert.h b/src/feature/nodelist/torcert.h
index f8fba2b794..3314ee2550 100644
--- a/src/feature/nodelist/torcert.h
+++ b/src/feature/nodelist/torcert.h
@@ -11,7 +11,9 @@
#include "lib/crypt_ops/crypto_ed25519.h"
-#define SIGNED_KEY_TYPE_ED25519 0x01
+#define SIGNED_KEY_TYPE_ED25519 0x01
+#define SIGNED_KEY_TYPE_SHA256_OF_RSA 0x02
+#define SIGNED_KEY_TYPE_SHA256_OF_X509 0x03
#define CERT_TYPE_ID_SIGNING 0x04
#define CERT_TYPE_SIGNING_LINK 0x05
@@ -56,11 +58,17 @@ typedef struct tor_cert_st {
struct tor_tls_t;
-tor_cert_t *tor_cert_create(const ed25519_keypair_t *signing_key,
+tor_cert_t *tor_cert_create_ed25519(const ed25519_keypair_t *signing_key,
uint8_t cert_type,
const ed25519_public_key_t *signed_key,
time_t now, time_t lifetime,
uint32_t flags);
+tor_cert_t * tor_cert_create_raw(const ed25519_keypair_t *signing_key,
+ uint8_t cert_type,
+ uint8_t signed_key_type,
+ const uint8_t signed_key_info[32],
+ time_t now, time_t lifetime,
+ uint32_t flags);
tor_cert_t *tor_cert_parse(const uint8_t *cert, size_t certlen);
diff --git a/src/feature/relay/circuitbuild_relay.c b/src/feature/relay/circuitbuild_relay.c
index b89866b477..289a5be557 100644
--- a/src/feature/relay/circuitbuild_relay.c
+++ b/src/feature/relay/circuitbuild_relay.c
@@ -33,6 +33,7 @@
#include "core/or/channel.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
+#include "core/or/extendinfo.h"
#include "core/or/onion.h"
#include "core/or/relay.h"
@@ -122,6 +123,52 @@ circuit_extend_add_ed25519_helper(struct extend_cell_t *ec)
return 0;
}
+/* Make sure the extend cell <b>ec</b> has an IPv4 address if the relay
+ * supports in, and if not, fill it in. */
+STATIC int
+circuit_extend_add_ipv4_helper(struct extend_cell_t *ec)
+{
+ IF_BUG_ONCE(!ec) {
+ return -1;
+ }
+
+ const node_t *node = node_get_by_id((const char *) ec->node_id);
+ if (node) {
+ tor_addr_port_t node_ipv4;
+ node_get_prim_orport(node, &node_ipv4);
+ if (tor_addr_is_null(&ec->orport_ipv4.addr) &&
+ !tor_addr_is_null(&node_ipv4.addr)) {
+ tor_addr_copy(&ec->orport_ipv4.addr, &node_ipv4.addr);
+ ec->orport_ipv4.port = node_ipv4.port;
+ }
+ }
+
+ return 0;
+}
+
+/* Make sure the extend cell <b>ec</b> has an IPv6 address if the relay
+ * supports in, and if not, fill it in. */
+STATIC int
+circuit_extend_add_ipv6_helper(struct extend_cell_t *ec)
+{
+ IF_BUG_ONCE(!ec) {
+ return -1;
+ }
+
+ const node_t *node = node_get_by_id((const char *) ec->node_id);
+ if (node) {
+ tor_addr_port_t node_ipv6;
+ node_get_pref_ipv6_orport(node, &node_ipv6);
+ if (tor_addr_is_null(&ec->orport_ipv6.addr) &&
+ !tor_addr_is_null(&node_ipv6.addr)) {
+ tor_addr_copy(&ec->orport_ipv6.addr, &node_ipv6.addr);
+ ec->orport_ipv6.port = node_ipv6.port;
+ }
+ }
+
+ return 0;
+}
+
/* Check if the address and port in the tor_addr_port_t <b>ap</b> are valid,
* and are allowed by the current ExtendAllowPrivateAddresses config.
*
@@ -354,11 +401,7 @@ circuit_open_connection_for_extend(const struct extend_cell_t *ec,
if (should_launch) {
/* we should try to open a connection */
- channel_t *n_chan = channel_connect_for_circuit(
- &circ->n_hop->addr,
- circ->n_hop->port,
- circ->n_hop->identity_digest,
- &circ->n_hop->ed_identity);
+ channel_t *n_chan = channel_connect_for_circuit(circ->n_hop);
if (!n_chan) {
log_info(LD_CIRC,"Launching n_chan failed. Closing circuit.");
circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED);
@@ -412,6 +455,12 @@ circuit_extend(struct cell_t *cell, struct circuit_t *circ)
if (circuit_extend_lspec_valid_helper(&ec, circ) < 0)
return -1;
+ if (circuit_extend_add_ipv4_helper(&ec) < 0)
+ return -1;
+
+ if (circuit_extend_add_ipv6_helper(&ec) < 0)
+ return -1;
+
/* Check the addresses, without logging */
const int ipv4_valid = circuit_extend_addr_port_is_valid(&ec.orport_ipv4,
false, false, 0);
@@ -426,6 +475,7 @@ circuit_extend(struct cell_t *cell, struct circuit_t *circ)
&ec.ed_pubkey,
ipv4_valid ? &ec.orport_ipv4.addr : NULL,
ipv6_valid ? &ec.orport_ipv6.addr : NULL,
+ false,
&msg,
&should_launch);
@@ -452,7 +502,7 @@ circuit_extend(struct cell_t *cell, struct circuit_t *circ)
circ->n_chan = n_chan;
log_debug(LD_CIRC,
"n_chan is %s.",
- channel_get_canonical_remote_descr(n_chan));
+ channel_describe_peer(n_chan));
if (circuit_deliver_create_cell(circ, &ec.create_cell, 1) < 0)
return -1;
@@ -539,10 +589,24 @@ onionskin_answer(struct or_circuit_t *circ,
if ((!channel_is_local(circ->p_chan)
|| get_options()->ExtendAllowPrivateAddresses)
&& !channel_is_outgoing(circ->p_chan)) {
- /* record that we could process create cells from a non-local conn
- * that we didn't initiate; presumably this means that create cells
- * can reach us too. */
- router_orport_found_reachable();
+ /* Okay, it's a create cell from a non-local connection
+ * that we didn't initiate. Presumably this means that create cells
+ * can reach us too. But what address can they reach us on? */
+ const tor_addr_t *my_supposed_addr = &circ->p_chan->addr_according_to_peer;
+ if (router_addr_is_my_published_addr(my_supposed_addr)) {
+ /* Great, this create cell came on connection where the peer says
+ * that the our address is an address we're actually advertising!
+ * That should mean that we're reachable. But before we finally
+ * declare ourselves reachable, make sure that the address listed
+ * by the peer is the same family as the peer is actually using.
+ */
+ tor_addr_t remote_addr;
+ int family = tor_addr_family(my_supposed_addr);
+ if (channel_get_addr_if_possible(circ->p_chan, &remote_addr) &&
+ tor_addr_family(&remote_addr) == family) {
+ router_orport_found_reachable(family);
+ }
+ }
}
return 0;
diff --git a/src/feature/relay/circuitbuild_relay.h b/src/feature/relay/circuitbuild_relay.h
index 0783161538..dc0b886a34 100644
--- a/src/feature/relay/circuitbuild_relay.h
+++ b/src/feature/relay/circuitbuild_relay.h
@@ -73,6 +73,8 @@ onionskin_answer(struct or_circuit_t *circ,
STATIC int circuit_extend_state_valid_helper(const struct circuit_t *circ);
STATIC int circuit_extend_add_ed25519_helper(struct extend_cell_t *ec);
+STATIC int circuit_extend_add_ipv4_helper(struct extend_cell_t *ec);
+STATIC int circuit_extend_add_ipv6_helper(struct extend_cell_t *ec);
STATIC int circuit_extend_lspec_valid_helper(const struct extend_cell_t *ec,
const struct circuit_t *circ);
STATIC const tor_addr_port_t * circuit_choose_ip_ap_for_extend(
diff --git a/src/feature/relay/dns.c b/src/feature/relay/dns.c
index b83bd9b758..3d9e50524f 100644
--- a/src/feature/relay/dns.c
+++ b/src/feature/relay/dns.c
@@ -1691,7 +1691,7 @@ launch_one_resolve(const char *address, uint8_t query_type,
log_warn(LD_BUG, "Called with PTR query and unexpected address family");
break;
default:
- log_warn(LD_BUG, "Called with unexpectd query type %d", (int)query_type);
+ log_warn(LD_BUG, "Called with unexpected query type %d", (int)query_type);
break;
}
diff --git a/src/feature/relay/ext_orport.c b/src/feature/relay/ext_orport.c
index 2cf30262f5..1bb8741e45 100644
--- a/src/feature/relay/ext_orport.c
+++ b/src/feature/relay/ext_orport.c
@@ -391,7 +391,7 @@ connection_ext_or_auth_handle_client_hash(connection_t *conn)
}
/** Handle data from <b>or_conn</b> received on Extended ORPort.
- * Return -1 on error. 0 on unsufficient data. 1 on correct. */
+ * Return -1 on error. 0 on insufficient data. 1 on correct. */
static int
connection_ext_or_auth_process_inbuf(or_connection_t *or_conn)
{
diff --git a/src/feature/relay/relay_config.c b/src/feature/relay/relay_config.c
index fac6a2f577..c4a5d7f572 100644
--- a/src/feature/relay/relay_config.c
+++ b/src/feature/relay/relay_config.c
@@ -36,6 +36,7 @@
#include "feature/nodelist/nickname.h"
#include "feature/stats/geoip_stats.h"
#include "feature/stats/predict_ports.h"
+#include "feature/stats/connstats.h"
#include "feature/stats/rephist.h"
#include "feature/dirauth/authmode.h"
@@ -132,12 +133,208 @@ port_warn_nonlocal_ext_orports(const smartlist_t *ports, const char *portname)
} SMARTLIST_FOREACH_END(port);
}
+/**
+ * Return a static buffer describing the port number in @a port, which may
+ * CFG_AUTO_PORT.
+ **/
+static const char *
+describe_portnum(int port)
+{
+ static char buf[16];
+ if (port == CFG_AUTO_PORT) {
+ return "auto";
+ } else {
+ tor_snprintf(buf, sizeof(buf), "%d", port);
+ return buf;
+ }
+}
+
+/** Return a static buffer containing the human readable logging string that
+ * describes the given port object. */
+STATIC const char *
+describe_relay_port(const port_cfg_t *port)
+{
+ IF_BUG_ONCE(!port) {
+ return "<null port>";
+ }
+
+ static char buf[256];
+ const char *type, *addr;
+
+ switch (port->type) {
+ case CONN_TYPE_OR_LISTENER:
+ type = "OR";
+ break;
+ case CONN_TYPE_DIR_LISTENER:
+ type = "Dir";
+ break;
+ case CONN_TYPE_EXT_OR_LISTENER:
+ type = "ExtOR";
+ break;
+ default:
+ type = "";
+ break;
+ }
+
+ if (port->explicit_addr) {
+ addr = fmt_and_decorate_addr(&port->addr);
+ } else {
+ addr = "";
+ }
+
+ tor_snprintf(buf, sizeof(buf), "%sPort %s%s%s",
+ type, addr, (strlen(addr) > 0) ? ":" : "",
+ describe_portnum(port->port));
+ return buf;
+}
+
+/** Return true iff port p1 is equal to p2.
+ *
+ * This does a field by field comparaison. */
+static bool
+port_cfg_eq(const port_cfg_t *p1, const port_cfg_t *p2)
+{
+ bool ret = true;
+
+ tor_assert(p1);
+ tor_assert(p2);
+
+ /* Address, port and type. */
+ ret &= tor_addr_eq(&p1->addr, &p2->addr);
+ ret &= (p1->port == p2->port);
+ ret &= (p1->type == p2->type);
+
+ /* Mode. */
+ ret &= (p1->is_unix_addr == p2->is_unix_addr);
+ ret &= (p1->is_group_writable == p2->is_group_writable);
+ ret &= (p1->is_world_writable == p2->is_world_writable);
+ ret &= (p1->relax_dirmode_check == p2->relax_dirmode_check);
+ ret &= (p1->explicit_addr == p2->explicit_addr);
+
+ /* Entry config flags. */
+ ret &= tor_memeq(&p1->entry_cfg, &p2->entry_cfg,
+ sizeof(entry_port_cfg_t));
+ /* Server config flags. */
+ ret &= tor_memeq(&p1->server_cfg, &p2->server_cfg,
+ sizeof(server_port_cfg_t));
+ /* Unix address path if any. */
+ ret &= !strcmp(p1->unix_addr, p2->unix_addr);
+
+ return ret;
+}
+
+/** Attempt to find duplicate ORPort that would be superseded by another and
+ * remove them from the given ports list. This is possible if we have for
+ * instance:
+ *
+ * ORPort 9050
+ * ORPort [4242::1]:9050
+ *
+ * First one binds to both v4 and v6 address but second one is specific to an
+ * address superseding the global bind one.
+ *
+ * Another example is this one:
+ *
+ * ORPort 9001
+ * ORPort [4242::1]:9002
+ * ORPort [4242::2]:9003
+ *
+ * In this case, all IPv4 and IPv6 are kept since we do allow multiple ORPorts
+ * but the published port will be the first explicit one if any to be
+ * published or else the implicit.
+ *
+ * The following is O(n^2) but it is done at bootstrap or config reload and
+ * the list is not very long usually. */
+STATIC void
+remove_duplicate_orports(smartlist_t *ports)
+{
+ /* First we'll decide what to remove, then we'll remove it. */
+ bool *removing = tor_calloc(smartlist_len(ports), sizeof(bool));
+
+ for (int i = 0; i < smartlist_len(ports); ++i) {
+ const port_cfg_t *current = smartlist_get(ports, i);
+ if (removing[i]) {
+ continue;
+ }
+
+ /* Skip non ORPorts. */
+ if (current->type != CONN_TYPE_OR_LISTENER) {
+ continue;
+ }
+
+ for (int j = 0; j < smartlist_len(ports); ++j) {
+ const port_cfg_t *next = smartlist_get(ports, j);
+
+ /* Avoid comparing the same object. */
+ if (current == next) {
+ continue;
+ }
+ if (removing[j]) {
+ continue;
+ }
+ /* Skip non ORPorts. */
+ if (next->type != CONN_TYPE_OR_LISTENER) {
+ continue;
+ }
+ /* Remove duplicates. */
+ if (port_cfg_eq(current, next)) {
+ removing[j] = true;
+ continue;
+ }
+ /* Don't compare addresses of different family. */
+ if (tor_addr_family(&current->addr) != tor_addr_family(&next->addr)) {
+ continue;
+ }
+ /* At this point, we have a port of the same type and same address
+ * family. Now, we want to avoid comparing addresses that are different
+ * but are both explicit. As an example, these are not duplicates:
+ *
+ * ORPort 127.0.0.:9001 NoAdvertise
+ * ORPort 1.2.3.4:9001 NoListen
+ *
+ * Any implicit address must be considered for removal since an explicit
+ * one will always supersedes it. */
+ if (!tor_addr_eq(&current->addr, &next->addr) &&
+ current->explicit_addr && next->explicit_addr) {
+ continue;
+ }
+
+ /* Port value is the same so we either have a duplicate or a port that
+ * supersedes another. */
+ if (current->port == next->port) {
+ /* Do not remove the explicit address. As stated before above, we keep
+ * explicit addresses which supersedes implicit ones. */
+ if (!current->explicit_addr && next->explicit_addr) {
+ continue;
+ }
+ removing[j] = true;
+ char *next_str = tor_strdup(describe_relay_port(next));
+ log_warn(LD_CONFIG, "Configuration port %s superseded by %s",
+ next_str, describe_relay_port(current));
+ tor_free(next_str);
+ }
+ }
+ }
+
+ /* Iterate over array in reverse order to keep indices valid. */
+ for (int i = smartlist_len(ports)-1; i >= 0; --i) {
+ tor_assert(i < smartlist_len(ports));
+ if (removing[i]) {
+ port_cfg_t *current = smartlist_get(ports, i);
+ smartlist_del_keeporder(ports, i);
+ port_cfg_free(current);
+ }
+ }
+
+ tor_free(removing);
+}
+
/** 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,
+check_and_prune_server_ports(smartlist_t *ports,
const or_options_t *options,
int *n_low_ports_out)
{
@@ -158,6 +355,9 @@ check_server_ports(const smartlist_t *ports,
int n_low_port = 0;
int r = 0;
+ /* Remove possible duplicate ORPorts before inspecting the list. */
+ remove_duplicate_orports(ports);
+
SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) {
if (port->type == CONN_TYPE_DIR_LISTENER) {
if (! port->server_cfg.no_advertise)
@@ -270,6 +470,14 @@ port_parse_ports_relay(or_options_t *options,
goto err;
}
if (port_parse_config(ports,
+ options->ORPort_lines,
+ "OR", CONN_TYPE_OR_LISTENER,
+ "[::]", 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,
@@ -286,7 +494,7 @@ port_parse_ports_relay(or_options_t *options,
goto err;
}
- if (check_server_ports(ports, options, &n_low_ports) < 0) {
+ if (check_and_prune_server_ports(ports, options, &n_low_ports) < 0) {
*msg = tor_strdup("Misconfigured server ports");
goto err;
}
@@ -904,7 +1112,7 @@ options_validate_relay_mode(const or_options_t *old_options,
"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");
+ "https://bugs.torproject.org/tpo/core/tor/8742.");
if (options->BridgeRelay && options->DirPort_set) {
log_warn(LD_CONFIG, "Can't set a DirPort on a bridge relay; disabling "
@@ -1029,7 +1237,7 @@ options_transition_affects_descriptor(const or_options_t *old_options,
YES_IF_CHANGED_STRING(DataDirectory);
YES_IF_CHANGED_STRING(Nickname);
- YES_IF_CHANGED_STRING(Address);
+ YES_IF_CHANGED_LINELIST(Address);
YES_IF_CHANGED_LINELIST(ExitPolicy);
YES_IF_CHANGED_BOOL(ExitRelay);
YES_IF_CHANGED_BOOL(ExitPolicyRejectPrivate);
@@ -1114,8 +1322,6 @@ options_act_relay(const or_options_t *old_options)
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();
}
@@ -1309,7 +1515,7 @@ options_act_relay_stats(const or_options_t *old_options,
}
if ((!old_options || !old_options->ConnDirectionStatistics) &&
options->ConnDirectionStatistics) {
- rep_hist_conn_stats_init(now);
+ conn_stats_init(now);
}
if ((!old_options || !old_options->HiddenServiceStatistics) &&
options->HiddenServiceStatistics) {
@@ -1339,7 +1545,7 @@ options_act_relay_stats(const or_options_t *old_options,
rep_hist_exit_stats_term();
if (old_options && old_options->ConnDirectionStatistics &&
!options->ConnDirectionStatistics)
- rep_hist_conn_stats_term();
+ conn_stats_terminate();
return 0;
}
diff --git a/src/feature/relay/relay_config.h b/src/feature/relay/relay_config.h
index c70c322d88..d36863a1a1 100644
--- a/src/feature/relay/relay_config.h
+++ b/src/feature/relay/relay_config.h
@@ -84,9 +84,16 @@ int options_act_relay_dir(const struct or_options_t *old_options);
#ifdef RELAY_CONFIG_PRIVATE
+STATIC void remove_duplicate_orports(struct smartlist_t *ports);
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);
+#ifdef TOR_UNIT_TESTS
+
+struct port_cfg_t;
+STATIC const char *describe_relay_port(const struct port_cfg_t *port);
+
+#endif /* TOR_UNIT_TESTS */
#endif /* defined(RELAY_CONFIG_PRIVATE) */
diff --git a/src/feature/relay/relay_find_addr.c b/src/feature/relay/relay_find_addr.c
index 86cd799d42..c43885af51 100644
--- a/src/feature/relay/relay_find_addr.c
+++ b/src/feature/relay/relay_find_addr.c
@@ -12,122 +12,228 @@
#include "app/config/resolve_addr.h"
#include "core/mainloop/mainloop.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "core/or/extendinfo.h"
#include "feature/control/control_events.h"
#include "feature/dircommon/dir_connection_st.h"
+#include "feature/nodelist/dirlist.h"
+#include "feature/nodelist/node_select.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerstatus_st.h"
#include "feature/relay/relay_find_addr.h"
#include "feature/relay/router.h"
#include "feature/relay/routermode.h"
-/** The most recently guessed value of our IP address, based on directory
- * headers. */
-static tor_addr_t last_guessed_ip = TOR_ADDR_NULL;
-
-/** We failed to resolve our address locally, but we'd like to build
- * a descriptor and publish / test reachability. If we have a guess
- * about our address based on directory headers, answer it and return
- * 0; else return -1. */
-static int
-router_guess_address_from_dir_headers(uint32_t *guess)
-{
- if (!tor_addr_is_null(&last_guessed_ip)) {
- *guess = tor_addr_to_ipv4h(&last_guessed_ip);
- return 0;
- }
- return -1;
-}
-
-/** A directory server <b>d_conn</b> told us our IP address is
- * <b>suggestion</b>.
- * If this address is different from the one we think we are now, and
- * if our computer doesn't actually know its IP address, then switch. */
+/** Consider the address suggestion suggested_addr as a possible one to use as
+ * our address.
+ *
+ * This is called when a valid NETINFO cell is received containing a candidate
+ * for our address or when a directory sends us back the X-Your-Address-Is
+ * header.
+ *
+ * The suggested address is ignored if it does NOT come from a trusted source.
+ * At the moment, we only look a trusted directory authorities.
+ *
+ * The suggested address is ignored if it is internal or it is the same as the
+ * given peer_addr which is the address from the endpoint that sent the
+ * NETINFO cell.
+ *
+ * The identity_digest is NULL if this is an address suggested by a directory
+ * since this is a plaintext connection.
+ *
+ * The suggested address is set in our suggested address cache if everything
+ * passes. */
void
-router_new_address_suggestion(const char *suggestion,
- const dir_connection_t *d_conn)
+relay_address_new_suggestion(const tor_addr_t *suggested_addr,
+ const tor_addr_t *peer_addr,
+ const char *identity_digest)
{
- tor_addr_t addr;
- uint32_t cur = 0; /* Current IPv4 address. */
const or_options_t *options = get_options();
- /* first, learn what the IP address actually is */
- if (tor_addr_parse(&addr, suggestion) == -1) {
- log_debug(LD_DIR, "Malformed X-Your-Address-Is header %s. Ignoring.",
- escaped(suggestion));
- return;
- }
-
- log_debug(LD_DIR, "Got X-Your-Address-Is: %s.", suggestion);
+ tor_assert(suggested_addr);
+ tor_assert(peer_addr);
+ /* Non server should just ignore this suggestion. Clients don't need to
+ * learn their address let alone cache it. */
if (!server_mode(options)) {
- tor_addr_copy(&last_guessed_ip, &addr);
return;
}
- /* XXXX ipv6 */
- cur = get_last_resolved_addr();
- if (cur ||
- resolve_my_address(LOG_INFO, options, &cur, NULL, NULL) >= 0) {
- /* We're all set -- we already know our address. Great. */
- tor_addr_from_ipv4h(&last_guessed_ip, cur); /* store it in case we
- need it later */
+ /* Is the peer a trusted source? Ignore anything coming from non trusted
+ * source. In this case, we only look at trusted directory authorities. */
+ if (!router_addr_is_trusted_dir(peer_addr) ||
+ (identity_digest && !router_digest_is_trusted_dir(identity_digest))) {
return;
}
- if (tor_addr_is_internal(&addr, 0)) {
- /* Don't believe anybody who says our IP is, say, 127.0.0.1. */
+
+ /* Ignore a suggestion that is an internal address or the same as the one
+ * the peer address. */
+ if (tor_addr_is_internal(suggested_addr, 0)) {
+ /* Do not believe anyone who says our address is internal. */
return;
}
- if (tor_addr_eq(&d_conn->base_.addr, &addr)) {
- /* Don't believe anybody who says our IP is their IP. */
- log_debug(LD_DIR, "A directory server told us our IP address is %s, "
- "but they are just reporting their own IP address. Ignoring.",
- suggestion);
+ if (tor_addr_eq(suggested_addr, peer_addr)) {
+ /* Do not believe anyone who says our address is their address. */
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "A relay endpoint %s is telling us that their address is ours.",
+ fmt_addr(peer_addr));
return;
}
- /* Okay. We can't resolve our own address, and X-Your-Address-Is is giving
- * us an answer different from what we had the last time we managed to
- * resolve it. */
- if (!tor_addr_eq(&last_guessed_ip, &addr)) {
- control_event_server_status(LOG_NOTICE,
- "EXTERNAL_ADDRESS ADDRESS=%s METHOD=DIRSERV",
- suggestion);
- log_addr_has_changed(LOG_NOTICE, &last_guessed_ip, &addr,
- d_conn->base_.address);
- ip_address_changed(0);
- tor_addr_copy(&last_guessed_ip, &addr); /* router_rebuild_descriptor()
- will fetch it */
- }
+ /* Save the suggestion in our cache. */
+ resolved_addr_set_suggested(suggested_addr);
}
-/** Make a current best guess at our address, either because
- * it's configured in torrc, or because we've learned it from
- * dirserver headers. Place the answer in *<b>addr</b> and return
- * 0 on success, else return -1 if we have no guess.
+/** Find our address to be published in our descriptor. Three places are
+ * looked at:
+ *
+ * 1. Resolved cache. Populated by find_my_address() during the relay
+ * periodic event that attempts to learn if our address has changed.
+ *
+ * 2. If flags is set with RELAY_FIND_ADDR_CACHE_ONLY, only the resolved
+ * and suggested cache are looked at. No address discovery will be done.
+ *
+ * 3. Finally, if all fails, use the suggested address cache which is
+ * populated by the NETINFO cell content or HTTP header from a
+ * directory.
*
- * If <b>cache_only</b> is true, just return any cached answers, and
- * don't try to get any new answers.
- */
-MOCK_IMPL(int,
-router_pick_published_address, (const or_options_t *options, uint32_t *addr,
- int cache_only))
+ * The AddressDisableIPv6 is checked here for IPv6 address discovery and if
+ * set, false is returned and addr_out is UNSPEC.
+ *
+ * Before doing any discovery, the configuration is checked for an ORPort of
+ * the given family. If none can be found, false is returned and addr_out is
+ * UNSPEC.
+ *
+ * Return true on success and addr_out contains the address to use for the
+ * given family. On failure to find the address, false is returned and
+ * addr_out is set to an AF_UNSPEC address. */
+MOCK_IMPL(bool,
+relay_find_addr_to_publish, (const or_options_t *options, int family,
+ int flags, tor_addr_t *addr_out))
{
- /* First, check the cached output from resolve_my_address(). */
- *addr = get_last_resolved_addr();
- if (*addr)
- return 0;
-
- /* Second, consider doing a resolve attempt right here. */
- if (!cache_only) {
- if (resolve_my_address(LOG_INFO, options, addr, NULL, NULL) >= 0) {
- log_info(LD_CONFIG,"Success: chose address '%s'.", fmt_addr32(*addr));
- return 0;
+ tor_assert(options);
+ tor_assert(addr_out);
+
+ tor_addr_make_unspec(addr_out);
+
+ /* If an IPv6 is requested, check if IPv6 address discovery is disabled on
+ * this instance. If so, we return a failure. It is done here so we don't
+ * query the suggested cache that might be populated with an IPv6. */
+ if (family == AF_INET6 && options->AddressDisableIPv6) {
+ return false;
+ }
+
+ /* There is no point on attempting an address discovery to publish if we
+ * don't have an ORPort for this family. */
+ if (!routerconf_find_or_port(options, family)) {
+ return false;
+ }
+
+ /* First, check our resolved address cache. It should contain the address
+ * we've discovered from the periodic relay event. */
+ resolved_addr_get_last(family, addr_out);
+ if (!tor_addr_is_null(addr_out)) {
+ goto found;
+ }
+
+ /* Second, attempt to find our address. The following can do a DNS resolve
+ * thus only do it when the no cache only flag is flipped. */
+ if (!(flags & RELAY_FIND_ADDR_CACHE_ONLY)) {
+ if (find_my_address(options, family, LOG_INFO, addr_out, NULL, NULL)) {
+ goto found;
}
}
- /* Third, check the cached output from router_new_address_suggestion(). */
- if (router_guess_address_from_dir_headers(addr) >= 0)
- return 0;
+ /* Third, consider address from our suggestion cache. */
+ resolved_addr_get_suggested(family, addr_out);
+ if (!tor_addr_is_null(addr_out)) {
+ goto found;
+ }
+
+ /* No publishable address was found even though we have an ORPort thus
+ * print a notice log so operator can notice. We'll do that every hour so
+ * it is not too spammy but enough so operators address the issue. */
+ static ratelim_t rlim = RATELIM_INIT(3600);
+ log_fn_ratelim(&rlim, LOG_NOTICE, LD_CONFIG,
+ "Unable to find %s address for ORPort %u. "
+ "You might want to specify %sOnly to it or set an "
+ "explicit address or set Address.",
+ fmt_af_family(family),
+ routerconf_find_or_port(options, family),
+ (family == AF_INET) ? fmt_af_family(AF_INET6) :
+ fmt_af_family(AF_INET));
+
+ /* Not found. */
+ return false;
+
+ found:
+ return true;
+}
+
+/** How often should we launch a circuit to an authority to be sure of getting
+ * a guess for our IP? */
+#define DUMMY_DOWNLOAD_INTERVAL (20*60)
+
+void
+relay_addr_learn_from_dirauth(void)
+{
+ static time_t last_dummy_circuit = 0;
+ const or_options_t *options = get_options();
+ time_t now = time(NULL);
+ bool have_addr;
+ tor_addr_t addr_out;
+
+ /* This dummy circuit only matter for relays. */
+ if (BUG(!server_mode(options))) {
+ return;
+ }
+
+ /* Lookup the address cache to learn if we have a good usable address. We
+ * still force relays to have an IPv4 so that alone is enough to learn if we
+ * need a lookup. In case we don't have one, we might want to attempt a
+ * dummy circuit to learn our address as a suggestion from an authority. */
+ have_addr = relay_find_addr_to_publish(options, AF_INET,
+ RELAY_FIND_ADDR_CACHE_ONLY,
+ &addr_out);
+
+ /* If we're a relay or bridge for which we were unable to discover our
+ * public address, we rely on learning our address from a directory
+ * authority from the NETINFO cell. */
+ if (!have_addr && last_dummy_circuit + DUMMY_DOWNLOAD_INTERVAL < now) {
+ last_dummy_circuit = now;
+
+ const routerstatus_t *rs = router_pick_trusteddirserver(V3_DIRINFO, 0);
+ if (BUG(!rs)) {
+ /* We should really always have trusted directories configured at this
+ * stage. They are loaded early either from default list or the one
+ * given in the configuration file. */
+ return;
+ }
+ const node_t *node = node_get_by_id(rs->identity_digest);
+ if (!node) {
+ /* This can happen if we are still in the early starting stage where no
+ * descriptors we actually fetched and thus we have the routerstatus_t
+ * for the authority but not its descriptor which is needed to build a
+ * circuit and thus learn our address. */
+ log_info(LD_GENERAL, "Can't build a circuit to an authority. Unable to "
+ "learn for now our address from them.");
+ return;
+ }
+ extend_info_t *ei = extend_info_from_node(node, 1);
+ if (BUG(!ei)) {
+ return;
+ }
- /* We have no useful cached answers. Return failure. */
- return -1;
+ log_debug(LD_GENERAL, "Attempting dummy testing circuit to an authority "
+ "in order to learn our address.");
+
+ /* Launch a one-hop testing circuit to a trusted authority so we can learn
+ * our address through the NETINFO cell. */
+ circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
+ CIRCLAUNCH_IS_INTERNAL |
+ CIRCLAUNCH_ONEHOP_TUNNEL);
+ extend_info_free(ei);
+ }
}
diff --git a/src/feature/relay/relay_find_addr.h b/src/feature/relay/relay_find_addr.h
index ac51a977e6..f049d1bd20 100644
--- a/src/feature/relay/relay_find_addr.h
+++ b/src/feature/relay/relay_find_addr.h
@@ -9,11 +9,20 @@
#ifndef TOR_RELAY_FIND_ADDR_H
#define TOR_RELAY_FIND_ADDR_H
-MOCK_DECL(int, router_pick_published_address,
- (const or_options_t *options, uint32_t *addr, int cache_only));
+typedef enum {
+ RELAY_FIND_ADDR_NO_FLAG = (1U << 0),
+ RELAY_FIND_ADDR_CACHE_ONLY = (1U << 1),
+} relay_find_addr_flags_t;
-void router_new_address_suggestion(const char *suggestion,
- const dir_connection_t *d_conn);
+void relay_address_new_suggestion(const tor_addr_t *suggested_addr,
+ const tor_addr_t *peer_addr,
+ const char *identity_digest);
+
+MOCK_DECL(bool, relay_find_addr_to_publish,
+ (const or_options_t *options, int family, int flags,
+ tor_addr_t *addr_out));
+
+void relay_addr_learn_from_dirauth(void);
#ifdef RELAY_FIND_ADDR_PRIVATE
diff --git a/src/feature/relay/relay_periodic.c b/src/feature/relay/relay_periodic.c
index bfe12cd0b0..a917d90f1a 100644
--- a/src/feature/relay/relay_periodic.c
+++ b/src/feature/relay/relay_periodic.c
@@ -6,12 +6,14 @@
/**
* @file relay_periodic.c
- * @brief Periodic functions for the relay subsytem
+ * @brief Periodic functions for the relay subsystem
**/
#include "orconfig.h"
#include "core/or/or.h"
+#include "app/config/resolve_addr.h"
+
#include "core/mainloop/periodic.h"
#include "core/mainloop/cpuworker.h" // XXXX use a pubsub event.
#include "core/mainloop/mainloop.h"
@@ -102,7 +104,7 @@ rotate_onion_key_callback(time_t now, const or_options_t *options)
log_info(LD_GENERAL,"Rotating onion key.");
rotate_onion_key();
cpuworkers_rotate_keyinfo();
- if (router_rebuild_descriptor(1)<0) {
+ if (!router_rebuild_descriptor(1)) {
log_info(LD_CONFIG, "Couldn't rebuild router descriptor");
}
if (advertised_server_mode() && !net_is_disabled())
@@ -204,36 +206,77 @@ reachability_warnings_callback(time_t now, const or_options_t *options)
have_completed_a_circuit()) {
/* every 20 minutes, check and complain if necessary */
const routerinfo_t *me = router_get_my_routerinfo();
- if (me && !check_whether_orport_reachable(options)) {
- char *address = tor_dup_ip(me->addr);
- if (address) {
- log_warn(LD_CONFIG,
- "Your server (%s:%d) has not managed to confirm that "
- "its ORPort is reachable. Relays do not publish descriptors "
- "until their ORPort and DirPort are reachable. Please check "
- "your firewalls, ports, address, /etc/hosts file, etc.",
- address, me->or_port);
- control_event_server_status(LOG_WARN,
- "REACHABILITY_FAILED ORADDRESS=%s:%d",
- address, me->or_port);
- tor_free(address);
+ bool v4_ok =
+ router_orport_seems_reachable(options,AF_INET);
+ bool v6_ok =
+ router_orport_seems_reachable(options,AF_INET6);
+ if (me && !(v4_ok && v6_ok)) {
+ /* We need to warn that one or more of our ORPorts isn't reachable.
+ * Determine which, and give a reasonable warning. */
+ char *address4 = tor_addr_to_str_dup(&me->ipv4_addr);
+ char *address6 = tor_addr_to_str_dup(&me->ipv6_addr);
+ if (address4 || address6) {
+ char *where4=NULL, *where6=NULL;
+ if (!v4_ok)
+ tor_asprintf(&where4, "%s:%d", address4, me->ipv4_orport);
+ if (!v6_ok)
+ tor_asprintf(&where6, "[%s]:%d", address6, me->ipv6_orport);
+ const char *opt_and = (!v4_ok && !v6_ok) ? "and" : "";
+
+ /* IPv4 reachability test worked but not the IPv6. We will _not_
+ * publish the descriptor if our IPv6 was configured. We will if it
+ * was auto discovered. */
+ if (v4_ok && !v6_ok && !resolved_addr_is_configured(AF_INET6)) {
+ static ratelim_t rlim = RATELIM_INIT(3600);
+ log_fn_ratelim(&rlim, LOG_NOTICE, LD_CONFIG,
+ "Auto-discovered IPv6 address %s has not been found "
+ "reachable. However, IPv4 address is reachable. "
+ "Publishing server descriptor without IPv6 address.",
+ where6 ? where6 : "");
+ /* Indicate we want to publish even if reachability test failed. */
+ mark_my_descriptor_if_omit_ipv6_changes("IPv4 is reachable. "
+ "IPv6 is not but was "
+ "auto-discovered", true);
+ } else {
+ log_warn(LD_CONFIG,
+ "Your server has not managed to confirm reachability for "
+ "its ORPort(s) at %s%s%s. Relays do not publish "
+ "descriptors until their ORPort and DirPort are "
+ "reachable. Please check your firewalls, ports, address, "
+ "/etc/hosts file, etc.",
+ where4?where4:"",
+ opt_and,
+ where6?where6:"");
+ }
+ tor_free(where4);
+ tor_free(where6);
+ if (!v4_ok) {
+ control_event_server_status(LOG_WARN,
+ "REACHABILITY_FAILED ORADDRESS=%s:%d",
+ address4, me->ipv4_orport);
+ }
+ if (!v6_ok) {
+ control_event_server_status(LOG_WARN,
+ "REACHABILITY_FAILED ORADDRESS=[%s]:%d",
+ address6, me->ipv6_orport);
+ }
}
+ tor_free(address4);
+ tor_free(address6);
}
- if (me && !check_whether_dirport_reachable(options)) {
- char *address = tor_dup_ip(me->addr);
- if (address) {
- log_warn(LD_CONFIG,
- "Your server (%s:%d) has not managed to confirm that its "
- "DirPort is reachable. Relays do not publish descriptors "
- "until their ORPort and DirPort are reachable. Please check "
- "your firewalls, ports, address, /etc/hosts file, etc.",
- address, me->dir_port);
- control_event_server_status(LOG_WARN,
- "REACHABILITY_FAILED DIRADDRESS=%s:%d",
- address, me->dir_port);
- tor_free(address);
- }
+ if (me && !router_dirport_seems_reachable(options)) {
+ char *address4 = tor_addr_to_str_dup(&me->ipv4_addr);
+ log_warn(LD_CONFIG,
+ "Your server (%s:%d) has not managed to confirm that its "
+ "DirPort is reachable. Relays do not publish descriptors "
+ "until their ORPort and DirPort are reachable. Please check "
+ "your firewalls, ports, address, /etc/hosts file, etc.",
+ address4, me->ipv4_dirport);
+ control_event_server_status(LOG_WARN,
+ "REACHABILITY_FAILED DIRADDRESS=%s:%d",
+ address4, me->ipv4_dirport);
+ tor_free(address4);
}
}
diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c
index 75a3d2f35c..2696b8633b 100644
--- a/src/feature/relay/router.c
+++ b/src/feature/relay/router.c
@@ -38,12 +38,14 @@
#include "feature/relay/dns.h"
#include "feature/relay/relay_config.h"
#include "feature/relay/relay_find_addr.h"
+#include "feature/relay/relay_periodic.h"
#include "feature/relay/router.h"
#include "feature/relay/routerkeys.h"
#include "feature/relay/routermode.h"
#include "feature/relay/selftest.h"
#include "lib/geoip/geoip.h"
#include "feature/stats/geoip_stats.h"
+#include "feature/stats/bwhist.h"
#include "feature/stats/rephist.h"
#include "lib/crypt_ops/crypto_ed25519.h"
#include "lib/crypt_ops/crypto_format.h"
@@ -136,6 +138,18 @@ static authority_cert_t *legacy_key_certificate = NULL;
* used by tor-gencert to sign new signing keys and make new key
* certificates. */
+/** Indicate if the IPv6 address should be omitted from the descriptor when
+ * publishing it. This can happen if the IPv4 is reachable but the
+ * auto-discovered IPv6 is not. We still publish the descriptor.
+ *
+ * Only relays should look at this and only for their descriptor.
+ *
+ * XXX: The real harder fix is to never put in the routerinfo_t a non
+ * reachable address and instead use the last resolved address cache to do
+ * reachability test or anything that has to do with what address tor thinks
+ * it has. */
+static bool omit_ipv6_on_publish = false;
+
/** Return a readonly string with human readable description
* of <b>err</b>.
*/
@@ -174,7 +188,7 @@ routerinfo_err_is_transient(int err)
/**
* For simplicity, we consider all errors other than
* "not a server" transient - see discussion on
- * https://trac.torproject.org/projects/tor/ticket/27034
+ * https://bugs.torproject.org/tpo/core/tor/27034.
*/
return err != TOR_ROUTERINFO_ERROR_NOT_A_SERVER;
}
@@ -384,7 +398,8 @@ MOCK_IMPL(crypto_pk_t *,
get_server_identity_key,(void))
{
tor_assert(server_identitykey);
- tor_assert(server_mode(get_options()));
+ tor_assert(server_mode(get_options()) ||
+ get_options()->command == CMD_KEY_EXPIRATION);
assert_identity_keys_ok();
return server_identitykey;
}
@@ -396,7 +411,9 @@ get_server_identity_key,(void))
int
server_identity_key_is_set(void)
{
- return server_mode(get_options()) && server_identitykey != NULL;
+ return (server_mode(get_options()) ||
+ get_options()->command == CMD_KEY_EXPIRATION) &&
+ server_identitykey != NULL;
}
/** Set the current client identity key to <b>k</b>.
@@ -831,53 +848,57 @@ router_initialize_tls_context(void)
* -1 if Tor should die,
*/
STATIC int
-router_write_fingerprint(int hashed)
+router_write_fingerprint(int hashed, int ed25519_identity)
{
- char *keydir = NULL, *cp = NULL;
+ char *keydir = NULL;
const char *fname = hashed ? "hashed-fingerprint" :
- "fingerprint";
+ (ed25519_identity ? "fingerprint-ed25519" :
+ "fingerprint");
char fingerprint[FINGERPRINT_LEN+1];
const or_options_t *options = get_options();
char *fingerprint_line = NULL;
int result = -1;
keydir = get_datadir_fname(fname);
- log_info(LD_GENERAL,"Dumping %sfingerprint to \"%s\"...",
- hashed ? "hashed " : "", keydir);
- if (!hashed) {
- if (crypto_pk_get_fingerprint(get_server_identity_key(),
- fingerprint, 0) < 0) {
- log_err(LD_GENERAL,"Error computing fingerprint");
- goto done;
- }
- } else {
- if (crypto_pk_get_hashed_fingerprint(get_server_identity_key(),
- fingerprint) < 0) {
- log_err(LD_GENERAL,"Error computing hashed fingerprint");
- goto done;
+ log_info(LD_GENERAL,"Dumping %s%s to \"%s\"...", hashed ? "hashed " : "",
+ ed25519_identity ? "ed25519 identity" : "fingerprint", keydir);
+
+ if (ed25519_identity) { /* ed25519 identity */
+ digest256_to_base64(fingerprint, (const char *)
+ get_master_identity_key()->pubkey);
+ } else { /* RSA identity */
+ if (!hashed) {
+ if (crypto_pk_get_fingerprint(get_server_identity_key(),
+ fingerprint, 0) < 0) {
+ log_err(LD_GENERAL,"Error computing fingerprint");
+ goto done;
+ }
+ } else {
+ if (crypto_pk_get_hashed_fingerprint(get_server_identity_key(),
+ fingerprint) < 0) {
+ log_err(LD_GENERAL,"Error computing hashed fingerprint");
+ goto done;
+ }
}
}
tor_asprintf(&fingerprint_line, "%s %s\n", options->Nickname, fingerprint);
/* Check whether we need to write the (hashed-)fingerprint file. */
-
- cp = read_file_to_str(keydir, RFTS_IGNORE_MISSING, NULL);
- if (!cp || strcmp(cp, fingerprint_line)) {
- if (write_str_to_file(keydir, fingerprint_line, 0)) {
- log_err(LD_FS, "Error writing %sfingerprint line to file",
- hashed ? "hashed " : "");
- goto done;
- }
+ if (write_str_to_file_if_not_equal(keydir, fingerprint_line)) {
+ log_err(LD_FS, "Error writing %s%s line to file",
+ hashed ? "hashed " : "",
+ ed25519_identity ? "ed25519 identity" : "fingerprint");
+ goto done;
}
- log_notice(LD_GENERAL, "Your Tor %s identity key fingerprint is '%s %s'",
- hashed ? "bridge's hashed" : "server's", options->Nickname,
- fingerprint);
+ log_notice(LD_GENERAL, "Your Tor %s identity key %s fingerprint is '%s %s'",
+ hashed ? "bridge's hashed" : "server's",
+ ed25519_identity ? "ed25519" : "",
+ options->Nickname, fingerprint);
result = 0;
done:
- tor_free(cp);
tor_free(keydir);
tor_free(fingerprint_line);
return result;
@@ -935,7 +956,7 @@ init_keys(void)
/* OP's don't need persistent keys; just make up an identity and
* initialize the TLS context. */
- if (!server_mode(options)) {
+ if (!server_mode(options) && !(options->command == CMD_KEY_EXPIRATION)) {
return init_keys_client();
}
if (init_keys_common() < 0)
@@ -1109,15 +1130,20 @@ init_keys(void)
}
}
- /* 5. Dump fingerprint and possibly hashed fingerprint to files. */
- if (router_write_fingerprint(0)) {
+ /* 5. Dump fingerprint, ed25519 identity and possibly hashed fingerprint
+ * to files. */
+ if (router_write_fingerprint(0, 0)) {
log_err(LD_FS, "Error writing fingerprint to file");
return -1;
}
- if (!public_server_mode(options) && router_write_fingerprint(1)) {
+ if (!public_server_mode(options) && router_write_fingerprint(1, 0)) {
log_err(LD_FS, "Error writing hashed fingerprint to file");
return -1;
}
+ if (router_write_fingerprint(0, 1)) {
+ log_err(LD_FS, "Error writing ed25519 identity to file");
+ return -1;
+ }
if (!authdir_mode(options))
return 0;
@@ -1134,10 +1160,12 @@ init_keys(void)
ds = router_get_trusteddirserver_by_digest(digest);
if (!ds) {
+ tor_addr_port_t ipv6_orport;
+ routerconf_find_ipv6_or_ap(options, &ipv6_orport);
ds = trusted_dir_server_new(options->Nickname, NULL,
- router_get_advertised_dir_port(options, 0),
- router_get_advertised_or_port(options),
- NULL,
+ routerconf_find_dir_port(options, 0),
+ routerconf_find_or_port(options,AF_INET),
+ &ipv6_orport,
digest,
v3_digest,
type, 0.0);
@@ -1288,10 +1316,10 @@ decide_to_advertise_dir_impl(const or_options_t *options,
return 1;
if (net_is_disabled())
return 0;
- if (dir_port && !router_get_advertised_dir_port(options, dir_port))
+ if (dir_port && !routerconf_find_dir_port(options, dir_port))
return 0;
if (supports_tunnelled_dir_requests &&
- !router_get_advertised_or_port(options))
+ !routerconf_find_or_port(options, AF_INET))
return 0;
/* Part two: consider config options that could make us choose to
@@ -1335,6 +1363,17 @@ should_refuse_unknown_exits(const or_options_t *options)
}
}
+/**
+ * If true, then we will publish our descriptor even if our own IPv4 ORPort
+ * seems to be unreachable.
+ **/
+static bool publish_even_when_ipv4_orport_unreachable = false;
+/**
+ * If true, then we will publish our descriptor even if our own IPv6 ORPort
+ * seems to be unreachable.
+ **/
+static bool publish_even_when_ipv6_orport_unreachable = false;
+
/** Decide if we're a publishable server. We are a publishable server if:
* - We don't have the ClientOnly option set
* and
@@ -1361,16 +1400,30 @@ decide_if_publishable_server(void)
return 0;
if (authdir_mode(options))
return 1;
- if (!router_get_advertised_or_port(options))
- return 0;
- if (!check_whether_orport_reachable(options))
+ if (!routerconf_find_or_port(options, AF_INET))
return 0;
+ if (!router_orport_seems_reachable(options, AF_INET)) {
+ // We have an ipv4 orport, and it doesn't seem reachable.
+ if (!publish_even_when_ipv4_orport_unreachable) {
+ return 0;
+ }
+ }
+ /* We could be flagged to omit the IPv6 and if so, don't check for
+ * reachability on the IPv6. This can happen if the address was
+ * auto-discovered but turns out to be non reachable. */
+ if (!omit_ipv6_on_publish &&
+ !router_orport_seems_reachable(options, AF_INET6)) {
+ // We have an ipv6 orport, and it doesn't seem reachable.
+ if (!publish_even_when_ipv6_orport_unreachable) {
+ return 0;
+ }
+ }
if (router_have_consensus_path() == CONSENSUS_PATH_INTERNAL) {
/* All set: there are no exits in the consensus (maybe this is a tiny
* test network), so we can't check our DirPort reachability. */
return 1;
} else {
- return check_whether_dirport_reachable(options);
+ return router_dirport_seems_reachable(options);
}
}
@@ -1390,10 +1443,9 @@ consider_publishable_server(int force)
return;
rebuilt = router_rebuild_descriptor(0);
- if (decide_if_publishable_server()) {
+ if (rebuilt && decide_if_publishable_server()) {
set_server_advertised(1);
- if (rebuilt == 0)
- router_upload_dir_desc_to_dirservers(force);
+ router_upload_dir_desc_to_dirservers(force);
} else {
set_server_advertised(0);
}
@@ -1420,22 +1472,14 @@ router_get_active_listener_port_by_type_af(int listener_type,
return 0;
}
-/** 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". Returns 0 if no port is found. */
-uint16_t
-router_get_advertised_or_port(const or_options_t *options)
-{
- return router_get_advertised_or_port_by_af(options, AF_INET);
-}
-
-/** As router_get_advertised_or_port(), but allows an address family argument.
- */
+/** Return the port that we should advertise as our ORPort in a given address
+ * family; this is either the one configured in the ORPort option, or the one
+ * we actually bound to if ORPort is "auto". Returns 0 if no port is found. */
uint16_t
-router_get_advertised_or_port_by_af(const or_options_t *options,
- sa_family_t family)
+routerconf_find_or_port(const or_options_t *options,
+ sa_family_t family)
{
- int port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
+ int port = portconf_get_first_advertised_port(CONN_TYPE_OR_LISTENER,
family);
(void)options;
@@ -1448,11 +1492,11 @@ 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
+/** As routerconf_find_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,
+routerconf_find_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
@@ -1463,11 +1507,10 @@ router_get_advertised_ipv6_or_ap(const or_options_t *options,
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(
+ const tor_addr_t *addr = portconf_get_first_advertised_addr(
CONN_TYPE_OR_LISTENER,
AF_INET6);
- const uint16_t port = router_get_advertised_or_port_by_af(
- options,
+ const uint16_t port = routerconf_find_or_port(options,
AF_INET6);
if (!addr || port == 0) {
@@ -1494,20 +1537,42 @@ router_get_advertised_ipv6_or_ap(const or_options_t *options,
/** Returns true if this router has an advertised IPv6 ORPort. */
bool
-router_has_advertised_ipv6_orport(const or_options_t *options)
+routerconf_has_ipv6_orport(const or_options_t *options)
{
- tor_addr_port_t ipv6_ap;
- router_get_advertised_ipv6_or_ap(options, &ipv6_ap);
- return tor_addr_port_is_valid_ap(&ipv6_ap, 0);
+ /* What we want here is to learn if we have configured an IPv6 ORPort.
+ * Remember, ORPort can listen on [::] and thus consider internal by
+ * router_get_advertised_ipv6_or_ap() since we do _not_ want to advertise
+ * such address. */
+ const tor_addr_t *addr =
+ portconf_get_first_advertised_addr(CONN_TYPE_OR_LISTENER, AF_INET6);
+ const uint16_t port =
+ routerconf_find_or_port(options, AF_INET6);
+
+ return tor_addr_port_is_valid(addr, port, 1);
}
-/** Returns true if this router has an advertised IPv6 ORPort. */
+/** Returns true if this router can extend over IPv6.
+ *
+ * This check should only be performed by relay extend code.
+ *
+ * Clients should check if relays can initiate and accept IPv6 extends using
+ * node_supports_initiating_ipv6_extends() and
+ * node_supports_accepting_ipv6_extends().
+ *
+ * As with other extends, relays should assume the client has already
+ * performed the relevant checks for the next hop. (Otherwise, relays that
+ * have just added IPv6 ORPorts won't be able to self-test those ORPorts.)
+ *
+ * Accepting relays don't need to perform any IPv6-specific checks before
+ * accepting a connection, because having an IPv6 ORPort implies support for
+ * the relevant protocol version.
+ */
MOCK_IMPL(bool,
router_can_extend_over_ipv6,(const or_options_t *options))
{
/* We might add some extra checks here, such as ExtendAllowIPv6Addresses
* from ticket 33818. */
- return router_has_advertised_ipv6_orport(options);
+ return routerconf_has_ipv6_orport(options);
}
/** Return the port that we should advertise as our DirPort;
@@ -1516,9 +1581,9 @@ router_can_extend_over_ipv6,(const or_options_t *options))
* the one configured in the DirPort option,
* or the one we actually bound to if DirPort is "auto". */
uint16_t
-router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport)
+routerconf_find_dir_port(const or_options_t *options, uint16_t dirport)
{
- int dirport_configured = get_primary_dir_port();
+ int dirport_configured = portconf_get_primary_dir_port();
(void)options;
if (!dirport_configured)
@@ -1682,6 +1747,31 @@ router_is_me(const routerinfo_t *router)
return router_digest_is_me(router->cache_info.identity_digest);
}
+/**
+ * Return true if we are a server, and if @a addr is an address we are
+ * currently publishing (or trying to publish) in our descriptor.
+ * Return false otherwise.
+ **/
+bool
+router_addr_is_my_published_addr(const tor_addr_t *addr)
+{
+ IF_BUG_ONCE(!addr)
+ return false;
+
+ const routerinfo_t *me = router_get_my_routerinfo();
+ if (!me)
+ return false;
+
+ switch (tor_addr_family(addr)) {
+ case AF_INET:
+ return tor_addr_eq(addr, &me->ipv4_addr);
+ case AF_INET6:
+ return tor_addr_eq(addr, &me->ipv6_addr);
+ default:
+ return false;
+ }
+}
+
/** Return a routerinfo for this OR, rebuilding a fresh one if
* necessary. Return NULL on error, or if called on an OP. */
MOCK_IMPL(const routerinfo_t *,
@@ -1704,16 +1794,6 @@ router_get_my_routerinfo_with_err,(int *err))
return NULL;
}
- if (!desc_clean_since) {
- int rebuild_err = router_rebuild_descriptor(0);
- if (rebuild_err < 0) {
- if (err)
- *err = rebuild_err;
-
- return NULL;
- }
- }
-
if (!desc_routerinfo) {
if (err)
*err = TOR_ROUTERINFO_ERROR_DESC_REBUILDING;
@@ -1752,7 +1832,7 @@ router_get_my_extrainfo(void)
{
if (!server_mode(get_options()))
return NULL;
- if (router_rebuild_descriptor(0))
+ if (!router_rebuild_descriptor(0))
return NULL;
return desc_extrainfo;
}
@@ -1769,54 +1849,55 @@ router_get_descriptor_gen_reason(void)
* ORPort or DirPort.
* listener_type is either CONN_TYPE_OR_LISTENER or CONN_TYPE_DIR_LISTENER. */
static void
-router_check_descriptor_address_port_consistency(uint32_t ipv4h_desc_addr,
+router_check_descriptor_address_port_consistency(const tor_addr_t *addr,
int listener_type)
{
+ int family, port_cfg;
+
+ tor_assert(addr);
tor_assert(listener_type == CONN_TYPE_OR_LISTENER ||
listener_type == CONN_TYPE_DIR_LISTENER);
- /* The first advertised Port may be the magic constant CFG_AUTO_PORT.
- */
- int port_v4_cfg = get_first_advertised_port_by_type_af(listener_type,
- AF_INET);
- if (port_v4_cfg != 0 &&
- !port_exists_by_type_addr32h_port(listener_type,
- ipv4h_desc_addr, port_v4_cfg, 1)) {
- const tor_addr_t *port_addr = get_first_advertised_addr_by_type_af(
- listener_type,
- AF_INET);
- /* If we're building a descriptor with no advertised address,
- * something is terribly wrong. */
- tor_assert(port_addr);
-
- tor_addr_t desc_addr;
- char port_addr_str[TOR_ADDR_BUF_LEN];
- char desc_addr_str[TOR_ADDR_BUF_LEN];
-
- tor_addr_to_str(port_addr_str, port_addr, TOR_ADDR_BUF_LEN, 0);
-
- tor_addr_from_ipv4h(&desc_addr, ipv4h_desc_addr);
- tor_addr_to_str(desc_addr_str, &desc_addr, TOR_ADDR_BUF_LEN, 0);
-
- const char *listener_str = (listener_type == CONN_TYPE_OR_LISTENER ?
- "OR" : "Dir");
- log_warn(LD_CONFIG, "The IPv4 %sPort address %s does not match the "
- "descriptor address %s. If you have a static public IPv4 "
- "address, use 'Address <IPv4>' and 'OutboundBindAddress "
- "<IPv4>'. If you are behind a NAT, use two %sPort lines: "
- "'%sPort <PublicPort> NoListen' and '%sPort <InternalPort> "
- "NoAdvertise'.",
- listener_str, port_addr_str, desc_addr_str, listener_str,
- listener_str, listener_str);
- }
-}
-
-/* Tor relays only have one IPv4 address in the descriptor, which is derived
- * from the Address torrc option, or guessed using various methods in
- * router_pick_published_address().
- * Warn the operator if there is no ORPort on the descriptor address
- * ipv4h_desc_addr.
+ family = tor_addr_family(addr);
+ /* The first advertised Port may be the magic constant CFG_AUTO_PORT. */
+ port_cfg = portconf_get_first_advertised_port(listener_type, family);
+ if (port_cfg != 0 &&
+ !port_exists_by_type_addr_port(listener_type, addr, port_cfg, 1)) {
+ const tor_addr_t *port_addr =
+ portconf_get_first_advertised_addr(listener_type, family);
+ /* If we're building a descriptor with no advertised address,
+ * something is terribly wrong. */
+ tor_assert(port_addr);
+
+ char port_addr_str[TOR_ADDR_BUF_LEN];
+ char desc_addr_str[TOR_ADDR_BUF_LEN];
+
+ tor_addr_to_str(port_addr_str, port_addr, TOR_ADDR_BUF_LEN, 0);
+ tor_addr_to_str(desc_addr_str, addr, TOR_ADDR_BUF_LEN, 0);
+
+ const char *listener_str = (listener_type == CONN_TYPE_OR_LISTENER ?
+ "OR" : "Dir");
+ const char *af_str = fmt_af_family(family);
+ log_warn(LD_CONFIG, "The %s %sPort address %s does not match the "
+ "descriptor address %s. If you have a static public IPv4 "
+ "address, use 'Address <%s>' and 'OutboundBindAddress "
+ "<%s>'. If you are behind a NAT, use two %sPort lines: "
+ "'%sPort <PublicPort> NoListen' and '%sPort <InternalPort> "
+ "NoAdvertise'.",
+ af_str, listener_str, port_addr_str, desc_addr_str, af_str,
+ af_str, listener_str, listener_str, listener_str);
+ }
+}
+
+/** Tor relays only have one IPv4 or/and one IPv6 address in the descriptor,
+ * which is derived from the Address torrc option, or guessed using various
+ * methods in relay_find_addr_to_publish().
+ *
+ * Warn the operator if there is no ORPort associated with the given address
+ * in addr.
+ *
* Warn the operator if there is no DirPort on the descriptor address.
+ *
* This catches a few common config errors:
* - operators who expect ORPorts and DirPorts to be advertised on the
* ports' listen addresses, rather than the torrc Address (or guessed
@@ -1825,20 +1906,22 @@ router_check_descriptor_address_port_consistency(uint32_t ipv4h_desc_addr,
* addresses;
* - discrepancies between guessed addresses and configured listen
* addresses (when the Address option isn't set).
+ *
* If a listener is listening on all IPv4 addresses, it is assumed that it
* is listening on the configured Address, and no messages are logged.
+ *
* If an operators has specified NoAdvertise ORPorts in a NAT setting,
* no messages are logged, unless they have specified other advertised
* addresses.
+ *
* The message tells operators to configure an ORPort and DirPort that match
- * the Address (using NoListen if needed).
- */
+ * the Address (using NoListen if needed). */
static void
-router_check_descriptor_address_consistency(uint32_t ipv4h_desc_addr)
+router_check_descriptor_address_consistency(const tor_addr_t *addr)
{
- router_check_descriptor_address_port_consistency(ipv4h_desc_addr,
+ router_check_descriptor_address_port_consistency(addr,
CONN_TYPE_OR_LISTENER);
- router_check_descriptor_address_port_consistency(ipv4h_desc_addr,
+ router_check_descriptor_address_port_consistency(addr,
CONN_TYPE_DIR_LISTENER);
}
@@ -1980,7 +2063,7 @@ MOCK_IMPL(STATIC int,
router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
{
routerinfo_t *ri = NULL;
- uint32_t addr;
+ tor_addr_t ipv4_addr;
char platform[256];
int hibernating = we_are_hibernating();
const or_options_t *options = get_options();
@@ -1991,22 +2074,39 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
goto err;
}
- if (router_pick_published_address(options, &addr, 0) < 0) {
- log_warn(LD_CONFIG, "Don't know my address while generating descriptor");
+ /* Find our resolved address both IPv4 and IPv6. In case the address is not
+ * found, the object is set to an UNSPEC address. */
+ bool have_v4 = relay_find_addr_to_publish(options, AF_INET,
+ RELAY_FIND_ADDR_NO_FLAG,
+ &ipv4_addr);
+ /* Tor requires a relay to have an IPv4 so bail if we can't find it. */
+ if (!have_v4) {
+ log_info(LD_CONFIG, "Don't know my address while generating descriptor. "
+ "Launching circuit to authority to learn it.");
+ relay_addr_learn_from_dirauth();
result = TOR_ROUTERINFO_ERROR_NO_EXT_ADDR;
goto err;
}
-
/* Log a message if the address in the descriptor doesn't match the ORPort
* and DirPort addresses configured by the operator. */
- router_check_descriptor_address_consistency(addr);
+ router_check_descriptor_address_consistency(&ipv4_addr);
ri = tor_malloc_zero(sizeof(routerinfo_t));
+ tor_addr_copy(&ri->ipv4_addr, &ipv4_addr);
ri->cache_info.routerlist_index = -1;
ri->nickname = tor_strdup(options->Nickname);
- ri->addr = addr;
- ri->or_port = router_get_advertised_or_port(options);
- ri->dir_port = router_get_advertised_dir_port(options, 0);
+
+ /* IPv4. */
+ ri->ipv4_orport = routerconf_find_or_port(options, AF_INET);
+ ri->ipv4_dirport = routerconf_find_dir_port(options, 0);
+
+ /* Optionally check for an IPv6. We still publish without one. */
+ if (relay_find_addr_to_publish(options, AF_INET6, RELAY_FIND_ADDR_NO_FLAG,
+ &ri->ipv6_addr)) {
+ ri->ipv6_orport = routerconf_find_or_port(options, AF_INET6);
+ router_check_descriptor_address_consistency(&ri->ipv6_addr);
+ }
+
ri->supports_tunnelled_dir_requests =
directory_permits_begindir_requests(options);
ri->cache_info.published_on = time(NULL);
@@ -2018,13 +2118,6 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
tor_memdup(&get_current_curve25519_keypair()->pubkey,
sizeof(curve25519_public_key_t));
- /* For now, at most one IPv6 or-address is being advertised. */
- tor_addr_port_t ipv6_orport;
- router_get_advertised_ipv6_or_ap(options, &ipv6_orport);
- /* If there is no valid 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,
ri->cache_info.identity_digest) < 0)) {
@@ -2046,13 +2139,14 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
ri->bandwidthburst = relay_get_effective_bwburst(options);
/* Report bandwidth, unless we're hibernating or shutting down */
- ri->bandwidthcapacity = hibernating ? 0 : rep_hist_bandwidth_assess();
+ ri->bandwidthcapacity = hibernating ? 0 : bwhist_bandwidth_assess();
if (dns_seems_to_be_broken() || has_dns_init_failed()) {
/* DNS is screwed up; don't claim to be an exit. */
policies_exit_policy_append_reject_star(&ri->exit_policy);
} else {
- policies_parse_exit_policy_from_options(options,ri->addr,&ri->ipv6_addr,
+ policies_parse_exit_policy_from_options(options, &ri->ipv4_addr,
+ &ri->ipv6_addr,
&ri->exit_policy);
}
ri->policy_is_reject_star =
@@ -2327,34 +2421,24 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e)
/** If <b>force</b> is true, or our descriptor is out-of-date, rebuild a fresh
* routerinfo, signed server descriptor, and extra-info document for this OR.
- * Return 0 on success, -1 on temporary error.
+ *
+ * Return true on success, else false on temporary error.
*/
-int
+bool
router_rebuild_descriptor(int force)
{
int err = 0;
routerinfo_t *ri;
extrainfo_t *ei;
- uint32_t addr;
- const or_options_t *options = get_options();
if (desc_clean_since && !force)
- return 0;
-
- if (router_pick_published_address(options, &addr, 0) < 0 ||
- router_get_advertised_or_port(options) == 0) {
- /* Stop trying to rebuild our descriptor every second. We'll
- * learn that it's time to try again when ip_address_changed()
- * marks it dirty. */
- desc_clean_since = time(NULL);
- return TOR_ROUTERINFO_ERROR_DESC_REBUILDING;
- }
+ return true;
log_info(LD_OR, "Rebuilding relay descriptor%s", force ? " (forced)" : "");
err = router_build_fresh_descriptor(&ri, &ei);
if (err < 0) {
- return err;
+ return false;
}
routerinfo_free(desc_routerinfo);
@@ -2370,7 +2454,41 @@ router_rebuild_descriptor(int force)
}
desc_dirty_reason = NULL;
control_event_my_descriptor_changed();
- return 0;
+ return true;
+}
+
+/** Called when we have a new set of consensus parameters. */
+void
+router_new_consensus_params(const networkstatus_t *ns)
+{
+ const int32_t DEFAULT_ASSUME_REACHABLE = 0;
+ const int32_t DEFAULT_ASSUME_REACHABLE_IPV6 = 0;
+ int ar, ar6;
+ ar = networkstatus_get_param(ns,
+ "assume-reachable",
+ DEFAULT_ASSUME_REACHABLE, 0, 1);
+ ar6 = networkstatus_get_param(ns,
+ "assume-reachable-ipv6",
+ DEFAULT_ASSUME_REACHABLE_IPV6, 0, 1);
+
+ publish_even_when_ipv4_orport_unreachable = ar;
+ publish_even_when_ipv6_orport_unreachable = ar || ar6;
+}
+
+/** Mark our descriptor out of data iff the IPv6 omit status flag is flipped
+ * it changes from its previous value.
+ *
+ * This is used when our IPv6 port is found reachable or not. */
+void
+mark_my_descriptor_if_omit_ipv6_changes(const char *reason, bool omit_ipv6)
+{
+ bool previous = omit_ipv6_on_publish;
+ omit_ipv6_on_publish = omit_ipv6;
+
+ /* Only mark it dirty if the IPv6 omit flag was flipped. */
+ if (previous != omit_ipv6) {
+ mark_my_descriptor_dirty(reason);
+ }
}
/** If our router descriptor ever goes this long without being regenerated
@@ -2431,11 +2549,13 @@ mark_my_descriptor_dirty(const char *reason)
if (BUG(reason == NULL)) {
reason = "marked descriptor dirty for unspecified reason";
}
- if (server_mode(options) && options->PublishServerDescriptor_)
+ if (server_mode(options) && options->PublishServerDescriptor_) {
log_info(LD_OR, "Decided to publish new relay descriptor: %s", reason);
+ }
desc_clean_since = 0;
if (!desc_dirty_reason)
desc_dirty_reason = reason;
+ reschedule_descriptor_update_check();
}
/** How frequently will we republish our descriptor because of large (factor
@@ -2474,7 +2594,7 @@ check_descriptor_bandwidth_changed(time_t now)
/* Consider ourselves to have zero bandwidth if we're hibernating or
* shutting down. */
- cur = hibernating ? 0 : rep_hist_bandwidth_assess();
+ cur = hibernating ? 0 : bwhist_bandwidth_assess();
if ((prev != cur && (!prev || !cur)) ||
cur > (prev * BANDWIDTH_CHANGE_FACTOR) ||
@@ -2523,48 +2643,69 @@ log_addr_has_changed(int severity,
}
ENABLE_GCC_WARNING("-Wmissing-noreturn")
-/** Check whether our own address as defined by the Address configuration
- * has changed. This is for routers that get their address from a service
- * like dyndns. If our address has changed, mark our descriptor dirty. */
+/** Check whether our own address has changed versus the one we have in our
+ * current descriptor.
+ *
+ * If our address has changed, call ip_address_changed() which takes
+ * appropriate actions. */
void
check_descriptor_ipaddress_changed(time_t now)
{
- uint32_t prev, cur;
- const or_options_t *options = get_options();
- const char *method = NULL;
- char *hostname = NULL;
const routerinfo_t *my_ri = router_get_my_routerinfo();
+ resolved_addr_method_t method = RESOLVED_ADDR_NONE;
+ char *hostname = NULL;
+ int families[2] = { AF_INET, AF_INET6 };
+ bool has_changed = false;
(void) now;
- if (my_ri == NULL) /* make sure routerinfo exists */
- return;
-
- /* XXXX ipv6 */
- prev = my_ri->addr;
- if (resolve_my_address(LOG_INFO, options, &cur, &method, &hostname) < 0) {
- log_info(LD_CONFIG,"options->Address didn't resolve into an IP.");
+ /* We can't learn our descriptor address without one. */
+ if (my_ri == NULL) {
return;
}
- if (prev != cur) {
- char *source;
- tor_addr_t tmp_prev, tmp_cur;
+ for (size_t i = 0; i < ARRAY_LENGTH(families); i++) {
+ tor_addr_t current;
+ const tor_addr_t *previous;
+ int family = families[i];
- tor_addr_from_ipv4h(&tmp_prev, prev);
- tor_addr_from_ipv4h(&tmp_cur, cur);
-
- tor_asprintf(&source, "METHOD=%s%s%s", method,
- hostname ? " HOSTNAME=" : "",
- hostname ? hostname : "");
+ /* Get the descriptor address from the family we are looking up. */
+ previous = &my_ri->ipv4_addr;
+ if (family == AF_INET6) {
+ previous = &my_ri->ipv6_addr;
+ }
- log_addr_has_changed(LOG_NOTICE, &tmp_prev, &tmp_cur, source);
- tor_free(source);
+ /* Attempt to discovery the publishable address for the family which will
+ * actively attempt to discover the address if we are configured with a
+ * port for the family.
+ *
+ * It is OK to ignore the returned value here since in the failure case,
+ * that is the address was not found, the current value is set to UNSPEC.
+ * Add this (void) so Coverity is happy. */
+ (void) relay_find_addr_to_publish(get_options(), family,
+ RELAY_FIND_ADDR_NO_FLAG, &current);
+
+ /* The "current" address might be UNSPEC meaning it was not discovered nor
+ * found in our current cache. If we had an address before and we have
+ * none now, we consider this an IP change since it appears the relay lost
+ * its address. */
+
+ if (!tor_addr_eq(previous, &current)) {
+ char *source;
+ tor_asprintf(&source, "METHOD=%s%s%s",
+ resolved_addr_method_to_str(method),
+ hostname ? " HOSTNAME=" : "",
+ hostname ? hostname : "");
+ log_addr_has_changed(LOG_NOTICE, previous, &current, source);
+ tor_free(source);
+ has_changed = true;
+ }
+ tor_free(hostname);
+ }
+ if (has_changed) {
ip_address_changed(0);
}
-
- tor_free(hostname);
}
/** Set <b>platform</b> (max length <b>len</b>) to a NUL-terminated short
@@ -2770,7 +2911,7 @@ router_dump_router_to_string(routerinfo_t *router,
}
}
- if (router->ipv6_orport &&
+ if (!omit_ipv6_on_publish && router->ipv6_orport &&
tor_addr_family(&router->ipv6_addr) == AF_INET6) {
char addr[TOR_ADDR_BUF_LEN];
const char *a;
@@ -2788,7 +2929,7 @@ router_dump_router_to_string(routerinfo_t *router,
proto_line = tor_strdup("");
}
- address = tor_dup_ip(router->addr);
+ address = tor_addr_to_str_dup(&router->ipv4_addr);
if (!address)
goto err;
@@ -2812,8 +2953,8 @@ router_dump_router_to_string(routerinfo_t *router,
"%s%s%s",
router->nickname,
address,
- router->or_port,
- router_should_advertise_dirport(options, router->dir_port),
+ router->ipv4_orport,
+ router_should_advertise_dirport(options, router->ipv4_dirport),
ed_cert_line ? ed_cert_line : "",
extra_or_address ? extra_or_address : "",
router->platform,
@@ -2859,11 +3000,9 @@ router_dump_router_to_string(routerinfo_t *router,
}
if (router->onion_curve25519_pkey) {
- char kbuf[128];
- base64_encode(kbuf, sizeof(kbuf),
- (const char *)router->onion_curve25519_pkey->public_key,
- CURVE25519_PUBKEY_LEN, BASE64_ENCODE_MULTILINE);
- smartlist_add_asprintf(chunks, "ntor-onion-key %s", kbuf);
+ char kbuf[CURVE25519_BASE64_PADDED_LEN + 1];
+ curve25519_public_to_base64(kbuf, router->onion_curve25519_pkey, false);
+ smartlist_add_asprintf(chunks, "ntor-onion-key %s\n", kbuf);
} else {
/* Authorities will start rejecting relays without ntor keys in 0.2.9 */
log_err(LD_BUG, "A relay must have an ntor onion key");
@@ -2993,57 +3132,77 @@ router_dump_exit_policy_to_string(const routerinfo_t *router,
include_ipv6);
}
-/** Load the contents of <b>filename</b>, find the last line starting with
- * <b>end_line</b>, ensure that its timestamp is not more than 25 hours in
- * the past or more than 1 hour in the future with respect to <b>now</b>,
- * and write the file contents starting with that line to *<b>out</b>.
- * Return 1 for success, 0 if the file does not exist or is empty, or -1
- * if the file does not contain a line matching these criteria or other
- * failure. */
-static int
-load_stats_file(const char *filename, const char *end_line, time_t now,
+/** Load the contents of <b>filename</b>, find a line starting with
+ * timestamp tag <b>ts_tag</b>, ensure that its timestamp is not more than 25
+ * hours in the past or more than 1 hour in the future with respect to
+ * <b>now</b>, and write the entire file contents into <b>out</b>.
+ *
+ * The timestamp expected should be an ISO-formatted UTC time value which is
+ * parsed using our parse_iso_time() function.
+ *
+ * In case more than one tag are found in the file, the very first one is
+ * used.
+ *
+ * Return 1 for success, 0 if the file does not exist or is empty, or -1 if
+ * the file does not contain a line with the timestamp tag. */
+STATIC int
+load_stats_file(const char *filename, const char *ts_tag, time_t now,
char **out)
{
int r = -1;
char *fname = get_datadir_fname(filename);
- char *contents, *start = NULL, *tmp, timestr[ISO_TIME_LEN+1];
+ char *contents = NULL, timestr[ISO_TIME_LEN+1];
time_t written;
+
switch (file_status(fname)) {
- case FN_FILE:
- /* X022 Find an alternative to reading the whole file to memory. */
- if ((contents = read_file_to_str(fname, 0, NULL))) {
- tmp = strstr(contents, end_line);
- /* Find last block starting with end_line */
- while (tmp) {
- start = tmp;
- tmp = strstr(tmp + 1, end_line);
- }
- if (!start)
- goto notfound;
- if (strlen(start) < strlen(end_line) + 1 + sizeof(timestr))
- goto notfound;
- strlcpy(timestr, start + 1 + strlen(end_line), sizeof(timestr));
- if (parse_iso_time(timestr, &written) < 0)
- goto notfound;
- if (written < now - (25*60*60) || written > now + (1*60*60))
- goto notfound;
- *out = tor_strdup(start);
- r = 1;
- }
- notfound:
- tor_free(contents);
- break;
- /* treat empty stats files as if the file doesn't exist */
- case FN_NOENT:
- case FN_EMPTY:
- r = 0;
- break;
- case FN_ERROR:
- case FN_DIR:
- default:
- break;
- }
+ case FN_FILE:
+ contents = read_file_to_str(fname, 0, NULL);
+ if (contents == NULL) {
+ log_debug(LD_BUG, "Unable to read content of %s", filename);
+ goto end;
+ }
+ /* Find the timestamp tag to validate that the file is not too old or if
+ * exists. */
+ const char *ts_tok = find_str_at_start_of_line(contents, ts_tag);
+ if (!ts_tok) {
+ log_warn(LD_BUG, "Token %s not found in file %s", ts_tag, filename);
+ goto end;
+ }
+ /* Do we have enough for parsing a timestamp? */
+ if (strlen(ts_tok) < strlen(ts_tag) + 1 + sizeof(timestr)) {
+ log_warn(LD_BUG, "Token %s malformed in file %s", ts_tag, filename);
+ goto end;
+ }
+ /* Parse timestamp in order to validate it is not too old. */
+ strlcpy(timestr, ts_tok + strlen(ts_tag) + 1, sizeof(timestr));
+ if (parse_iso_time(timestr, &written) < 0) {
+ log_warn(LD_BUG, "Token %s has a malformed timestamp in file %s",
+ ts_tag, filename);
+ goto end;
+ }
+ if (written < now - (25*60*60) || written > now + (1*60*60)) {
+ /* This can happen normally so don't log. */
+ goto end;
+ }
+ /* Success. Put in the entire content. */
+ *out = contents;
+ contents = NULL; /* Must not free it. */
+ r = 1;
+ break;
+ /* treat empty stats files as if the file doesn't exist */
+ case FN_NOENT:
+ case FN_EMPTY:
+ r = 0;
+ break;
+ case FN_ERROR:
+ case FN_DIR:
+ default:
+ break;
+ }
+
+ end:
tor_free(fname);
+ tor_free(contents);
return r;
}
@@ -3140,7 +3299,7 @@ extrainfo_dump_to_string_stats_helper(smartlist_t *chunks,
log_info(LD_GENERAL, "Adding stats to extra-info descriptor.");
/* Bandwidth usage stats don't have their own option */
{
- contents = rep_hist_get_bandwidth_lines();
+ contents = bwhist_get_bandwidth_lines();
smartlist_add(chunks, contents);
}
/* geoip hashes aren't useful unless we are publishing other stats */
@@ -3447,7 +3606,7 @@ router_set_rsa_onion_pkey(const crypto_pk_t *pk, char **onion_pkey_out,
}
/* From an ASN-1 encoded onion pkey, return a newly allocated RSA key object.
- * It is the caller responsability to free the returned object.
+ * It is the caller's responsibility to free the returned object.
*
* Return NULL if the pkey is NULL, malformed or if the length is 0. */
crypto_pk_t *
diff --git a/src/feature/relay/router.h b/src/feature/relay/router.h
index 50790a73dd..aa03c27142 100644
--- a/src/feature/relay/router.h
+++ b/src/feature/relay/router.h
@@ -65,14 +65,13 @@ 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,
+void routerconf_find_ipv6_or_ap(const or_options_t *options,
tor_addr_port_t *ipv6_ap_out);
-bool router_has_advertised_ipv6_orport(const or_options_t *options);
+bool routerconf_has_ipv6_orport(const or_options_t *options);
MOCK_DECL(bool, router_can_extend_over_ipv6,(const or_options_t *options));
-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,
+uint16_t routerconf_find_or_port(const or_options_t *options,
+ sa_family_t family);
+uint16_t routerconf_find_dir_port(const or_options_t *options,
uint16_t dirport);
int router_should_advertise_dirport(const or_options_t *options,
@@ -81,9 +80,12 @@ int router_should_advertise_dirport(const or_options_t *options,
void consider_publishable_server(int force);
int should_refuse_unknown_exits(const or_options_t *options);
+void router_new_consensus_params(const networkstatus_t *);
void router_upload_dir_desc_to_dirservers(int force);
void mark_my_descriptor_dirty_if_too_old(time_t now);
void mark_my_descriptor_dirty(const char *reason);
+void mark_my_descriptor_if_omit_ipv6_changes(const char *reason,
+ bool omit_ipv6);
void check_descriptor_bandwidth_changed(time_t now);
void check_descriptor_ipaddress_changed(time_t now);
int router_has_bandwidth_to_be_dirserver(const or_options_t *options);
@@ -98,8 +100,9 @@ int router_digest_is_me(const char *digest);
const uint8_t *router_get_my_id_digest(void);
int router_extrainfo_digest_is_me(const char *digest);
int router_is_me(const routerinfo_t *router);
+bool router_addr_is_my_published_addr(const tor_addr_t *addr);
int router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e);
-int router_rebuild_descriptor(int force);
+bool router_rebuild_descriptor(int force);
char *router_dump_router_to_string(routerinfo_t *router,
const crypto_pk_t *ident_key,
const crypto_pk_t *tap_key,
@@ -124,8 +127,10 @@ void router_free_all(void);
#ifdef ROUTER_PRIVATE
/* Used only by router.c and the unit tests */
STATIC void get_platform_str(char *platform, size_t len);
-STATIC int router_write_fingerprint(int hashed);
+STATIC int router_write_fingerprint(int hashed, int ed25519_identity);
STATIC smartlist_t *get_my_declared_family(const or_options_t *options);
+STATIC int load_stats_file(const char *filename, const char *ts_tag,
+ time_t now, char **out);
#ifdef TOR_UNIT_TESTS
extern time_t desc_clean_since;
diff --git a/src/feature/relay/routerkeys.c b/src/feature/relay/routerkeys.c
index d3de83cb86..116f0b4e3d 100644
--- a/src/feature/relay/routerkeys.c
+++ b/src/feature/relay/routerkeys.c
@@ -387,12 +387,10 @@ generate_ed_link_cert(const or_options_t *options, time_t now,
return 0;
}
- ed25519_public_key_t dummy_key;
- memcpy(dummy_key.pubkey, digests->d[DIGEST_SHA256], DIGEST256_LEN);
-
- link_cert = tor_cert_create(get_master_signing_keypair(),
+ link_cert = tor_cert_create_raw(get_master_signing_keypair(),
CERT_TYPE_SIGNING_LINK,
- &dummy_key,
+ SIGNED_KEY_TYPE_SHA256_OF_X509,
+ (const uint8_t*)digests->d[DIGEST_SHA256],
now,
options->TestingLinkCertLifetime, 0);
@@ -466,7 +464,7 @@ init_mock_ed_keys(const crypto_pk_t *rsa_identity_key)
MAKEKEY(master_signing_key);
MAKEKEY(current_auth_key);
#define MAKECERT(cert, signing, signed_, type, flags) \
- cert = tor_cert_create(signing, \
+ cert = tor_cert_create_ed25519(signing, \
type, \
&signed_->pubkey, \
time(NULL), 86400, \
@@ -519,19 +517,33 @@ print_cert_expiration(const char *expiration,
/**
* Log when a certificate, <b>cert</b>, with some <b>description</b> and
- * stored in a file named <b>fname</b>, is going to expire.
+ * stored in a file named <b>fname</b>, is going to expire. Formats the expire
+ * time according to <b>time_format</b>.
*/
static void
log_ed_cert_expiration(const tor_cert_t *cert,
const char *description,
- const char *fname) {
- char expiration[ISO_TIME_LEN+1];
-
+ const char *fname,
+ key_expiration_format_t time_format) {
if (BUG(!cert)) { /* If the specified key hasn't been loaded */
log_warn(LD_OR, "No %s key loaded; can't get certificate expiration.",
description);
} else {
- format_local_iso_time(expiration, cert->valid_until);
+ char expiration[ISO_TIME_LEN+1];
+ switch (time_format) {
+ case KEY_EXPIRATION_FORMAT_ISO8601:
+ format_local_iso_time(expiration, cert->valid_until);
+ break;
+
+ case KEY_EXPIRATION_FORMAT_TIMESTAMP:
+ tor_snprintf(expiration, sizeof(expiration), "%"PRId64,
+ (int64_t) cert->valid_until);
+ break;
+
+ default:
+ log_err(LD_BUG, "Unknown time format value: %d.", time_format);
+ return;
+ }
log_notice(LD_OR, "The %s certificate stored in %s is valid until %s.",
description, fname, expiration);
print_cert_expiration(expiration, description);
@@ -567,7 +579,8 @@ log_master_signing_key_cert_expiration(const or_options_t *options)
/* If we do have a signing key, log the expiration time. */
if (signing_key) {
- log_ed_cert_expiration(signing_key, "signing", fn);
+ key_expiration_format_t time_format = options->key_expiration_format;
+ log_ed_cert_expiration(signing_key, "signing", fn, time_format);
} else {
log_warn(LD_OR, "Could not load signing key certificate from %s, so " \
"we couldn't learn anything about certificate expiration.", fn);
@@ -684,8 +697,8 @@ make_ntor_onion_key_crosscert(const curve25519_keypair_t *onion_key,
onion_key) < 0)
goto end;
- cert = tor_cert_create(&ed_onion_key, CERT_TYPE_ONION_ID, master_id_key,
- now, lifetime, 0);
+ cert = tor_cert_create_ed25519(&ed_onion_key, CERT_TYPE_ONION_ID,
+ master_id_key, now, lifetime, 0);
end:
memwipe(&ed_onion_key, 0, sizeof(ed_onion_key));
diff --git a/src/feature/relay/selftest.c b/src/feature/relay/selftest.c
index 18fe25b989..46b4b20ffc 100644
--- a/src/feature/relay/selftest.c
+++ b/src/feature/relay/selftest.c
@@ -15,38 +15,68 @@
#include "core/or/or.h"
#include "app/config/config.h"
+
#include "core/mainloop/connection.h"
#include "core/mainloop/mainloop.h"
#include "core/mainloop/netstatus.h"
+
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
#include "core/or/crypt_path_st.h"
+#include "core/or/extendinfo.h"
+#include "core/or/extend_info_st.h"
#include "core/or/origin_circuit_st.h"
#include "core/or/relay.h"
+
#include "feature/control/control_events.h"
+
+#include "feature/dirauth/authmode.h"
+
#include "feature/dirclient/dirclient.h"
#include "feature/dircommon/directory.h"
+
#include "feature/nodelist/authority_cert_st.h"
#include "feature/nodelist/routerinfo.h"
#include "feature/nodelist/routerinfo_st.h"
#include "feature/nodelist/routerlist.h" // but...
#include "feature/nodelist/routerset.h"
#include "feature/nodelist/torcert.h"
+
#include "feature/relay/relay_periodic.h"
#include "feature/relay/router.h"
#include "feature/relay/selftest.h"
-/** Whether we can reach our ORPort from the outside. */
-static int can_reach_or_port = 0;
+static bool have_orport_for_family(int family);
+static void inform_testing_reachability(const tor_addr_t *addr,
+ uint16_t port,
+ bool is_dirport);
+
+/** Whether we can reach our IPv4 ORPort from the outside. */
+static bool can_reach_or_port_ipv4 = false;
+/** Whether we can reach our IPv6 ORPort from the outside. */
+static bool can_reach_or_port_ipv6 = false;
/** Whether we can reach our DirPort from the outside. */
-static int can_reach_dir_port = 0;
+static bool can_reach_dir_port = false;
+
+/** Has informed_testing_reachable logged a message about testing our IPv4
+ * ORPort? */
+static bool have_informed_testing_or_port_ipv4 = false;
+/** Has informed_testing_reachable logged a message about testing our IPv6
+ * ORPort? */
+static bool have_informed_testing_or_port_ipv6 = false;
+/** Has informed_testing_reachable logged a message about testing our
+ * DirPort? */
+static bool have_informed_testing_dir_port = false;
/** Forget what we have learned about our reachability status. */
void
router_reset_reachability(void)
{
- can_reach_or_port = can_reach_dir_port = 0;
+ can_reach_or_port_ipv4 = can_reach_or_port_ipv6 = can_reach_dir_port = false;
+ have_informed_testing_or_port_ipv4 =
+ have_informed_testing_or_port_ipv6 =
+ have_informed_testing_dir_port = false;
}
/** Return 1 if we won't do reachability checks, because:
@@ -68,13 +98,43 @@ router_reachability_checks_disabled(const or_options_t *options)
* - we've seen a successful reachability check, or
* - AssumeReachable is set, or
* - the network is disabled.
+
+ * If `family'`is AF_INET or AF_INET6, return true only when we should skip
+ * the given family's orport check (Because it's been checked, or because we
+ * aren't checking it.) If `family` is 0, return true if we can skip _all_
+ * orport checks.
*/
int
-check_whether_orport_reachable(const or_options_t *options)
+router_orport_seems_reachable(const or_options_t *options,
+ int family)
{
+ tor_assert_nonfatal(family == AF_INET || family == AF_INET6 || family == 0);
int reach_checks_disabled = router_reachability_checks_disabled(options);
- return reach_checks_disabled ||
- can_reach_or_port;
+ if (reach_checks_disabled) {
+ return true;
+ }
+
+ // Note that we do a == 1 here, not just a boolean check. This value
+ // is also an autobool, so CFG_AUTO does not mean that we should
+ // assume IPv6 ports are reachable.
+ const bool ipv6_assume_reachable = (options->AssumeReachableIPv6 == 1);
+
+ // Which reachability flags should we look at?
+ const bool checking_ipv4 = (family == AF_INET || family == 0);
+ const bool checking_ipv6 = (family == AF_INET6 || family == 0);
+
+ if (checking_ipv4) {
+ if (have_orport_for_family(AF_INET) && !can_reach_or_port_ipv4) {
+ return false;
+ }
+ }
+ if (checking_ipv6 && !ipv6_assume_reachable) {
+ if (have_orport_for_family(AF_INET6) && !can_reach_or_port_ipv6) {
+ return false;
+ }
+ }
+
+ return true;
}
/** Return 0 if we need to do a DirPort reachability check, because:
@@ -84,12 +144,14 @@ check_whether_orport_reachable(const or_options_t *options)
* - we've seen a successful reachability check, or
* - there is no DirPort set, or
* - AssumeReachable is set, or
+ * - We're a dir auth (see ticket #40287), or
* - the network is disabled.
*/
int
-check_whether_dirport_reachable(const or_options_t *options)
+router_dirport_seems_reachable(const or_options_t *options)
{
int reach_checks_disabled = router_reachability_checks_disabled(options) ||
+ authdir_mode(options) ||
!options->DirPort_set;
return reach_checks_disabled ||
can_reach_dir_port;
@@ -107,6 +169,7 @@ router_should_check_reachability(int test_or, int test_dir)
if (!me)
return 0;
+ /* Doesn't check our IPv6 address, see #34065. */
if (routerset_contains_router(options->ExcludeNodes, me, -1) &&
options->StrictNodes) {
/* If we've excluded ourself, and StrictNodes is set, we can't test
@@ -115,7 +178,7 @@ router_should_check_reachability(int test_or, int test_dir)
#define SELF_EXCLUDED_WARN_INTERVAL 3600
static ratelim_t warning_limit=RATELIM_INIT(SELF_EXCLUDED_WARN_INTERVAL);
log_fn_ratelim(&warning_limit, LOG_WARN, LD_CIRC,
- "Can't peform self-tests for this relay: we have "
+ "Can't perform self-tests for this relay: we have "
"listed ourself in ExcludeNodes, and StrictNodes is set. "
"We cannot learn whether we are usable, and will not "
"be able to advertise ourself.");
@@ -125,19 +188,51 @@ router_should_check_reachability(int test_or, int test_dir)
return 1;
}
+/**
+ * Return true if we have configured an ORPort for the given family that
+ * we would like to advertise.
+ *
+ * Like other self-testing functions, this function looks at our most
+ * recently built descriptor.
+ **/
+static bool
+have_orport_for_family(int family)
+{
+ const routerinfo_t *me = router_get_my_routerinfo();
+
+ if (!me)
+ return false;
+
+ tor_addr_port_t ap;
+ if (router_get_orport(me, &ap, family) < 0) {
+ return false;
+ }
+ return true;
+}
+
/** Allocate and return a new extend_info_t that can be used to build
- * a circuit to or through the router <b>r</b>. Uses the primary
- * address of the router, so should only be called on a server. */
+ * a circuit to or through the router <b>r</b>, using an address from
+ * <b>family</b> (if available).
+ *
+ * Clients don't have routerinfos, so this function should only be called on a
+ * server.
+ *
+ * If the requested address is not available, returns NULL. */
static extend_info_t *
-extend_info_from_router(const routerinfo_t *r)
+extend_info_from_router(const routerinfo_t *r, int family)
{
crypto_pk_t *rsa_pubkey;
extend_info_t *info;
tor_addr_port_t ap;
- tor_assert(r);
- /* Make sure we don't need to check address reachability */
- tor_assert_nonfatal(router_skip_or_reachability(get_options(), 0));
+ if (BUG(!r)) {
+ return NULL;
+ }
+
+ /* Relays always assume that the first hop is reachable. They ignore
+ * ReachableAddresses. */
+ tor_assert_nonfatal(router_or_conn_should_skip_reachable_address_check(
+ get_options(), 0));
const ed25519_public_key_t *ed_id_key;
if (r->cache_info.signing_key_cert)
@@ -145,7 +240,10 @@ extend_info_from_router(const routerinfo_t *r)
else
ed_id_key = NULL;
- router_get_prim_orport(r, &ap);
+ if (router_get_orport(r, &ap, family) < 0) {
+ /* We don't have an ORPort for the requested family. */
+ return NULL;
+ }
rsa_pubkey = router_get_rsa_onion_pkey(r->onion_pkey, r->onion_pkey_len);
info = extend_info_new(r->nickname, r->cache_info.identity_digest,
ed_id_key,
@@ -155,6 +253,80 @@ extend_info_from_router(const routerinfo_t *r)
return info;
}
+/** Launch a self-testing circuit to one of our ORPorts, using an address from
+ * <b>family</b> (if available). The circuit can be used to test reachability
+ * or bandwidth. <b>me</b> is our own routerinfo.
+ *
+ * Logs an info-level status message. If <b>orport_reachable</b> is false,
+ * call it a reachability circuit. Otherwise, call it a bandwidth circuit.
+ *
+ * See router_do_reachability_checks() for details. */
+static void
+router_do_orport_reachability_checks(const routerinfo_t *me,
+ int family,
+ int orport_reachable)
+{
+ extend_info_t *ei = extend_info_from_router(me, family);
+ int ipv6_flags = (family == AF_INET6 ? CIRCLAUNCH_IS_IPV6_SELFTEST : 0);
+
+ /* If we're trying to test IPv6, but we don't have an IPv6 ORPort, ei will
+ * be NULL. */
+ if (ei) {
+ const char *family_name = fmt_af_family(family);
+ const tor_addr_port_t *ap = extend_info_get_orport(ei, family);
+ log_info(LD_CIRC, "Testing %s of my %s ORPort: %s.",
+ !orport_reachable ? "reachability" : "bandwidth",
+ family_name, fmt_addrport_ap(ap));
+
+ if (!orport_reachable) {
+ /* Only log if we are actually doing a reachability test to learn if our
+ * ORPort is reachable. Else, this prints a log notice if we are simply
+ * opening a bandwidth testing circuit even do we are reachable. */
+ inform_testing_reachability(&ap->addr, ap->port, false);
+ }
+
+ circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
+ CIRCLAUNCH_NEED_CAPACITY|
+ CIRCLAUNCH_IS_INTERNAL|
+ ipv6_flags);
+ extend_info_free(ei);
+ }
+}
+
+/** Launch a self-testing circuit, and ask an exit to connect to our DirPort.
+ * <b>me</b> is our own routerinfo.
+ *
+ * Relays don't advertise IPv6 DirPorts, so this function only supports IPv4.
+ *
+ * See router_do_reachability_checks() for details. */
+static void
+router_do_dirport_reachability_checks(const routerinfo_t *me)
+{
+ tor_addr_port_t my_dirport;
+ tor_addr_copy(&my_dirport.addr, &me->ipv4_addr);
+ my_dirport.port = me->ipv4_dirport;
+
+ /* If there is already a pending connection, don't open another one. */
+ if (!connection_get_by_type_addr_port_purpose(
+ CONN_TYPE_DIR,
+ &my_dirport.addr, my_dirport.port,
+ DIR_PURPOSE_FETCH_SERVERDESC)) {
+ /* ask myself, via tor, for my server descriptor. */
+ directory_request_t *req =
+ directory_request_new(DIR_PURPOSE_FETCH_SERVERDESC);
+ directory_request_set_dir_addr_port(req, &my_dirport);
+ directory_request_set_directory_id_digest(req,
+ me->cache_info.identity_digest);
+ /* ask via an anon circuit, connecting to our dirport. */
+ directory_request_set_indirection(req, DIRIND_ANON_DIRPORT);
+ directory_request_set_resource(req, "authority.z");
+ directory_initiate_request(req);
+ directory_request_free(req);
+
+ inform_testing_reachability(&my_dirport.addr, my_dirport.port, true);
+ }
+}
+
/** Some time has passed, or we just got new directory information.
* See if we currently believe our ORPort or DirPort to be
* unreachable. If so, launch a new test for it.
@@ -171,113 +343,140 @@ router_do_reachability_checks(int test_or, int test_dir)
{
const routerinfo_t *me = router_get_my_routerinfo();
const or_options_t *options = get_options();
- int orport_reachable = check_whether_orport_reachable(options);
- tor_addr_t addr;
+ int orport_reachable_v4 =
+ router_orport_seems_reachable(options, AF_INET);
+ int orport_reachable_v6 =
+ router_orport_seems_reachable(options, AF_INET6);
if (router_should_check_reachability(test_or, test_dir)) {
- if (test_or && (!orport_reachable || !circuit_enough_testing_circs())) {
- extend_info_t *ei = extend_info_from_router(me);
- /* XXX IPv6 self testing */
- log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.",
- !orport_reachable ? "reachability" : "bandwidth",
- fmt_addr32(me->addr), me->or_port);
- circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
- CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
- extend_info_free(ei);
+ bool need_testing = !circuit_enough_testing_circs();
+ /* At the moment, tor relays believe that they are reachable when they
+ * receive any create cell on an inbound connection, if the address
+ * family is correct.
+ */
+ if (test_or && (!orport_reachable_v4 || need_testing)) {
+ router_do_orport_reachability_checks(me, AF_INET, orport_reachable_v4);
+ }
+ if (test_or && (!orport_reachable_v6 || need_testing)) {
+ router_do_orport_reachability_checks(me, AF_INET6, orport_reachable_v6);
}
- /* XXX IPv6 self testing */
- tor_addr_from_ipv4h(&addr, me->addr);
- if (test_dir && !check_whether_dirport_reachable(options) &&
- !connection_get_by_type_addr_port_purpose(
- CONN_TYPE_DIR, &addr, me->dir_port,
- DIR_PURPOSE_FETCH_SERVERDESC)) {
- tor_addr_port_t my_orport, my_dirport;
- memcpy(&my_orport.addr, &addr, sizeof(addr));
- memcpy(&my_dirport.addr, &addr, sizeof(addr));
- my_orport.port = me->or_port;
- my_dirport.port = me->dir_port;
- /* ask myself, via tor, for my server descriptor. */
- directory_request_t *req =
- directory_request_new(DIR_PURPOSE_FETCH_SERVERDESC);
- directory_request_set_or_addr_port(req, &my_orport);
- directory_request_set_dir_addr_port(req, &my_dirport);
- directory_request_set_directory_id_digest(req,
- me->cache_info.identity_digest);
- // ask via an anon circuit, connecting to our dirport.
- directory_request_set_indirection(req, DIRIND_ANON_DIRPORT);
- directory_request_set_resource(req, "authority.z");
- directory_initiate_request(req);
- directory_request_free(req);
+ if (test_dir && !router_dirport_seems_reachable(options)) {
+ router_do_dirport_reachability_checks(me);
}
}
}
-/** We've decided to start our reachability testing. If all
- * is set, log this to the user. Return 1 if we did, or 0 if
- * we chose not to log anything. */
-int
-inform_testing_reachability(void)
+/** Log a message informing the user that we are testing a port for
+ * reachability, if we have not already logged such a message.
+ *
+ * If @a is_dirport is true, then the port is a DirPort; otherwise it is an
+ * ORPort.
+ *
+ * Calls to router_reset_reachability() will reset our view of whether we have
+ * logged this message for a given port. */
+static void
+inform_testing_reachability(const tor_addr_t *addr,
+ uint16_t port,
+ bool is_dirport)
{
- char dirbuf[128];
- char *address;
- const routerinfo_t *me = router_get_my_routerinfo();
- if (!me)
- return 0;
+ if (!router_get_my_routerinfo())
+ return;
- address = tor_dup_ip(me->addr);
- if (!address)
- return 0;
+ bool *have_informed_ptr;
+ if (is_dirport) {
+ have_informed_ptr = &have_informed_testing_dir_port;
+ } else if (tor_addr_family(addr) == AF_INET) {
+ have_informed_ptr = &have_informed_testing_or_port_ipv4;
+ } else {
+ have_informed_ptr = &have_informed_testing_or_port_ipv6;
+ }
- control_event_server_status(LOG_NOTICE,
- "CHECKING_REACHABILITY ORADDRESS=%s:%d",
- address, me->or_port);
- if (me->dir_port) {
- tor_snprintf(dirbuf, sizeof(dirbuf), " and DirPort %s:%d",
- address, me->dir_port);
- control_event_server_status(LOG_NOTICE,
- "CHECKING_REACHABILITY DIRADDRESS=%s:%d",
- address, me->dir_port);
+ if (*have_informed_ptr) {
+ /* We already told the user that we're testing this port; no need to
+ * do it again. */
+ return;
}
- log_notice(LD_OR, "Now checking whether ORPort %s:%d%s %s reachable... "
- "(this may take up to %d minutes -- look for log "
- "messages indicating success)",
- address, me->or_port,
- me->dir_port ? dirbuf : "",
- me->dir_port ? "are" : "is",
- TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT/60);
-
- tor_free(address);
- return 1;
+
+ char addr_buf[TOR_ADDRPORT_BUF_LEN];
+ strlcpy(addr_buf, fmt_addrport(addr, port), sizeof(addr_buf));
+
+ const char *control_addr_type = is_dirport ? "DIRADDRESS" : "ORADDRESS";
+ const char *port_type = is_dirport ? "DirPort" : "ORPort";
+ const char *afname = fmt_af_family(tor_addr_family(addr));
+
+ control_event_server_status(LOG_NOTICE,
+ "CHECKING_REACHABILITY %s=%s",
+ control_addr_type, addr_buf);
+
+ log_notice(LD_OR, "Now checking whether %s %s %s is reachable... "
+ "(this may take up to %d minutes -- look for log "
+ "messages indicating success)",
+ afname, port_type, addr_buf,
+ TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT/60);
+
+ *have_informed_ptr = true;
+}
+
+/**
+ * Return true if this module knows of no reason why we shouldn't publish
+ * a server descriptor.
+ **/
+static bool
+ready_to_publish(const or_options_t *options)
+{
+ return options->PublishServerDescriptor_ != NO_DIRINFO &&
+ router_dirport_seems_reachable(options) &&
+ router_all_orports_seem_reachable(options);
}
-/** Annotate that we found our ORPort reachable. */
+/** Annotate that we found our ORPort reachable with a given address
+ * family. */
void
-router_orport_found_reachable(void)
+router_orport_found_reachable(int family)
{
const routerinfo_t *me = router_get_my_routerinfo();
const or_options_t *options = get_options();
- if (!can_reach_or_port && me) {
- char *address = tor_dup_ip(me->addr);
-
- if (!address)
+ const char *reachable_reason = "ORPort found reachable";
+ bool *can_reach_ptr;
+ if (family == AF_INET) {
+ can_reach_ptr = &can_reach_or_port_ipv4;
+ } else if (family == AF_INET6) {
+ can_reach_ptr = &can_reach_or_port_ipv6;
+ } else {
+ tor_assert_nonfatal_unreached();
+ return;
+ }
+ if (!*can_reach_ptr && me) {
+ tor_addr_port_t ap;
+ if (router_get_orport(me, &ap, family) < 0) {
return;
+ }
+ char *address = tor_strdup(fmt_addrport_ap(&ap));
+
+ *can_reach_ptr = true;
- log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from "
+ log_notice(LD_OR,"Self-testing indicates your ORPort %s is reachable from "
"the outside. Excellent.%s",
- options->PublishServerDescriptor_ != NO_DIRINFO
- && check_whether_dirport_reachable(options) ?
- " Publishing server descriptor." : "");
- can_reach_or_port = 1;
- mark_my_descriptor_dirty("ORPort found reachable");
+ address,
+ ready_to_publish(options) ?
+ " Publishing server descriptor." : "");
+
+ /* Make sure our descriptor is marked to publish the IPv6 if it is now
+ * reachable. This can change at runtime. */
+ if (family == AF_INET6) {
+ mark_my_descriptor_if_omit_ipv6_changes(reachable_reason, false);
+ } else {
+ mark_my_descriptor_dirty(reachable_reason);
+ }
/* This is a significant enough change to upload immediately,
* at least in a test network */
if (options->TestingTorNetwork == 1) {
reschedule_descriptor_update_check();
}
control_event_server_status(LOG_NOTICE,
- "REACHABILITY_SUCCEEDED ORADDRESS=%s:%d",
- address, me->or_port);
+ "REACHABILITY_SUCCEEDED ORADDRESS=%s",
+ address);
tor_free(address);
}
}
@@ -288,19 +487,20 @@ router_dirport_found_reachable(void)
{
const routerinfo_t *me = router_get_my_routerinfo();
const or_options_t *options = get_options();
+
if (!can_reach_dir_port && me) {
- char *address = tor_dup_ip(me->addr);
+ char *address = tor_addr_to_str_dup(&me->ipv4_addr);
if (!address)
return;
+ can_reach_dir_port = true;
log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable "
"from the outside. Excellent.%s",
- options->PublishServerDescriptor_ != NO_DIRINFO
- && check_whether_orport_reachable(options) ?
+ ready_to_publish(options) ?
" Publishing server descriptor." : "");
- can_reach_dir_port = 1;
- if (router_should_advertise_dirport(options, me->dir_port)) {
+
+ if (router_should_advertise_dirport(options, me->ipv4_dirport)) {
mark_my_descriptor_dirty("DirPort found reachable");
/* This is a significant enough change to upload immediately,
* at least in a test network */
@@ -310,13 +510,15 @@ router_dirport_found_reachable(void)
}
control_event_server_status(LOG_NOTICE,
"REACHABILITY_SUCCEEDED DIRADDRESS=%s:%d",
- address, me->dir_port);
+ address, me->ipv4_dirport);
tor_free(address);
}
}
/** We have enough testing circuits open. Send a bunch of "drop"
- * cells down each of them, to exercise our bandwidth. */
+ * cells down each of them, to exercise our bandwidth.
+ *
+ * May use IPv4 and IPv6 testing circuits (if available). */
void
router_perform_bandwidth_test(int num_circs, time_t now)
{
diff --git a/src/feature/relay/selftest.h b/src/feature/relay/selftest.h
index f5babc95da..e09c0e7898 100644
--- a/src/feature/relay/selftest.h
+++ b/src/feature/relay/selftest.h
@@ -15,23 +15,29 @@
#ifdef HAVE_MODULE_RELAY
struct or_options_t;
-int check_whether_orport_reachable(const struct or_options_t *options);
-int check_whether_dirport_reachable(const struct or_options_t *options);
+#define router_all_orports_seem_reachable(opts) \
+ router_orport_seems_reachable((opts),0)
+int router_orport_seems_reachable(
+ const struct or_options_t *options,
+ int family);
+int router_dirport_seems_reachable(
+ const struct or_options_t *options);
void router_do_reachability_checks(int test_or, int test_dir);
void router_perform_bandwidth_test(int num_circs, time_t now);
-int inform_testing_reachability(void);
-void router_orport_found_reachable(void);
+void router_orport_found_reachable(int family);
void router_dirport_found_reachable(void);
void router_reset_reachability(void);
#else /* !defined(HAVE_MODULE_RELAY) */
-#define check_whether_orport_reachable(opts) \
+#define router_all_orports_seem_reachable(opts) \
((void)(opts), 0)
-#define check_whether_dirport_reachable(opts) \
+#define router_orport_seems_reachable(opts, fam) \
+ ((void)(opts), (void)(fam), 0)
+#define router_dirport_seems_reachable(opts) \
((void)(opts), 0)
static inline void
diff --git a/src/feature/rend/rendcache.c b/src/feature/rend/rendcache.c
index 0890a81d8f..04f6390a7f 100644
--- a/src/feature/rend/rendcache.c
+++ b/src/feature/rend/rendcache.c
@@ -37,7 +37,7 @@ STATIC digestmap_t *rend_cache_v2_dir = NULL;
* or discard a new descriptor we just fetched. Here is a description of the
* cache behavior.
*
- * Everytime tor discards an IP (ex: receives a NACK), we add an entry to
+ * Every time tor discards an IP (ex: receives a NACK), we add an entry to
* this cache noting the identity digest of the IP and it's failure type for
* the service ID. The reason we indexed this cache by service ID is to
* differentiate errors that can occur only for a specific service like a
@@ -257,7 +257,7 @@ rend_cache_free_all(void)
/** Remove all entries that re REND_CACHE_FAILURE_MAX_AGE old. This is
* called every second.
*
- * We have to clean these regurlarly else if for whatever reasons an hidden
+ * We have to clean these regularly else if for whatever reasons an hidden
* service goes offline and a client tries to connect to it during that
* time, a failure entry is created and the client will be unable to connect
* for a while even though the service has return online. */
@@ -340,8 +340,9 @@ rend_cache_failure_purge(void)
/** Lookup the rend failure cache using a relay identity digest in
* <b>identity</b> which has DIGEST_LEN bytes and service ID <b>service_id</b>
- * which is a null-terminated string. If found, the intro failure is set in
- * <b>intro_entry</b> else it stays untouched. Return 1 iff found else 0. */
+ * which is a null-terminated string. If @a intro_entry is provided, then it
+ * is set to the entry on success, and to NULL on failure.
+ * Return 1 iff found else 0. */
STATIC int
cache_failure_intro_lookup(const uint8_t *identity, const char *service_id,
rend_cache_failure_intro_t **intro_entry)
diff --git a/src/feature/rend/rendclient.c b/src/feature/rend/rendclient.c
index 427491e3a8..3dda7cd46d 100644
--- a/src/feature/rend/rendclient.c
+++ b/src/feature/rend/rendclient.c
@@ -15,6 +15,7 @@
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
#include "core/or/connection_edge.h"
+#include "core/or/extendinfo.h"
#include "core/or/relay.h"
#include "feature/client/circpathbias.h"
#include "feature/control/control_events.h"
@@ -234,9 +235,15 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
/* version 2 format */
extend_info_t *extend_info = rendcirc->build_state->chosen_exit;
int klen;
+ const tor_addr_port_t *orport =
+ extend_info_get_orport(extend_info, AF_INET);
+ IF_BUG_ONCE(! orport) {
+ /* we should never put an IPv6 address here. */
+ goto perm_err;
+ }
/* nul pads */
- set_uint32(tmp+v3_shift+1, tor_addr_to_ipv4n(&extend_info->addr));
- set_uint16(tmp+v3_shift+5, htons(extend_info->port));
+ set_uint32(tmp+v3_shift+1, tor_addr_to_ipv4n(&orport->addr));
+ set_uint16(tmp+v3_shift+5, htons(orport->port));
memcpy(tmp+v3_shift+7, extend_info->identity_digest, DIGEST_LEN);
klen = crypto_pk_asn1_encode(extend_info->onion_key,
tmp+v3_shift+7+DIGEST_LEN+2,
diff --git a/src/feature/rend/rendcommon.c b/src/feature/rend/rendcommon.c
index 5d04755819..775d487805 100644
--- a/src/feature/rend/rendcommon.c
+++ b/src/feature/rend/rendcommon.c
@@ -14,6 +14,7 @@
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
+#include "core/or/extendinfo.h"
#include "app/config/config.h"
#include "feature/control/control_events.h"
#include "lib/crypt_ops/crypto_rand.h"
@@ -233,7 +234,12 @@ rend_encode_v2_intro_points(char **encoded, rend_service_descriptor_t *desc)
goto done;
}
/* Assemble everything for this introduction point. */
- address = tor_addr_to_str_dup(&info->addr);
+ const tor_addr_port_t *orport = extend_info_get_orport(info, AF_INET);
+ IF_BUG_ONCE(!orport) {
+ /* There must be an IPv4 address for v2 hs. */
+ goto done;
+ }
+ address = tor_addr_to_str_dup(&orport->addr);
res = tor_snprintf(unenc + unenc_written, unenc_len - unenc_written,
"introduction-point %s\n"
"ip-address %s\n"
@@ -242,7 +248,7 @@ rend_encode_v2_intro_points(char **encoded, rend_service_descriptor_t *desc)
"service-key\n%s",
id_base32,
address,
- info->port,
+ orport->port,
onion_key,
service_key);
tor_free(address);
diff --git a/src/feature/rend/rendparse.c b/src/feature/rend/rendparse.c
index 0979d767a7..c28add5ca9 100644
--- a/src/feature/rend/rendparse.c
+++ b/src/feature/rend/rendparse.c
@@ -10,6 +10,7 @@
**/
#include "core/or/or.h"
+#include "core/or/extendinfo.h"
#include "feature/dirparse/parsecommon.h"
#include "feature/dirparse/sigcommon.h"
#include "feature/rend/rendcommon.h"
@@ -428,7 +429,8 @@ rend_parse_introduction_points(rend_service_descriptor_t *parsed,
}
/* Allocate new intro point and extend info. */
intro = tor_malloc_zero(sizeof(rend_intro_point_t));
- info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
+ info = intro->extend_info =
+ extend_info_new(NULL, NULL, NULL, NULL, NULL, NULL, 0);
/* Parse identifier. */
tok = find_by_keyword(tokens, R_IPO_IDENTIFIER);
if (base32_decode(info->identity_digest, DIGEST_LEN,
@@ -446,12 +448,13 @@ rend_parse_introduction_points(rend_service_descriptor_t *parsed,
info->identity_digest, DIGEST_LEN);
/* Parse IP address. */
tok = find_by_keyword(tokens, R_IPO_IP_ADDRESS);
- if (tor_addr_parse(&info->addr, tok->args[0])<0) {
+ tor_addr_t addr;
+ if (tor_addr_parse(&addr, tok->args[0])<0) {
log_warn(LD_REND, "Could not parse introduction point address.");
rend_intro_point_free(intro);
goto err;
}
- if (tor_addr_family(&info->addr) != AF_INET) {
+ if (tor_addr_family(&addr) != AF_INET) {
log_warn(LD_REND, "Introduction point address was not ipv4.");
rend_intro_point_free(intro);
goto err;
@@ -459,14 +462,18 @@ rend_parse_introduction_points(rend_service_descriptor_t *parsed,
/* Parse onion port. */
tok = find_by_keyword(tokens, R_IPO_ONION_PORT);
- info->port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535,
+ uint16_t port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535,
&num_ok,NULL);
- if (!info->port || !num_ok) {
+ if (!port || !num_ok) {
log_warn(LD_REND, "Introduction point onion port %s is invalid",
escaped(tok->args[0]));
rend_intro_point_free(intro);
goto err;
}
+
+ /* Add the address and port. */
+ extend_info_add_orport(info, &addr, port);
+
/* Parse onion key. */
tok = find_by_keyword(tokens, R_IPO_ONION_KEY);
if (!crypto_pk_public_exponent_ok(tok->key)) {
diff --git a/src/feature/rend/rendservice.c b/src/feature/rend/rendservice.c
index 83388a72eb..a2be900e2a 100644
--- a/src/feature/rend/rendservice.c
+++ b/src/feature/rend/rendservice.c
@@ -16,6 +16,7 @@
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
+#include "core/or/extendinfo.h"
#include "core/or/policies.h"
#include "core/or/relay.h"
#include "core/or/crypt_path.h"
@@ -670,7 +671,7 @@ rend_service_prune_list_impl_(void)
ocirc->build_state->chosen_exit)),
safe_str_client(rend_data_get_address(ocirc->rend_data)));
/* Reason is FINISHED because service has been removed and thus the
- * circuit is considered old/uneeded. */
+ * circuit is considered old/unneeded. */
circuit_mark_for_close(TO_CIRCUIT(ocirc), END_CIRC_REASON_FINISHED);
}
smartlist_free(surviving_services);
@@ -1553,7 +1554,7 @@ rend_service_load_keys(rend_service_t *s)
fname = rend_service_path(s, hostname_fname);
tor_snprintf(buf, sizeof(buf),"%s.onion\n", s->service_id);
- if (write_str_to_file(fname,buf,0)<0) {
+ if (write_str_to_file_if_not_equal(fname, buf)) {
log_warn(LD_CONFIG, "Could not write onion address to hostname file.");
goto err;
}
@@ -1848,10 +1849,13 @@ rend_service_use_direct_connection(const or_options_t* options,
const extend_info_t* ei)
{
/* We'll connect directly all reachable addresses, whether preferred or not.
- * The prefer_ipv6 argument to fascist_firewall_allows_address_addr is
+ * The prefer_ipv6 argument to reachable_addr_allows_addr is
* ignored, because pref_only is 0. */
+ const tor_addr_port_t *ap = extend_info_get_orport(ei, AF_INET);
+ if (!ap)
+ return 0;
return (rend_service_allow_non_anonymous_connection(options) &&
- fascist_firewall_allows_address_addr(&ei->addr, ei->port,
+ reachable_addr_allows_addr(&ap->addr, ap->port,
FIREWALL_OR_CONNECTION, 0, 0));
}
@@ -1863,7 +1867,7 @@ rend_service_use_direct_connection_node(const or_options_t* options,
/* We'll connect directly all reachable addresses, whether preferred or not.
*/
return (rend_service_allow_non_anonymous_connection(options) &&
- fascist_firewall_allows_node(node, FIREWALL_OR_CONNECTION, 0));
+ reachable_addr_allows_node(node, FIREWALL_OR_CONNECTION, 0));
}
/******
@@ -2280,7 +2284,8 @@ find_rp_for_intro(const rend_intro_cell_t *intro,
/* Make sure the RP we are being asked to connect to is _not_ a private
* address unless it's allowed. Let's avoid to build a circuit to our
* second middle node and fail right after when extending to the RP. */
- if (!extend_info_addr_is_allowed(&rp->addr)) {
+ const tor_addr_port_t *orport = extend_info_get_orport(rp, AF_INET);
+ if (! orport || !extend_info_addr_is_allowed(&orport->addr)) {
if (err_msg_out) {
tor_asprintf(&err_msg,
"Relay IP in INTRODUCE2 cell is private address.");
@@ -2549,9 +2554,11 @@ rend_service_parse_intro_for_v2(
goto err;
}
- extend_info = tor_malloc_zero(sizeof(extend_info_t));
- tor_addr_from_ipv4n(&extend_info->addr, get_uint32(buf + 1));
- extend_info->port = ntohs(get_uint16(buf + 5));
+ extend_info = extend_info_new(NULL, NULL, NULL, NULL, NULL, NULL, 0);
+ tor_addr_t addr;
+ tor_addr_from_ipv4n(&addr, get_uint32(buf + 1));
+ uint16_t port = ntohs(get_uint16(buf + 5));
+ extend_info_add_orport(extend_info, &addr, port);
memcpy(extend_info->identity_digest, buf + 7, DIGEST_LEN);
extend_info->nickname[0] = '$';
base16_encode(extend_info->nickname + 1, sizeof(extend_info->nickname) - 1,
@@ -3733,7 +3740,7 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc,
rend_data_free(rend_data);
base32_encode(desc_id_base32, sizeof(desc_id_base32),
desc->desc_id, DIGEST_LEN);
- hs_dir_ip = tor_dup_ip(hs_dir->addr);
+ hs_dir_ip = tor_addr_to_str_dup(&hs_dir->ipv4_addr);
if (hs_dir_ip) {
log_info(LD_REND, "Launching upload for v2 descriptor for "
"service '%s' with descriptor ID '%s' with validity "
@@ -3744,7 +3751,7 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc,
seconds_valid,
hs_dir->nickname,
hs_dir_ip,
- hs_dir->or_port);
+ hs_dir->ipv4_orport);
tor_free(hs_dir_ip);
}
@@ -3839,6 +3846,9 @@ upload_service_descriptor(rend_service_t *service)
rend_get_service_id(service->desc->pk, serviceid);
if (get_options()->PublishHidServDescriptors) {
/* Post the current descriptors to the hidden service directories. */
+ /* This log message is used by Chutney as part of its bootstrap
+ * detection mechanism. Please don't change without first checking
+ * Chutney. */
log_info(LD_REND, "Launching upload for hidden service %s",
serviceid);
directory_post_to_hs_dir(service->desc, descs, NULL, serviceid,
@@ -4128,7 +4138,7 @@ rend_consider_services_intro_points(time_t now)
* list of the service. */
unsigned int n_intro_points_to_open;
/* Have an unsigned len so we can use it to compare values else gcc is
- * not happy with unmatching signed comparaison. */
+ * not happy with unmatching signed comparison. */
unsigned int intro_nodes_len;
/* Different service are allowed to have the same introduction point as
* long as they are on different circuit thus why we clear this list. */
@@ -4174,7 +4184,7 @@ rend_consider_services_intro_points(time_t now)
intro->circuit_retries++;
} SMARTLIST_FOREACH_END(intro);
- /* Avoid mismatched signed comparaison below. */
+ /* Avoid mismatched signed comparison below. */
intro_nodes_len = (unsigned int) smartlist_len(service->intro_nodes);
/* Quiescent state, we have more or the equal amount of wanted node for
@@ -4264,7 +4274,7 @@ rend_consider_services_intro_points(time_t now)
log_warn(LD_REND, "Error launching circuit to node %s for service %s.",
safe_str_client(extend_info_describe(intro->extend_info)),
safe_str_client(service->service_id));
- /* This funcion will be called again by the main loop so this intro
+ /* This function will be called again by the main loop so this intro
* point without a intro circuit will be retried on or removed after
* a maximum number of attempts. */
}
diff --git a/src/feature/stats/bw_array_st.h b/src/feature/stats/bw_array_st.h
new file mode 100644
index 0000000000..2d05ff0f77
--- /dev/null
+++ b/src/feature/stats/bw_array_st.h
@@ -0,0 +1,57 @@
+/* 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 bw_array_st.h
+ * @brief Declaration for bw_array_t structure and related constants
+ **/
+
+#ifndef TOR_FEATURE_STATS_BW_ARRAY_ST_H
+#define TOR_FEATURE_STATS_BW_ARRAY_ST_H
+
+/** For how many seconds do we keep track of individual per-second bandwidth
+ * totals? */
+#define NUM_SECS_ROLLING_MEASURE 10
+/** How large are the intervals for which we track and report bandwidth use? */
+#define NUM_SECS_BW_SUM_INTERVAL (24*60*60)
+/** How far in the past do we remember and publish bandwidth use? */
+#define NUM_SECS_BW_SUM_IS_VALID (5*24*60*60)
+/** How many bandwidth usage intervals do we remember? (derived) */
+#define NUM_TOTALS (NUM_SECS_BW_SUM_IS_VALID/NUM_SECS_BW_SUM_INTERVAL)
+
+/** Structure to track bandwidth use, and remember the maxima for a given
+ * time period.
+ */
+struct bw_array_t {
+ /** Observation array: Total number of bytes transferred in each of the last
+ * NUM_SECS_ROLLING_MEASURE seconds. This is used as a circular array. */
+ uint64_t obs[NUM_SECS_ROLLING_MEASURE];
+ int cur_obs_idx; /**< Current position in obs. */
+ time_t cur_obs_time; /**< Time represented in obs[cur_obs_idx] */
+ uint64_t total_obs; /**< Total for all members of obs except
+ * obs[cur_obs_idx] */
+ uint64_t max_total; /**< Largest value that total_obs has taken on in the
+ * current period. */
+ uint64_t total_in_period; /**< Total bytes transferred in the current
+ * period. */
+
+ /** When does the next period begin? */
+ time_t next_period;
+ /** Where in 'maxima' should the maximum bandwidth usage for the current
+ * period be stored? */
+ int next_max_idx;
+ /** How many values in maxima/totals have been set ever? */
+ int num_maxes_set;
+ /** Circular array of the maximum
+ * bandwidth-per-NUM_SECS_ROLLING_MEASURE usage for the last
+ * NUM_TOTALS periods */
+ uint64_t maxima[NUM_TOTALS];
+ /** Circular array of the total bandwidth usage for the last NUM_TOTALS
+ * periods */
+ uint64_t totals[NUM_TOTALS];
+};
+
+#endif /* !defined(TOR_FEATURE_STATS_BW_ARRAY_ST_H) */
diff --git a/src/feature/stats/bwhist.c b/src/feature/stats/bwhist.c
new file mode 100644
index 0000000000..7cbc5f60a6
--- /dev/null
+++ b/src/feature/stats/bwhist.c
@@ -0,0 +1,548 @@
+/* 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 bwhist.c
+ * @brief Tracking for relay bandwidth history
+ *
+ * This module handles bandwidth usage history, used by relays to
+ * self-report how much bandwidth they've used for different
+ * purposes over last day or so, in order to generate the
+ * {dirreq-,}{read,write}-history lines in that they publish.
+ **/
+
+#define BWHIST_PRIVATE
+#include "orconfig.h"
+#include "core/or/or.h"
+#include "feature/stats/bwhist.h"
+
+#include "app/config/config.h"
+#include "app/config/statefile.h"
+#include "feature/relay/routermode.h"
+
+#include "feature/stats/bw_array_st.h"
+#include "app/config/or_state_st.h"
+#include "app/config/or_options_st.h"
+
+/** Shift the current period of b forward by one. */
+STATIC void
+commit_max(bw_array_t *b)
+{
+ /* Store total from current period. */
+ b->totals[b->next_max_idx] = b->total_in_period;
+ /* Store maximum from current period. */
+ b->maxima[b->next_max_idx++] = b->max_total;
+ /* Advance next_period and next_max_idx */
+ b->next_period += NUM_SECS_BW_SUM_INTERVAL;
+ if (b->next_max_idx == NUM_TOTALS)
+ b->next_max_idx = 0;
+ if (b->num_maxes_set < NUM_TOTALS)
+ ++b->num_maxes_set;
+ /* Reset max_total. */
+ b->max_total = 0;
+ /* Reset total_in_period. */
+ b->total_in_period = 0;
+}
+
+/** Shift the current observation time of <b>b</b> forward by one second. */
+STATIC void
+advance_obs(bw_array_t *b)
+{
+ int nextidx;
+ uint64_t total;
+
+ /* Calculate the total bandwidth for the last NUM_SECS_ROLLING_MEASURE
+ * seconds; adjust max_total as needed.*/
+ total = b->total_obs + b->obs[b->cur_obs_idx];
+ if (total > b->max_total)
+ b->max_total = total;
+
+ nextidx = b->cur_obs_idx+1;
+ if (nextidx == NUM_SECS_ROLLING_MEASURE)
+ nextidx = 0;
+
+ b->total_obs = total - b->obs[nextidx];
+ b->obs[nextidx]=0;
+ b->cur_obs_idx = nextidx;
+
+ if (++b->cur_obs_time >= b->next_period)
+ commit_max(b);
+}
+
+/** Add <b>n</b> bytes to the number of bytes in <b>b</b> for second
+ * <b>when</b>. */
+STATIC void
+add_obs(bw_array_t *b, time_t when, uint64_t n)
+{
+ if (when < b->cur_obs_time)
+ return; /* Don't record data in the past. */
+
+ /* If we're currently adding observations for an earlier second than
+ * 'when', advance b->cur_obs_time and b->cur_obs_idx by an
+ * appropriate number of seconds, and do all the other housekeeping. */
+ while (when > b->cur_obs_time) {
+ /* Doing this one second at a time is potentially inefficient, if we start
+ with a state file that is very old. Fortunately, it doesn't seem to
+ show up in profiles, so we can just ignore it for now. */
+ advance_obs(b);
+ }
+
+ b->obs[b->cur_obs_idx] += n;
+ b->total_in_period += n;
+}
+
+/** Allocate, initialize, and return a new bw_array. */
+STATIC bw_array_t *
+bw_array_new(void)
+{
+ bw_array_t *b;
+ time_t start;
+ b = tor_malloc_zero(sizeof(bw_array_t));
+ start = time(NULL);
+ b->cur_obs_time = start;
+ b->next_period = start + NUM_SECS_BW_SUM_INTERVAL;
+ return b;
+}
+
+/** Free storage held by bandwidth array <b>b</b>. */
+STATIC void
+bw_array_free_(bw_array_t *b)
+{
+ if (!b) {
+ return;
+ }
+
+ tor_free(b);
+}
+
+/** Recent history of bandwidth observations for (all) read operations. */
+static bw_array_t *read_array = NULL;
+/** Recent history of bandwidth observations for IPv6 read operations. */
+static bw_array_t *read_array_ipv6 = NULL;
+/** Recent history of bandwidth observations for (all) write operations. */
+STATIC bw_array_t *write_array = NULL;
+/** Recent history of bandwidth observations for IPv6 write operations. */
+static bw_array_t *write_array_ipv6 = NULL;
+/** Recent history of bandwidth observations for read operations for the
+ directory protocol. */
+static bw_array_t *dir_read_array = NULL;
+/** Recent history of bandwidth observations for write operations for the
+ directory protocol. */
+static bw_array_t *dir_write_array = NULL;
+
+/** Set up structures for bandwidth history, clearing them if they already
+ * exist. */
+void
+bwhist_init(void)
+{
+ bw_array_free(read_array);
+ bw_array_free(read_array_ipv6);
+ bw_array_free(write_array);
+ bw_array_free(write_array_ipv6);
+ bw_array_free(dir_read_array);
+ bw_array_free(dir_write_array);
+
+ read_array = bw_array_new();
+ read_array_ipv6 = bw_array_new();
+ write_array = bw_array_new();
+ write_array_ipv6 = bw_array_new();
+ dir_read_array = bw_array_new();
+ dir_write_array = bw_array_new();
+}
+
+/** Remember that we read <b>num_bytes</b> bytes in second <b>when</b>.
+ *
+ * Add num_bytes to the current running total for <b>when</b>.
+ *
+ * <b>when</b> can go back to time, but it's safe to ignore calls
+ * earlier than the latest <b>when</b> you've heard of.
+ */
+void
+bwhist_note_bytes_written(uint64_t num_bytes, time_t when, bool ipv6)
+{
+/* Maybe a circular array for recent seconds, and step to a new point
+ * every time a new second shows up. Or simpler is to just to have
+ * a normal array and push down each item every second; it's short.
+ */
+/* When a new second has rolled over, compute the sum of the bytes we've
+ * seen over when-1 to when-1-NUM_SECS_ROLLING_MEASURE, and stick it
+ * somewhere. See bwhist_bandwidth_assess() below.
+ */
+ add_obs(write_array, when, num_bytes);
+ if (ipv6)
+ add_obs(write_array_ipv6, when, num_bytes);
+}
+
+/** Remember that we wrote <b>num_bytes</b> bytes in second <b>when</b>.
+ * (like bwhist_note_bytes_written() above)
+ */
+void
+bwhist_note_bytes_read(uint64_t num_bytes, time_t when, bool ipv6)
+{
+/* if we're smart, we can make this func and the one above share code */
+ add_obs(read_array, when, num_bytes);
+ if (ipv6)
+ add_obs(read_array_ipv6, when, num_bytes);
+}
+
+/** Remember that we wrote <b>num_bytes</b> directory bytes in second
+ * <b>when</b>. (like bwhist_note_bytes_written() above)
+ */
+void
+bwhist_note_dir_bytes_written(uint64_t num_bytes, time_t when)
+{
+ add_obs(dir_write_array, when, num_bytes);
+}
+
+/** Remember that we read <b>num_bytes</b> directory bytes in second
+ * <b>when</b>. (like bwhist_note_bytes_written() above)
+ */
+void
+bwhist_note_dir_bytes_read(uint64_t num_bytes, time_t when)
+{
+ add_obs(dir_read_array, when, num_bytes);
+}
+
+/** Helper: Return the largest value in b->maxima. (This is equal to the
+ * most bandwidth used in any NUM_SECS_ROLLING_MEASURE period for the last
+ * NUM_SECS_BW_SUM_IS_VALID seconds.)
+ */
+STATIC uint64_t
+find_largest_max(bw_array_t *b)
+{
+ int i;
+ uint64_t max;
+ max=0;
+ for (i=0; i<NUM_TOTALS; ++i) {
+ if (b->maxima[i]>max)
+ max = b->maxima[i];
+ }
+ return max;
+}
+
+/** Find the largest sums in the past NUM_SECS_BW_SUM_IS_VALID (roughly)
+ * seconds. Find one sum for reading and one for writing. They don't have
+ * to be at the same time.
+ *
+ * Return the smaller of these sums, divided by NUM_SECS_ROLLING_MEASURE.
+ */
+MOCK_IMPL(int,
+bwhist_bandwidth_assess,(void))
+{
+ uint64_t w,r;
+ r = find_largest_max(read_array);
+ w = find_largest_max(write_array);
+ if (r>w)
+ return (int)(((double)w)/NUM_SECS_ROLLING_MEASURE);
+ else
+ return (int)(((double)r)/NUM_SECS_ROLLING_MEASURE);
+}
+
+/** Print the bandwidth history of b (either [dir-]read_array or
+ * [dir-]write_array) into the buffer pointed to by buf. The format is
+ * simply comma separated numbers, from oldest to newest.
+ *
+ * It returns the number of bytes written.
+ */
+STATIC size_t
+bwhist_fill_bandwidth_history(char *buf, size_t len, const bw_array_t *b)
+{
+ char *cp = buf;
+ int i, n;
+ const or_options_t *options = get_options();
+ uint64_t cutoff;
+
+ if (b->num_maxes_set <= b->next_max_idx) {
+ /* We haven't been through the circular array yet; time starts at i=0.*/
+ i = 0;
+ } else {
+ /* We've been around the array at least once. The next i to be
+ overwritten is the oldest. */
+ i = b->next_max_idx;
+ }
+
+ if (options->RelayBandwidthRate) {
+ /* We don't want to report that we used more bandwidth than the max we're
+ * willing to relay; otherwise everybody will know how much traffic
+ * we used ourself. */
+ cutoff = options->RelayBandwidthRate * NUM_SECS_BW_SUM_INTERVAL;
+ } else {
+ cutoff = UINT64_MAX;
+ }
+
+ for (n=0; n<b->num_maxes_set; ++n,++i) {
+ uint64_t total;
+ if (i >= NUM_TOTALS)
+ i -= NUM_TOTALS;
+ tor_assert(i < NUM_TOTALS);
+ /* Round the bandwidth used down to the nearest 1k. */
+ total = b->totals[i] & ~0x3ff;
+ if (total > cutoff)
+ total = cutoff;
+
+ if (n==(b->num_maxes_set-1))
+ tor_snprintf(cp, len-(cp-buf), "%"PRIu64, (total));
+ else
+ tor_snprintf(cp, len-(cp-buf), "%"PRIu64",", (total));
+ cp += strlen(cp);
+ }
+ return cp-buf;
+}
+
+/** Encode a single bandwidth history line into <b>buf</b>. */
+static void
+bwhist_get_one_bandwidth_line(buf_t *buf, const char *desc,
+ const bw_array_t *b)
+{
+ /* [dirreq-](read|write)-history yyyy-mm-dd HH:MM:SS (n s) n,n,n... */
+ /* The n,n,n part above. Largest representation of a uint64_t is 20 chars
+ * long, plus the comma. */
+#define MAX_HIST_VALUE_LEN (21*NUM_TOTALS)
+
+ char tmp[MAX_HIST_VALUE_LEN];
+ char end[ISO_TIME_LEN+1];
+
+ size_t slen = bwhist_fill_bandwidth_history(tmp, MAX_HIST_VALUE_LEN, b);
+ /* If we don't have anything to write, skip to the next entry. */
+ if (slen == 0)
+ return;
+
+ format_iso_time(end, b->next_period-NUM_SECS_BW_SUM_INTERVAL);
+ buf_add_printf(buf, "%s %s (%d s) %s\n",
+ desc, end, NUM_SECS_BW_SUM_INTERVAL, tmp);
+}
+
+/** Allocate and return lines for representing this server's bandwidth
+ * history in its descriptor. We publish these lines in our extra-info
+ * descriptor.
+ */
+char *
+bwhist_get_bandwidth_lines(void)
+{
+ buf_t *buf = buf_new();
+
+ bwhist_get_one_bandwidth_line(buf, "write-history", write_array);
+ bwhist_get_one_bandwidth_line(buf, "read-history", read_array);
+ bwhist_get_one_bandwidth_line(buf, "ipv6-write-history", write_array_ipv6);
+ bwhist_get_one_bandwidth_line(buf, "ipv6-read-history", read_array_ipv6);
+ bwhist_get_one_bandwidth_line(buf, "dirreq-write-history", dir_write_array);
+ bwhist_get_one_bandwidth_line(buf, "dirreq-read-history", dir_read_array);
+
+ char *result = buf_extract(buf, NULL);
+ buf_free(buf);
+ return result;
+}
+
+/** Write a single bw_array_t into the Values, Ends, Interval, and Maximum
+ * entries of an or_state_t. Done before writing out a new state file. */
+static void
+bwhist_update_bwhist_state_section(or_state_t *state,
+ const bw_array_t *b,
+ smartlist_t **s_values,
+ smartlist_t **s_maxima,
+ time_t *s_begins,
+ int *s_interval)
+{
+ int i,j;
+ uint64_t maxval;
+
+ if (*s_values) {
+ SMARTLIST_FOREACH(*s_values, char *, val, tor_free(val));
+ smartlist_free(*s_values);
+ }
+ if (*s_maxima) {
+ SMARTLIST_FOREACH(*s_maxima, char *, val, tor_free(val));
+ smartlist_free(*s_maxima);
+ }
+ if (! server_mode(get_options())) {
+ /* Clients don't need to store bandwidth history persistently;
+ * force these values to the defaults. */
+ /* FFFF we should pull the default out of config.c's state table,
+ * so we don't have two defaults. */
+ if (*s_begins != 0 || *s_interval != 900) {
+ time_t now = time(NULL);
+ time_t save_at = get_options()->AvoidDiskWrites ? now+3600 : now+600;
+ or_state_mark_dirty(state, save_at);
+ }
+ *s_begins = 0;
+ *s_interval = 900;
+ *s_values = smartlist_new();
+ *s_maxima = smartlist_new();
+ return;
+ }
+ *s_begins = b->next_period;
+ *s_interval = NUM_SECS_BW_SUM_INTERVAL;
+
+ *s_values = smartlist_new();
+ *s_maxima = smartlist_new();
+ /* Set i to first position in circular array */
+ i = (b->num_maxes_set <= b->next_max_idx) ? 0 : b->next_max_idx;
+ for (j=0; j < b->num_maxes_set; ++j,++i) {
+ if (i >= NUM_TOTALS)
+ i = 0;
+ smartlist_add_asprintf(*s_values, "%"PRIu64,
+ (b->totals[i] & ~0x3ff));
+ maxval = b->maxima[i] / NUM_SECS_ROLLING_MEASURE;
+ smartlist_add_asprintf(*s_maxima, "%"PRIu64,
+ (maxval & ~0x3ff));
+ }
+ smartlist_add_asprintf(*s_values, "%"PRIu64,
+ (b->total_in_period & ~0x3ff));
+ maxval = b->max_total / NUM_SECS_ROLLING_MEASURE;
+ smartlist_add_asprintf(*s_maxima, "%"PRIu64,
+ (maxval & ~0x3ff));
+}
+
+/** Update <b>state</b> with the newest bandwidth history. Done before
+ * writing out a new state file. */
+void
+bwhist_update_state(or_state_t *state)
+{
+#define UPDATE(arrname,st) \
+ bwhist_update_bwhist_state_section(state,\
+ (arrname),\
+ &state->BWHistory ## st ## Values, \
+ &state->BWHistory ## st ## Maxima, \
+ &state->BWHistory ## st ## Ends, \
+ &state->BWHistory ## st ## Interval)
+
+ UPDATE(write_array, Write);
+ UPDATE(read_array, Read);
+ UPDATE(write_array_ipv6, IPv6Write);
+ UPDATE(read_array_ipv6, IPv6Read);
+ UPDATE(dir_write_array, DirWrite);
+ UPDATE(dir_read_array, DirRead);
+
+ if (server_mode(get_options())) {
+ or_state_mark_dirty(state, time(NULL)+(2*3600));
+ }
+#undef UPDATE
+}
+
+/** Load a single bw_array_t from its Values, Ends, Maxima, and Interval
+ * entries in an or_state_t. Done while reading the state file. */
+static int
+bwhist_load_bwhist_state_section(bw_array_t *b,
+ const smartlist_t *s_values,
+ const smartlist_t *s_maxima,
+ const time_t s_begins,
+ const int s_interval)
+{
+ time_t now = time(NULL);
+ int retval = 0;
+ time_t start;
+
+ uint64_t v, mv;
+ int i,ok,ok_m = 0;
+ int have_maxima = s_maxima && s_values &&
+ (smartlist_len(s_values) == smartlist_len(s_maxima));
+
+ if (s_values && s_begins >= now - NUM_SECS_BW_SUM_INTERVAL*NUM_TOTALS) {
+ start = s_begins - s_interval*(smartlist_len(s_values));
+ if (start > now)
+ return 0;
+ b->cur_obs_time = start;
+ b->next_period = start + NUM_SECS_BW_SUM_INTERVAL;
+ SMARTLIST_FOREACH_BEGIN(s_values, const char *, cp) {
+ const char *maxstr = NULL;
+ v = tor_parse_uint64(cp, 10, 0, UINT64_MAX, &ok, NULL);
+ if (have_maxima) {
+ maxstr = smartlist_get(s_maxima, cp_sl_idx);
+ mv = tor_parse_uint64(maxstr, 10, 0, UINT64_MAX, &ok_m, NULL);
+ mv *= NUM_SECS_ROLLING_MEASURE;
+ } else {
+ /* No maxima known; guess average rate to be conservative. */
+ mv = (v / s_interval) * NUM_SECS_ROLLING_MEASURE;
+ }
+ if (!ok) {
+ retval = -1;
+ log_notice(LD_HIST, "Could not parse value '%s' into a number.'",cp);
+ }
+ if (maxstr && !ok_m) {
+ retval = -1;
+ log_notice(LD_HIST, "Could not parse maximum '%s' into a number.'",
+ maxstr);
+ }
+
+ if (start < now) {
+ time_t cur_start = start;
+ time_t actual_interval_len = s_interval;
+ uint64_t cur_val = 0;
+ /* Calculate the average per second. This is the best we can do
+ * because our state file doesn't have per-second resolution. */
+ if (start + s_interval > now)
+ actual_interval_len = now - start;
+ cur_val = v / actual_interval_len;
+ /* This is potentially inefficient, but since we don't do it very
+ * often it should be ok. */
+ while (cur_start < start + actual_interval_len) {
+ add_obs(b, cur_start, cur_val);
+ ++cur_start;
+ }
+ b->max_total = mv;
+ /* This will result in some fairly choppy history if s_interval
+ * is not the same as NUM_SECS_BW_SUM_INTERVAL. XXXX */
+ start += actual_interval_len;
+ }
+ } SMARTLIST_FOREACH_END(cp);
+ }
+
+ /* Clean up maxima and observed */
+ for (i=0; i<NUM_SECS_ROLLING_MEASURE; ++i) {
+ b->obs[i] = 0;
+ }
+ b->total_obs = 0;
+
+ return retval;
+}
+
+/** Set bandwidth history from the state file we just loaded. */
+int
+bwhist_load_state(or_state_t *state, char **err)
+{
+ int all_ok = 1;
+
+ /* Assert they already have been malloced */
+ tor_assert(read_array && write_array);
+ tor_assert(read_array_ipv6 && write_array_ipv6);
+ tor_assert(dir_read_array && dir_write_array);
+
+#define LOAD(arrname,st) \
+ if (bwhist_load_bwhist_state_section( \
+ (arrname), \
+ state->BWHistory ## st ## Values, \
+ state->BWHistory ## st ## Maxima, \
+ state->BWHistory ## st ## Ends, \
+ state->BWHistory ## st ## Interval)<0) \
+ all_ok = 0
+
+ LOAD(write_array, Write);
+ LOAD(read_array, Read);
+ LOAD(write_array_ipv6, IPv6Write);
+ LOAD(read_array_ipv6, IPv6Read);
+ LOAD(dir_write_array, DirWrite);
+ LOAD(dir_read_array, DirRead);
+
+#undef LOAD
+ if (!all_ok) {
+ *err = tor_strdup("Parsing of bandwidth history values failed");
+ /* and create fresh arrays */
+ bwhist_init();
+ return -1;
+ }
+ return 0;
+}
+
+void
+bwhist_free_all(void)
+{
+ bw_array_free(read_array);
+ bw_array_free(read_array_ipv6);
+ bw_array_free(write_array);
+ bw_array_free(write_array_ipv6);
+ bw_array_free(dir_read_array);
+ bw_array_free(dir_write_array);
+}
diff --git a/src/feature/stats/bwhist.h b/src/feature/stats/bwhist.h
new file mode 100644
index 0000000000..f88b951447
--- /dev/null
+++ b/src/feature/stats/bwhist.h
@@ -0,0 +1,47 @@
+/* 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 bwhist.h
+ * @brief Header for feature/stats/bwhist.c
+ **/
+
+#ifndef TOR_FEATURE_STATS_BWHIST_H
+#define TOR_FEATURE_STATS_BWHIST_H
+
+void bwhist_init(void);
+void bwhist_free_all(void);
+
+void bwhist_note_bytes_read(uint64_t num_bytes, time_t when, bool ipv6);
+void bwhist_note_bytes_written(uint64_t num_bytes, time_t when, bool ipv6);
+void bwhist_note_dir_bytes_read(uint64_t num_bytes, time_t when);
+void bwhist_note_dir_bytes_written(uint64_t num_bytes, time_t when);
+
+MOCK_DECL(int, bwhist_bandwidth_assess, (void));
+char *bwhist_get_bandwidth_lines(void);
+struct or_state_t;
+void bwhist_update_state(struct or_state_t *state);
+int bwhist_load_state(struct or_state_t *state, char **err);
+
+#ifdef BWHIST_PRIVATE
+typedef struct bw_array_t bw_array_t;
+STATIC uint64_t find_largest_max(bw_array_t *b);
+STATIC void commit_max(bw_array_t *b);
+STATIC void advance_obs(bw_array_t *b);
+STATIC bw_array_t *bw_array_new(void);
+STATIC void add_obs(bw_array_t *b, time_t when, uint64_t n);
+#define bw_array_free(val) \
+ FREE_AND_NULL(bw_array_t, bw_array_free_, (val))
+STATIC void bw_array_free_(bw_array_t *b);
+STATIC size_t bwhist_fill_bandwidth_history(char *buf, size_t len,
+ const bw_array_t *b);
+#endif /* defined(REPHIST_PRIVATE) */
+
+#ifdef TOR_UNIT_TESTS
+extern struct bw_array_t *write_array;
+#endif
+
+#endif /* !defined(TOR_FEATURE_STATS_BWHIST_H) */
diff --git a/src/feature/stats/connstats.c b/src/feature/stats/connstats.c
new file mode 100644
index 0000000000..827a332be1
--- /dev/null
+++ b/src/feature/stats/connstats.c
@@ -0,0 +1,283 @@
+/* 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 connstats.c
+ * @brief Count bidirectional vs one-way connections.
+ *
+ * Connection statistics, use to track one-way and bidirectional connections.
+ *
+ * Note that this code counts concurrent connections in each
+ * BIDI_INTERVAL-second interval, not total connections. It can tell you what
+ * fraction of connections are bidirectional at each time, not necessarily
+ * what number are bidirectional.
+ **/
+
+#include "orconfig.h"
+#include "core/or/or.h"
+#include "feature/stats/connstats.h"
+#include "app/config/config.h"
+
+/** Start of the current connection stats interval or 0 if we're not
+ * collecting connection statistics. */
+static time_t start_of_conn_stats_interval;
+
+/** Initialize connection stats. */
+void
+conn_stats_init(time_t now)
+{
+ start_of_conn_stats_interval = now;
+}
+
+/** Count connections on which we read and wrote less than this many bytes
+ * as "below threshold." */
+#define BIDI_THRESHOLD 20480
+
+/** Count connections that we read or wrote at least this factor as many
+ * bytes from/to than we wrote or read to/from as mostly reading or
+ * writing. */
+#define BIDI_FACTOR 10
+
+/** Interval length in seconds for considering read and written bytes for
+ * connection stats. */
+#define BIDI_INTERVAL 10
+
+/** Start of next BIDI_INTERVAL second interval. */
+static time_t bidi_next_interval = 0;
+
+/** A single grouped set of connection type counts. */
+typedef struct conn_counts_t {
+ /** Number of connections that we read and wrote less than BIDI_THRESHOLD
+ * bytes from/to in BIDI_INTERVAL seconds. */
+ uint32_t below_threshold;
+
+ /** Number of connections that we read at least BIDI_FACTOR times more
+ * bytes from than we wrote to in BIDI_INTERVAL seconds. */
+ uint32_t mostly_read;
+
+ /** Number of connections that we wrote at least BIDI_FACTOR times more
+ * bytes to than we read from in BIDI_INTERVAL seconds. */
+ uint32_t mostly_written;
+
+ /** Number of connections that we read and wrote at least BIDI_THRESHOLD
+ * bytes from/to, but not BIDI_FACTOR times more in either direction in
+ * BIDI_INTERVAL seconds. */
+ uint32_t both_read_and_written;
+} conn_counts_t ;
+
+/** A collection of connection counts, over all OR connections. */
+static conn_counts_t counts;
+/** A collection of connection counts, over IPv6 OR connections only. */
+static conn_counts_t counts_ipv6;
+
+/** Entry in a map from connection ID to the number of read and written
+ * bytes on this connection in a BIDI_INTERVAL second interval. */
+typedef struct bidi_map_entry_t {
+ HT_ENTRY(bidi_map_entry_t) node;
+ uint64_t conn_id; /**< Connection ID */
+ size_t read; /**< Number of read bytes */
+ size_t written; /**< Number of written bytes */
+ bool is_ipv6; /**< True if this is an IPv6 connection */
+} bidi_map_entry_t;
+
+/** Map of OR connections together with the number of read and written
+ * bytes in the current BIDI_INTERVAL second interval. */
+static HT_HEAD(bidimap, bidi_map_entry_t) bidi_map =
+ HT_INITIALIZER();
+
+/** Hashtable helper: return true if @a a and @a b have the same key. */
+static int
+bidi_map_ent_eq(const bidi_map_entry_t *a, const bidi_map_entry_t *b)
+{
+ return a->conn_id == b->conn_id;
+}
+
+/** Hashtable helper: compute a digest for the key of @a entry. */
+static unsigned
+bidi_map_ent_hash(const bidi_map_entry_t *entry)
+{
+ return (unsigned) entry->conn_id;
+}
+
+HT_PROTOTYPE(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash,
+ bidi_map_ent_eq);
+HT_GENERATE2(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash,
+ bidi_map_ent_eq, 0.6, tor_reallocarray_, tor_free_);
+
+/** Release all storage held in connstats.c */
+void
+conn_stats_free_all(void)
+{
+ bidi_map_entry_t **ptr, **next, *ent;
+ for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) {
+ ent = *ptr;
+ next = HT_NEXT_RMV(bidimap, &bidi_map, ptr);
+ tor_free(ent);
+ }
+ HT_CLEAR(bidimap, &bidi_map);
+}
+
+/** Reset counters for conn statistics. */
+void
+conn_stats_reset(time_t now)
+{
+ start_of_conn_stats_interval = now;
+ memset(&counts, 0, sizeof(counts));
+ memset(&counts_ipv6, 0, sizeof(counts_ipv6));
+ conn_stats_free_all();
+}
+
+/** Stop collecting connection stats in a way that we can re-start doing
+ * so in conn_stats_init(). */
+void
+conn_stats_terminate(void)
+{
+ conn_stats_reset(0);
+}
+
+/**
+ * Record a single entry @a ent in the counts structure @a cnt.
+ */
+static void
+add_entry_to_count(conn_counts_t *cnt, const bidi_map_entry_t *ent)
+{
+ if (ent->read + ent->written < BIDI_THRESHOLD)
+ cnt->below_threshold++;
+ else if (ent->read >= ent->written * BIDI_FACTOR)
+ cnt->mostly_read++;
+ else if (ent->written >= ent->read * BIDI_FACTOR)
+ cnt->mostly_written++;
+ else
+ cnt->both_read_and_written++;
+}
+
+/**
+ * Count all the connection information we've received during the current
+ * period in 'bidimap', and store that information in the appropriate count
+ * structures.
+ **/
+static void
+collect_period_statistics(void)
+{
+ bidi_map_entry_t **ptr, **next, *ent;
+ for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) {
+ ent = *ptr;
+ add_entry_to_count(&counts, ent);
+ if (ent->is_ipv6)
+ add_entry_to_count(&counts_ipv6, ent);
+ next = HT_NEXT_RMV(bidimap, &bidi_map, ptr);
+ tor_free(ent);
+ }
+ log_info(LD_GENERAL, "%d below threshold, %d mostly read, "
+ "%d mostly written, %d both read and written.",
+ counts.below_threshold, counts.mostly_read, counts.mostly_written,
+ counts.both_read_and_written);
+}
+
+/** We read <b>num_read</b> bytes and wrote <b>num_written</b> from/to OR
+ * connection <b>conn_id</b> in second <b>when</b>. If this is the first
+ * observation in a new interval, sum up the last observations. Add bytes
+ * for this connection. */
+void
+conn_stats_note_or_conn_bytes(uint64_t conn_id, size_t num_read,
+ size_t num_written, time_t when,
+ bool is_ipv6)
+{
+ if (!start_of_conn_stats_interval)
+ return;
+ /* Initialize */
+ if (bidi_next_interval == 0)
+ bidi_next_interval = when + BIDI_INTERVAL;
+ /* Sum up last period's statistics */
+ if (when >= bidi_next_interval) {
+ collect_period_statistics();
+ while (when >= bidi_next_interval)
+ bidi_next_interval += BIDI_INTERVAL;
+ }
+ /* Add this connection's bytes. */
+ if (num_read > 0 || num_written > 0) {
+ bidi_map_entry_t *entry, lookup;
+ lookup.conn_id = conn_id;
+ entry = HT_FIND(bidimap, &bidi_map, &lookup);
+ if (entry) {
+ entry->written += num_written;
+ entry->read += num_read;
+ entry->is_ipv6 |= is_ipv6;
+ } else {
+ entry = tor_malloc_zero(sizeof(bidi_map_entry_t));
+ entry->conn_id = conn_id;
+ entry->written = num_written;
+ entry->read = num_read;
+ entry->is_ipv6 = is_ipv6;
+ HT_INSERT(bidimap, &bidi_map, entry);
+ }
+ }
+}
+
+/** Return a newly allocated string containing the connection statistics
+ * until <b>now</b>, or NULL if we're not collecting conn stats. Caller must
+ * ensure start_of_conn_stats_interval is in the past. */
+char *
+conn_stats_format(time_t now)
+{
+ char *result, written_at[ISO_TIME_LEN+1];
+
+ if (!start_of_conn_stats_interval)
+ return NULL; /* Not initialized. */
+
+ tor_assert(now >= start_of_conn_stats_interval);
+
+ format_iso_time(written_at, now);
+ tor_asprintf(&result,
+ "conn-bi-direct %s (%d s) "
+ "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n"
+ "ipv6-conn-bi-direct %s (%d s) "
+ "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n",
+ written_at,
+ (unsigned) (now - start_of_conn_stats_interval),
+ counts.below_threshold,
+ counts.mostly_read,
+ counts.mostly_written,
+ counts.both_read_and_written,
+ written_at,
+ (unsigned) (now - start_of_conn_stats_interval),
+ counts_ipv6.below_threshold,
+ counts_ipv6.mostly_read,
+ counts_ipv6.mostly_written,
+ counts_ipv6.both_read_and_written);
+
+ return result;
+}
+
+/** If 24 hours have passed since the beginning of the current conn stats
+ * period, write conn stats to $DATADIR/stats/conn-stats (possibly
+ * overwriting an existing file) and reset counters. Return when we would
+ * next want to write conn stats or 0 if we never want to write. */
+time_t
+conn_stats_save(time_t now)
+{
+ char *str = NULL;
+
+ if (!start_of_conn_stats_interval)
+ return 0; /* Not initialized. */
+ if (start_of_conn_stats_interval + WRITE_STATS_INTERVAL > now)
+ goto done; /* Not ready to write */
+
+ /* Generate history string. */
+ str = conn_stats_format(now);
+
+ /* Reset counters. */
+ conn_stats_reset(now);
+
+ /* Try to write to disk. */
+ if (!check_or_create_data_subdir("stats")) {
+ write_to_data_subdir("stats", "conn-stats", str, "connection statistics");
+ }
+
+ done:
+ tor_free(str);
+ return start_of_conn_stats_interval + WRITE_STATS_INTERVAL;
+}
diff --git a/src/feature/stats/connstats.h b/src/feature/stats/connstats.h
new file mode 100644
index 0000000000..1a03d0748b
--- /dev/null
+++ b/src/feature/stats/connstats.h
@@ -0,0 +1,25 @@
+/* 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 connstats.h
+ * @brief Header for feature/stats/connstats.c
+ **/
+
+#ifndef TOR_FEATURE_STATS_CONNSTATS_H
+#define TOR_FEATURE_STATS_CONNSTATS_H
+
+void conn_stats_init(time_t now);
+void conn_stats_note_or_conn_bytes(uint64_t conn_id, size_t num_read,
+ size_t num_written, time_t when,
+ bool is_ipv6);
+void conn_stats_reset(time_t now);
+char *conn_stats_format(time_t now);
+time_t conn_stats_save(time_t now);
+void conn_stats_terminate(void);
+void conn_stats_free_all(void);
+
+#endif /* !defined(TOR_FEATURE_STATS_CONNSTATS_H) */
diff --git a/src/feature/stats/geoip_stats.c b/src/feature/stats/geoip_stats.c
index f9a2f19d2e..a733653dde 100644
--- a/src/feature/stats/geoip_stats.c
+++ b/src/feature/stats/geoip_stats.c
@@ -774,7 +774,7 @@ geoip_get_dirreq_history(dirreq_type_t type)
*
* Store a newly allocated comma-separated string in <a>ipver_str</a>
* containing entries for clients connecting over IPv4 and IPv6. The
- * format is family=num where num is the nubmer of IPs we've seen
+ * format is family=num where num is the number of IPs we've seen
* connecting over that protocol family, and family is 'v4' or 'v6'.
*
* Return 0 on success and -1 if we're missing geoip data. */
diff --git a/src/feature/stats/include.am b/src/feature/stats/include.am
index 8789bc3d96..5be519936f 100644
--- a/src/feature/stats/include.am
+++ b/src/feature/stats/include.am
@@ -1,12 +1,17 @@
# ADD_C_FILE: INSERT SOURCES HERE.
LIBTOR_APP_A_SOURCES += \
+ src/feature/stats/bwhist.c \
+ src/feature/stats/connstats.c \
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/bw_array_st.h \
+ src/feature/stats/bwhist.h \
+ src/feature/stats/connstats.h \
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 d728f106a2..57463952e7 100644
--- a/src/feature/stats/predict_ports.c
+++ b/src/feature/stats/predict_ports.c
@@ -270,10 +270,10 @@ rep_hist_circbuilding_dormant(time_t now)
/* see if we'll still need to build testing circuits */
if (server_mode(options) &&
- (!check_whether_orport_reachable(options) ||
+ (!router_all_orports_seem_reachable(options) ||
!circuit_enough_testing_circs()))
return 0;
- if (!check_whether_dirport_reachable(options))
+ if (!router_dirport_seems_reachable(options))
return 0;
return 1;
diff --git a/src/feature/stats/rephist.c b/src/feature/stats/rephist.c
index 71e2e00086..3c22fda3b8 100644
--- a/src/feature/stats/rephist.c
+++ b/src/feature/stats/rephist.c
@@ -18,11 +18,6 @@
* stability information about various relays, including "uptime",
* "weighted fractional uptime" and "mean time between failures".
*
- * <li>Bandwidth usage history, used by relays to self-report how much
- * bandwidth they've used for different purposes over last day or so,
- * in order to generate the {dirreq-,}{read,write}-history lines in
- * that they publish.
- *
* <li>Predicted ports, used by clients to remember how long it's been
* since they opened an exit connection to each given target
* port. Clients use this information in order to try to keep circuits
@@ -48,9 +43,6 @@
* <li>Descriptor serving statistics, used by directory caches to track
* how many descriptors they've served.
*
- * <li>Connection statistics, used by relays to track one-way and
- * bidirectional connections.
- *
* <li>Onion handshake statistics, used by relays to count how many
* TAP and ntor handshakes they've handled.
*
@@ -77,14 +69,13 @@
#define REPHIST_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
-#include "app/config/statefile.h"
#include "core/or/circuitlist.h"
#include "core/or/connection_or.h"
#include "feature/dirauth/authmode.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
-#include "feature/relay/routermode.h"
#include "feature/stats/predict_ports.h"
+#include "feature/stats/connstats.h"
#include "feature/stats/rephist.h"
#include "lib/container/order.h"
#include "lib/crypt_ops/crypto_rand.h"
@@ -92,14 +83,11 @@
#include "feature/nodelist/networkstatus_st.h"
#include "core/or/or_circuit_st.h"
-#include "app/config/or_state_st.h"
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
-static void bw_arrays_init(void);
-
/** Total number of bytes currently allocated in fields used by rephist.c. */
uint64_t rephist_total_alloc=0;
/** Number of or_history_t objects currently allocated. */
@@ -232,7 +220,6 @@ void
rep_hist_init(void)
{
history_map = digestmap_new();
- bw_arrays_init();
}
/** We have just decided that this router with identity digest <b>id</b> is
@@ -973,560 +960,6 @@ rep_hist_load_mtbf_data(time_t now)
return r;
}
-/** For how many seconds do we keep track of individual per-second bandwidth
- * totals? */
-#define NUM_SECS_ROLLING_MEASURE 10
-/** How large are the intervals for which we track and report bandwidth use? */
-#define NUM_SECS_BW_SUM_INTERVAL (24*60*60)
-/** How far in the past do we remember and publish bandwidth use? */
-#define NUM_SECS_BW_SUM_IS_VALID (5*24*60*60)
-/** How many bandwidth usage intervals do we remember? (derived) */
-#define NUM_TOTALS (NUM_SECS_BW_SUM_IS_VALID/NUM_SECS_BW_SUM_INTERVAL)
-
-/** Structure to track bandwidth use, and remember the maxima for a given
- * time period.
- */
-struct bw_array_t {
- /** Observation array: Total number of bytes transferred in each of the last
- * NUM_SECS_ROLLING_MEASURE seconds. This is used as a circular array. */
- uint64_t obs[NUM_SECS_ROLLING_MEASURE];
- int cur_obs_idx; /**< Current position in obs. */
- time_t cur_obs_time; /**< Time represented in obs[cur_obs_idx] */
- uint64_t total_obs; /**< Total for all members of obs except
- * obs[cur_obs_idx] */
- uint64_t max_total; /**< Largest value that total_obs has taken on in the
- * current period. */
- uint64_t total_in_period; /**< Total bytes transferred in the current
- * period. */
-
- /** When does the next period begin? */
- time_t next_period;
- /** Where in 'maxima' should the maximum bandwidth usage for the current
- * period be stored? */
- int next_max_idx;
- /** How many values in maxima/totals have been set ever? */
- int num_maxes_set;
- /** Circular array of the maximum
- * bandwidth-per-NUM_SECS_ROLLING_MEASURE usage for the last
- * NUM_TOTALS periods */
- uint64_t maxima[NUM_TOTALS];
- /** Circular array of the total bandwidth usage for the last NUM_TOTALS
- * periods */
- uint64_t totals[NUM_TOTALS];
-};
-
-/** Shift the current period of b forward by one. */
-STATIC void
-commit_max(bw_array_t *b)
-{
- /* Store total from current period. */
- b->totals[b->next_max_idx] = b->total_in_period;
- /* Store maximum from current period. */
- b->maxima[b->next_max_idx++] = b->max_total;
- /* Advance next_period and next_max_idx */
- b->next_period += NUM_SECS_BW_SUM_INTERVAL;
- if (b->next_max_idx == NUM_TOTALS)
- b->next_max_idx = 0;
- if (b->num_maxes_set < NUM_TOTALS)
- ++b->num_maxes_set;
- /* Reset max_total. */
- b->max_total = 0;
- /* Reset total_in_period. */
- b->total_in_period = 0;
-}
-
-/** Shift the current observation time of <b>b</b> forward by one second. */
-STATIC void
-advance_obs(bw_array_t *b)
-{
- int nextidx;
- uint64_t total;
-
- /* Calculate the total bandwidth for the last NUM_SECS_ROLLING_MEASURE
- * seconds; adjust max_total as needed.*/
- total = b->total_obs + b->obs[b->cur_obs_idx];
- if (total > b->max_total)
- b->max_total = total;
-
- nextidx = b->cur_obs_idx+1;
- if (nextidx == NUM_SECS_ROLLING_MEASURE)
- nextidx = 0;
-
- b->total_obs = total - b->obs[nextidx];
- b->obs[nextidx]=0;
- b->cur_obs_idx = nextidx;
-
- if (++b->cur_obs_time >= b->next_period)
- commit_max(b);
-}
-
-/** Add <b>n</b> bytes to the number of bytes in <b>b</b> for second
- * <b>when</b>. */
-static inline void
-add_obs(bw_array_t *b, time_t when, uint64_t n)
-{
- if (when < b->cur_obs_time)
- return; /* Don't record data in the past. */
-
- /* If we're currently adding observations for an earlier second than
- * 'when', advance b->cur_obs_time and b->cur_obs_idx by an
- * appropriate number of seconds, and do all the other housekeeping. */
- while (when > b->cur_obs_time) {
- /* Doing this one second at a time is potentially inefficient, if we start
- with a state file that is very old. Fortunately, it doesn't seem to
- show up in profiles, so we can just ignore it for now. */
- advance_obs(b);
- }
-
- b->obs[b->cur_obs_idx] += n;
- b->total_in_period += n;
-}
-
-/** Allocate, initialize, and return a new bw_array. */
-static bw_array_t *
-bw_array_new(void)
-{
- bw_array_t *b;
- time_t start;
- b = tor_malloc_zero(sizeof(bw_array_t));
- rephist_total_alloc += sizeof(bw_array_t);
- start = time(NULL);
- b->cur_obs_time = start;
- b->next_period = start + NUM_SECS_BW_SUM_INTERVAL;
- return b;
-}
-
-#define bw_array_free(val) \
- FREE_AND_NULL(bw_array_t, bw_array_free_, (val))
-
-/** Free storage held by bandwidth array <b>b</b>. */
-static void
-bw_array_free_(bw_array_t *b)
-{
- if (!b) {
- return;
- }
-
- rephist_total_alloc -= sizeof(bw_array_t);
- tor_free(b);
-}
-
-/** Recent history of bandwidth observations for read operations. */
-static bw_array_t *read_array = NULL;
-/** Recent history of bandwidth observations for write operations. */
-STATIC bw_array_t *write_array = NULL;
-/** Recent history of bandwidth observations for read operations for the
- directory protocol. */
-static bw_array_t *dir_read_array = NULL;
-/** Recent history of bandwidth observations for write operations for the
- directory protocol. */
-static bw_array_t *dir_write_array = NULL;
-
-/** Set up [dir_]read_array and [dir_]write_array, freeing them if they
- * already exist. */
-static void
-bw_arrays_init(void)
-{
- bw_array_free(read_array);
- bw_array_free(write_array);
- bw_array_free(dir_read_array);
- bw_array_free(dir_write_array);
-
- read_array = bw_array_new();
- write_array = bw_array_new();
- dir_read_array = bw_array_new();
- dir_write_array = bw_array_new();
-}
-
-/** Remember that we read <b>num_bytes</b> bytes in second <b>when</b>.
- *
- * Add num_bytes to the current running total for <b>when</b>.
- *
- * <b>when</b> can go back to time, but it's safe to ignore calls
- * earlier than the latest <b>when</b> you've heard of.
- */
-void
-rep_hist_note_bytes_written(uint64_t num_bytes, time_t when)
-{
-/* Maybe a circular array for recent seconds, and step to a new point
- * every time a new second shows up. Or simpler is to just to have
- * a normal array and push down each item every second; it's short.
- */
-/* When a new second has rolled over, compute the sum of the bytes we've
- * seen over when-1 to when-1-NUM_SECS_ROLLING_MEASURE, and stick it
- * somewhere. See rep_hist_bandwidth_assess() below.
- */
- add_obs(write_array, when, num_bytes);
-}
-
-/** Remember that we wrote <b>num_bytes</b> bytes in second <b>when</b>.
- * (like rep_hist_note_bytes_written() above)
- */
-void
-rep_hist_note_bytes_read(uint64_t num_bytes, time_t when)
-{
-/* if we're smart, we can make this func and the one above share code */
- add_obs(read_array, when, num_bytes);
-}
-
-/** Remember that we wrote <b>num_bytes</b> directory bytes in second
- * <b>when</b>. (like rep_hist_note_bytes_written() above)
- */
-void
-rep_hist_note_dir_bytes_written(uint64_t num_bytes, time_t when)
-{
- add_obs(dir_write_array, when, num_bytes);
-}
-
-/** Remember that we read <b>num_bytes</b> directory bytes in second
- * <b>when</b>. (like rep_hist_note_bytes_written() above)
- */
-void
-rep_hist_note_dir_bytes_read(uint64_t num_bytes, time_t when)
-{
- add_obs(dir_read_array, when, num_bytes);
-}
-
-/** Helper: Return the largest value in b->maxima. (This is equal to the
- * most bandwidth used in any NUM_SECS_ROLLING_MEASURE period for the last
- * NUM_SECS_BW_SUM_IS_VALID seconds.)
- */
-STATIC uint64_t
-find_largest_max(bw_array_t *b)
-{
- int i;
- uint64_t max;
- max=0;
- for (i=0; i<NUM_TOTALS; ++i) {
- if (b->maxima[i]>max)
- max = b->maxima[i];
- }
- return max;
-}
-
-/** Find the largest sums in the past NUM_SECS_BW_SUM_IS_VALID (roughly)
- * seconds. Find one sum for reading and one for writing. They don't have
- * to be at the same time.
- *
- * Return the smaller of these sums, divided by NUM_SECS_ROLLING_MEASURE.
- */
-MOCK_IMPL(int,
-rep_hist_bandwidth_assess,(void))
-{
- uint64_t w,r;
- r = find_largest_max(read_array);
- w = find_largest_max(write_array);
- if (r>w)
- return (int)(((double)w)/NUM_SECS_ROLLING_MEASURE);
- else
- return (int)(((double)r)/NUM_SECS_ROLLING_MEASURE);
-}
-
-/** Print the bandwidth history of b (either [dir-]read_array or
- * [dir-]write_array) into the buffer pointed to by buf. The format is
- * simply comma separated numbers, from oldest to newest.
- *
- * It returns the number of bytes written.
- */
-static size_t
-rep_hist_fill_bandwidth_history(char *buf, size_t len, const bw_array_t *b)
-{
- char *cp = buf;
- int i, n;
- const or_options_t *options = get_options();
- uint64_t cutoff;
-
- if (b->num_maxes_set <= b->next_max_idx) {
- /* We haven't been through the circular array yet; time starts at i=0.*/
- i = 0;
- } else {
- /* We've been around the array at least once. The next i to be
- overwritten is the oldest. */
- i = b->next_max_idx;
- }
-
- if (options->RelayBandwidthRate) {
- /* We don't want to report that we used more bandwidth than the max we're
- * willing to relay; otherwise everybody will know how much traffic
- * we used ourself. */
- cutoff = options->RelayBandwidthRate * NUM_SECS_BW_SUM_INTERVAL;
- } else {
- cutoff = UINT64_MAX;
- }
-
- for (n=0; n<b->num_maxes_set; ++n,++i) {
- uint64_t total;
- if (i >= NUM_TOTALS)
- i -= NUM_TOTALS;
- tor_assert(i < NUM_TOTALS);
- /* Round the bandwidth used down to the nearest 1k. */
- total = b->totals[i] & ~0x3ff;
- if (total > cutoff)
- total = cutoff;
-
- if (n==(b->num_maxes_set-1))
- tor_snprintf(cp, len-(cp-buf), "%"PRIu64, (total));
- else
- tor_snprintf(cp, len-(cp-buf), "%"PRIu64",", (total));
- cp += strlen(cp);
- }
- return cp-buf;
-}
-
-/** Allocate and return lines for representing this server's bandwidth
- * history in its descriptor. We publish these lines in our extra-info
- * descriptor.
- */
-char *
-rep_hist_get_bandwidth_lines(void)
-{
- char *buf, *cp;
- char t[ISO_TIME_LEN+1];
- int r;
- bw_array_t *b = NULL;
- const char *desc = NULL;
- size_t len;
-
- /* [dirreq-](read|write)-history yyyy-mm-dd HH:MM:SS (n s) n,n,n... */
-/* The n,n,n part above. Largest representation of a uint64_t is 20 chars
- * long, plus the comma. */
-#define MAX_HIST_VALUE_LEN (21*NUM_TOTALS)
- len = (67+MAX_HIST_VALUE_LEN)*4;
- buf = tor_malloc_zero(len);
- cp = buf;
- for (r=0;r<4;++r) {
- char tmp[MAX_HIST_VALUE_LEN];
- size_t slen;
- switch (r) {
- case 0:
- b = write_array;
- desc = "write-history";
- break;
- case 1:
- b = read_array;
- desc = "read-history";
- break;
- case 2:
- b = dir_write_array;
- desc = "dirreq-write-history";
- break;
- case 3:
- b = dir_read_array;
- desc = "dirreq-read-history";
- break;
- }
- tor_assert(b);
- slen = rep_hist_fill_bandwidth_history(tmp, MAX_HIST_VALUE_LEN, b);
- /* If we don't have anything to write, skip to the next entry. */
- if (slen == 0)
- continue;
- format_iso_time(t, b->next_period-NUM_SECS_BW_SUM_INTERVAL);
- tor_snprintf(cp, len-(cp-buf), "%s %s (%d s) ",
- desc, t, NUM_SECS_BW_SUM_INTERVAL);
- cp += strlen(cp);
- strlcat(cp, tmp, len-(cp-buf));
- cp += slen;
- strlcat(cp, "\n", len-(cp-buf));
- ++cp;
- }
- return buf;
-}
-
-/** Write a single bw_array_t into the Values, Ends, Interval, and Maximum
- * entries of an or_state_t. Done before writing out a new state file. */
-static void
-rep_hist_update_bwhist_state_section(or_state_t *state,
- const bw_array_t *b,
- smartlist_t **s_values,
- smartlist_t **s_maxima,
- time_t *s_begins,
- int *s_interval)
-{
- int i,j;
- uint64_t maxval;
-
- if (*s_values) {
- SMARTLIST_FOREACH(*s_values, char *, val, tor_free(val));
- smartlist_free(*s_values);
- }
- if (*s_maxima) {
- SMARTLIST_FOREACH(*s_maxima, char *, val, tor_free(val));
- smartlist_free(*s_maxima);
- }
- if (! server_mode(get_options())) {
- /* Clients don't need to store bandwidth history persistently;
- * force these values to the defaults. */
- /* FFFF we should pull the default out of config.c's state table,
- * so we don't have two defaults. */
- if (*s_begins != 0 || *s_interval != 900) {
- time_t now = time(NULL);
- time_t save_at = get_options()->AvoidDiskWrites ? now+3600 : now+600;
- or_state_mark_dirty(state, save_at);
- }
- *s_begins = 0;
- *s_interval = 900;
- *s_values = smartlist_new();
- *s_maxima = smartlist_new();
- return;
- }
- *s_begins = b->next_period;
- *s_interval = NUM_SECS_BW_SUM_INTERVAL;
-
- *s_values = smartlist_new();
- *s_maxima = smartlist_new();
- /* Set i to first position in circular array */
- i = (b->num_maxes_set <= b->next_max_idx) ? 0 : b->next_max_idx;
- for (j=0; j < b->num_maxes_set; ++j,++i) {
- if (i >= NUM_TOTALS)
- i = 0;
- smartlist_add_asprintf(*s_values, "%"PRIu64,
- (b->totals[i] & ~0x3ff));
- maxval = b->maxima[i] / NUM_SECS_ROLLING_MEASURE;
- smartlist_add_asprintf(*s_maxima, "%"PRIu64,
- (maxval & ~0x3ff));
- }
- smartlist_add_asprintf(*s_values, "%"PRIu64,
- (b->total_in_period & ~0x3ff));
- maxval = b->max_total / NUM_SECS_ROLLING_MEASURE;
- smartlist_add_asprintf(*s_maxima, "%"PRIu64,
- (maxval & ~0x3ff));
-}
-
-/** Update <b>state</b> with the newest bandwidth history. Done before
- * writing out a new state file. */
-void
-rep_hist_update_state(or_state_t *state)
-{
-#define UPDATE(arrname,st) \
- rep_hist_update_bwhist_state_section(state,\
- (arrname),\
- &state->BWHistory ## st ## Values, \
- &state->BWHistory ## st ## Maxima, \
- &state->BWHistory ## st ## Ends, \
- &state->BWHistory ## st ## Interval)
-
- UPDATE(write_array, Write);
- UPDATE(read_array, Read);
- UPDATE(dir_write_array, DirWrite);
- UPDATE(dir_read_array, DirRead);
-
- if (server_mode(get_options())) {
- or_state_mark_dirty(state, time(NULL)+(2*3600));
- }
-#undef UPDATE
-}
-
-/** Load a single bw_array_t from its Values, Ends, Maxima, and Interval
- * entries in an or_state_t. Done while reading the state file. */
-static int
-rep_hist_load_bwhist_state_section(bw_array_t *b,
- const smartlist_t *s_values,
- const smartlist_t *s_maxima,
- const time_t s_begins,
- const int s_interval)
-{
- time_t now = time(NULL);
- int retval = 0;
- time_t start;
-
- uint64_t v, mv;
- int i,ok,ok_m = 0;
- int have_maxima = s_maxima && s_values &&
- (smartlist_len(s_values) == smartlist_len(s_maxima));
-
- if (s_values && s_begins >= now - NUM_SECS_BW_SUM_INTERVAL*NUM_TOTALS) {
- start = s_begins - s_interval*(smartlist_len(s_values));
- if (start > now)
- return 0;
- b->cur_obs_time = start;
- b->next_period = start + NUM_SECS_BW_SUM_INTERVAL;
- SMARTLIST_FOREACH_BEGIN(s_values, const char *, cp) {
- const char *maxstr = NULL;
- v = tor_parse_uint64(cp, 10, 0, UINT64_MAX, &ok, NULL);
- if (have_maxima) {
- maxstr = smartlist_get(s_maxima, cp_sl_idx);
- mv = tor_parse_uint64(maxstr, 10, 0, UINT64_MAX, &ok_m, NULL);
- mv *= NUM_SECS_ROLLING_MEASURE;
- } else {
- /* No maxima known; guess average rate to be conservative. */
- mv = (v / s_interval) * NUM_SECS_ROLLING_MEASURE;
- }
- if (!ok) {
- retval = -1;
- log_notice(LD_HIST, "Could not parse value '%s' into a number.'",cp);
- }
- if (maxstr && !ok_m) {
- retval = -1;
- log_notice(LD_HIST, "Could not parse maximum '%s' into a number.'",
- maxstr);
- }
-
- if (start < now) {
- time_t cur_start = start;
- time_t actual_interval_len = s_interval;
- uint64_t cur_val = 0;
- /* Calculate the average per second. This is the best we can do
- * because our state file doesn't have per-second resolution. */
- if (start + s_interval > now)
- actual_interval_len = now - start;
- cur_val = v / actual_interval_len;
- /* This is potentially inefficient, but since we don't do it very
- * often it should be ok. */
- while (cur_start < start + actual_interval_len) {
- add_obs(b, cur_start, cur_val);
- ++cur_start;
- }
- b->max_total = mv;
- /* This will result in some fairly choppy history if s_interval
- * is not the same as NUM_SECS_BW_SUM_INTERVAL. XXXX */
- start += actual_interval_len;
- }
- } SMARTLIST_FOREACH_END(cp);
- }
-
- /* Clean up maxima and observed */
- for (i=0; i<NUM_SECS_ROLLING_MEASURE; ++i) {
- b->obs[i] = 0;
- }
- b->total_obs = 0;
-
- return retval;
-}
-
-/** Set bandwidth history from the state file we just loaded. */
-int
-rep_hist_load_state(or_state_t *state, char **err)
-{
- int all_ok = 1;
-
- /* Assert they already have been malloced */
- tor_assert(read_array && write_array);
- tor_assert(dir_read_array && dir_write_array);
-
-#define LOAD(arrname,st) \
- if (rep_hist_load_bwhist_state_section( \
- (arrname), \
- state->BWHistory ## st ## Values, \
- state->BWHistory ## st ## Maxima, \
- state->BWHistory ## st ## Ends, \
- state->BWHistory ## st ## Interval)<0) \
- all_ok = 0
-
- LOAD(write_array, Write);
- LOAD(read_array, Read);
- LOAD(dir_write_array, DirWrite);
- LOAD(dir_read_array, DirRead);
-
-#undef LOAD
- if (!all_ok) {
- *err = tor_strdup("Parsing of bandwidth history values failed");
- /* and create fresh arrays */
- bw_arrays_init();
- return -1;
- }
- return 0;
-}
-
/*** Exit port statistics ***/
/* Some constants */
@@ -2213,223 +1646,6 @@ rep_hist_note_desc_served(const char * desc)
/*** Connection statistics ***/
-/** Start of the current connection stats interval or 0 if we're not
- * collecting connection statistics. */
-static time_t start_of_conn_stats_interval;
-
-/** Initialize connection stats. */
-void
-rep_hist_conn_stats_init(time_t now)
-{
- start_of_conn_stats_interval = now;
-}
-
-/* Count connections that we read and wrote less than these many bytes
- * from/to as below threshold. */
-#define BIDI_THRESHOLD 20480
-
-/* Count connections that we read or wrote at least this factor as many
- * bytes from/to than we wrote or read to/from as mostly reading or
- * writing. */
-#define BIDI_FACTOR 10
-
-/* Interval length in seconds for considering read and written bytes for
- * connection stats. */
-#define BIDI_INTERVAL 10
-
-/** Start of next BIDI_INTERVAL second interval. */
-static time_t bidi_next_interval = 0;
-
-/** Number of connections that we read and wrote less than BIDI_THRESHOLD
- * bytes from/to in BIDI_INTERVAL seconds. */
-static uint32_t below_threshold = 0;
-
-/** Number of connections that we read at least BIDI_FACTOR times more
- * bytes from than we wrote to in BIDI_INTERVAL seconds. */
-static uint32_t mostly_read = 0;
-
-/** Number of connections that we wrote at least BIDI_FACTOR times more
- * bytes to than we read from in BIDI_INTERVAL seconds. */
-static uint32_t mostly_written = 0;
-
-/** Number of connections that we read and wrote at least BIDI_THRESHOLD
- * bytes from/to, but not BIDI_FACTOR times more in either direction in
- * BIDI_INTERVAL seconds. */
-static uint32_t both_read_and_written = 0;
-
-/** Entry in a map from connection ID to the number of read and written
- * bytes on this connection in a BIDI_INTERVAL second interval. */
-typedef struct bidi_map_entry_t {
- HT_ENTRY(bidi_map_entry_t) node;
- uint64_t conn_id; /**< Connection ID */
- size_t read; /**< Number of read bytes */
- size_t written; /**< Number of written bytes */
-} bidi_map_entry_t;
-
-/** Map of OR connections together with the number of read and written
- * bytes in the current BIDI_INTERVAL second interval. */
-static HT_HEAD(bidimap, bidi_map_entry_t) bidi_map =
- HT_INITIALIZER();
-
-static int
-bidi_map_ent_eq(const bidi_map_entry_t *a, const bidi_map_entry_t *b)
-{
- return a->conn_id == b->conn_id;
-}
-
-/* DOCDOC bidi_map_ent_hash */
-static unsigned
-bidi_map_ent_hash(const bidi_map_entry_t *entry)
-{
- return (unsigned) entry->conn_id;
-}
-
-HT_PROTOTYPE(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash,
- bidi_map_ent_eq);
-HT_GENERATE2(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash,
- bidi_map_ent_eq, 0.6, tor_reallocarray_, tor_free_);
-
-/* DOCDOC bidi_map_free */
-static void
-bidi_map_free_all(void)
-{
- bidi_map_entry_t **ptr, **next, *ent;
- for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) {
- ent = *ptr;
- next = HT_NEXT_RMV(bidimap, &bidi_map, ptr);
- tor_free(ent);
- }
- HT_CLEAR(bidimap, &bidi_map);
-}
-
-/** Reset counters for conn statistics. */
-void
-rep_hist_reset_conn_stats(time_t now)
-{
- start_of_conn_stats_interval = now;
- below_threshold = 0;
- mostly_read = 0;
- mostly_written = 0;
- both_read_and_written = 0;
- bidi_map_free_all();
-}
-
-/** Stop collecting connection stats in a way that we can re-start doing
- * so in rep_hist_conn_stats_init(). */
-void
-rep_hist_conn_stats_term(void)
-{
- rep_hist_reset_conn_stats(0);
-}
-
-/** We read <b>num_read</b> bytes and wrote <b>num_written</b> from/to OR
- * connection <b>conn_id</b> in second <b>when</b>. If this is the first
- * observation in a new interval, sum up the last observations. Add bytes
- * for this connection. */
-void
-rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read,
- size_t num_written, time_t when)
-{
- if (!start_of_conn_stats_interval)
- return;
- /* Initialize */
- if (bidi_next_interval == 0)
- bidi_next_interval = when + BIDI_INTERVAL;
- /* Sum up last period's statistics */
- if (when >= bidi_next_interval) {
- bidi_map_entry_t **ptr, **next, *ent;
- for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) {
- ent = *ptr;
- if (ent->read + ent->written < BIDI_THRESHOLD)
- below_threshold++;
- else if (ent->read >= ent->written * BIDI_FACTOR)
- mostly_read++;
- else if (ent->written >= ent->read * BIDI_FACTOR)
- mostly_written++;
- else
- both_read_and_written++;
- next = HT_NEXT_RMV(bidimap, &bidi_map, ptr);
- tor_free(ent);
- }
- while (when >= bidi_next_interval)
- bidi_next_interval += BIDI_INTERVAL;
- log_info(LD_GENERAL, "%d below threshold, %d mostly read, "
- "%d mostly written, %d both read and written.",
- below_threshold, mostly_read, mostly_written,
- both_read_and_written);
- }
- /* Add this connection's bytes. */
- if (num_read > 0 || num_written > 0) {
- bidi_map_entry_t *entry, lookup;
- lookup.conn_id = conn_id;
- entry = HT_FIND(bidimap, &bidi_map, &lookup);
- if (entry) {
- entry->written += num_written;
- entry->read += num_read;
- } else {
- entry = tor_malloc_zero(sizeof(bidi_map_entry_t));
- entry->conn_id = conn_id;
- entry->written = num_written;
- entry->read = num_read;
- HT_INSERT(bidimap, &bidi_map, entry);
- }
- }
-}
-
-/** Return a newly allocated string containing the connection statistics
- * until <b>now</b>, or NULL if we're not collecting conn stats. Caller must
- * ensure start_of_conn_stats_interval is in the past. */
-char *
-rep_hist_format_conn_stats(time_t now)
-{
- char *result, written[ISO_TIME_LEN+1];
-
- if (!start_of_conn_stats_interval)
- return NULL; /* Not initialized. */
-
- tor_assert(now >= start_of_conn_stats_interval);
-
- format_iso_time(written, now);
- tor_asprintf(&result, "conn-bi-direct %s (%d s) %d,%d,%d,%d\n",
- written,
- (unsigned) (now - start_of_conn_stats_interval),
- below_threshold,
- mostly_read,
- mostly_written,
- both_read_and_written);
- return result;
-}
-
-/** If 24 hours have passed since the beginning of the current conn stats
- * period, write conn stats to $DATADIR/stats/conn-stats (possibly
- * overwriting an existing file) and reset counters. Return when we would
- * next want to write conn stats or 0 if we never want to write. */
-time_t
-rep_hist_conn_stats_write(time_t now)
-{
- char *str = NULL;
-
- if (!start_of_conn_stats_interval)
- return 0; /* Not initialized. */
- if (start_of_conn_stats_interval + WRITE_STATS_INTERVAL > now)
- goto done; /* Not ready to write */
-
- /* Generate history string. */
- str = rep_hist_format_conn_stats(now);
-
- /* Reset counters. */
- rep_hist_reset_conn_stats(now);
-
- /* Try to write to disk. */
- if (!check_or_create_data_subdir("stats")) {
- write_to_data_subdir("stats", "conn-stats", str, "connection statistics");
- }
-
- done:
- tor_free(str);
- return start_of_conn_stats_interval + WRITE_STATS_INTERVAL;
-}
-
/** Internal statistics to track how many requests of each type of
* handshake we've received, and how many we've assigned to cpuworkers.
* Useful for seeing trends in cpu load.
@@ -2455,6 +1671,26 @@ rep_hist_note_circuit_handshake_assigned(uint16_t type)
onion_handshakes_assigned[type]++;
}
+/** Get the circuit handshake value that is requested. */
+MOCK_IMPL(int,
+rep_hist_get_circuit_handshake_requested, (uint16_t type))
+{
+ if (BUG(type > MAX_ONION_HANDSHAKE_TYPE)) {
+ return 0;
+ }
+ return onion_handshakes_requested[type];
+}
+
+/** Get the circuit handshake value that is assigned. */
+MOCK_IMPL(int,
+rep_hist_get_circuit_handshake_assigned, (uint16_t type))
+{
+ if (BUG(type > MAX_ONION_HANDSHAKE_TYPE)) {
+ return 0;
+ }
+ return onion_handshakes_assigned[type];
+}
+
/** Log our onionskin statistics since the last time we were called. */
void
rep_hist_log_circuit_handshake_stats(time_t now)
@@ -2593,7 +1829,7 @@ rep_hist_stored_maybe_new_hs(const crypto_pk_t *pubkey)
/* The number of cells that are supposed to be hidden from the adversary
* by adding noise from the Laplace distribution. This value, divided by
- * EPSILON, is Laplace parameter b. It must be greather than 0. */
+ * EPSILON, is Laplace parameter b. It must be greater than 0. */
#define REND_CELLS_DELTA_F 2048
/* Security parameter for obfuscating number of cells with a value between
* ]0.0, 1.0]. Smaller values obfuscate observations more, but at the same
@@ -2901,23 +2137,11 @@ rep_hist_free_all(void)
hs_stats_free(hs_stats);
digestmap_free(history_map, free_or_history);
- bw_array_free(read_array);
- read_array = NULL;
-
- bw_array_free(write_array);
- write_array = NULL;
-
- bw_array_free(dir_read_array);
- dir_read_array = NULL;
-
- bw_array_free(dir_write_array);
- dir_write_array = NULL;
-
tor_free(exit_bytes_read);
tor_free(exit_bytes_written);
tor_free(exit_streams);
predicted_ports_free_all();
- bidi_map_free_all();
+ conn_stats_free_all();
if (circuits_for_buffer_stats) {
SMARTLIST_FOREACH(circuits_for_buffer_stats, circ_buffer_stats_t *, s,
diff --git a/src/feature/stats/rephist.h b/src/feature/stats/rephist.h
index 92c3d2a5a5..c9ebc5c328 100644
--- a/src/feature/stats/rephist.h
+++ b/src/feature/stats/rephist.h
@@ -14,18 +14,9 @@
void rep_hist_init(void);
void rep_hist_dump_stats(time_t now, int severity);
-void rep_hist_note_bytes_read(uint64_t num_bytes, time_t when);
-void rep_hist_note_bytes_written(uint64_t num_bytes, time_t when);
void rep_hist_make_router_pessimal(const char *id, time_t when);
-void rep_hist_note_dir_bytes_read(uint64_t num_bytes, time_t when);
-void rep_hist_note_dir_bytes_written(uint64_t num_bytes, time_t when);
-
-MOCK_DECL(int, rep_hist_bandwidth_assess, (void));
-char *rep_hist_get_bandwidth_lines(void);
-void rep_hist_update_state(or_state_t *state);
-int rep_hist_load_state(or_state_t *state, char **err);
void rep_history_clean(time_t before);
void rep_hist_note_router_reachable(const char *id, const tor_addr_t *at_addr,
@@ -65,18 +56,13 @@ void rep_hist_note_desc_served(const char * desc);
void rep_hist_desc_stats_term(void);
time_t rep_hist_desc_stats_write(time_t now);
-void rep_hist_conn_stats_init(time_t now);
-void rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read,
- size_t num_written, time_t when);
-void rep_hist_reset_conn_stats(time_t now);
-char *rep_hist_format_conn_stats(time_t now);
-time_t rep_hist_conn_stats_write(time_t now);
-void rep_hist_conn_stats_term(void);
-
void rep_hist_note_circuit_handshake_requested(uint16_t type);
void rep_hist_note_circuit_handshake_assigned(uint16_t type);
void rep_hist_log_circuit_handshake_stats(time_t now);
+MOCK_DECL(int, rep_hist_get_circuit_handshake_requested, (uint16_t type));
+MOCK_DECL(int, rep_hist_get_circuit_handshake_assigned, (uint16_t type));
+
void rep_hist_hs_stats_init(time_t now);
void rep_hist_hs_stats_term(void);
time_t rep_hist_hs_stats_write(time_t now);
@@ -95,16 +81,8 @@ extern uint32_t rephist_total_num;
#ifdef TOR_UNIT_TESTS
extern int onion_handshakes_requested[MAX_ONION_HANDSHAKE_TYPE+1];
extern int onion_handshakes_assigned[MAX_ONION_HANDSHAKE_TYPE+1];
-extern struct bw_array_t *write_array;
#endif
-#ifdef REPHIST_PRIVATE
-typedef struct bw_array_t bw_array_t;
-STATIC uint64_t find_largest_max(bw_array_t *b);
-STATIC void commit_max(bw_array_t *b);
-STATIC void advance_obs(bw_array_t *b);
-#endif /* defined(REPHIST_PRIVATE) */
-
/**
* Represents the type of a cell for padding accounting
*/
diff --git a/src/include.am b/src/include.am
index 657f6e823a..0826da7548 100644
--- a/src/include.am
+++ b/src/include.am
@@ -22,10 +22,11 @@ include src/lib/intmath/include.am
include src/lib/llharden/include.am
include src/lib/lock/include.am
include src/lib/log/include.am
+include src/lib/malloc/include.am
include src/lib/math/include.am
include src/lib/memarea/include.am
include src/lib/meminfo/include.am
-include src/lib/malloc/include.am
+include src/lib/metrics/include.am
include src/lib/net/include.am
include src/lib/osinfo/include.am
include src/lib/process/include.am
@@ -72,6 +73,7 @@ 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/metrics/include.am
include src/feature/nodelist/include.am
include src/feature/relay/include.am
include src/feature/rend/include.am
diff --git a/src/lib/buf/buffers.c b/src/lib/buf/buffers.c
index a5031a47a6..e9d5f7f031 100644
--- a/src/lib/buf/buffers.c
+++ b/src/lib/buf/buffers.c
@@ -14,7 +14,7 @@
*
* All socket-backed and TLS-based connection_t objects have a pair of
* buffers: one for incoming data, and one for outcoming data. These are fed
- * and drained from functions in connection.c, trigged by events that are
+ * and drained from functions in connection.c, triggered by events that are
* monitored in main.c.
*
* This module only handles the buffer implementation itself. To use a buffer
@@ -685,19 +685,22 @@ buf_move_to_buf(buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen)
}
/** Moves all data from <b>buf_in</b> to <b>buf_out</b>, without copying.
+ * Return the number of bytes that were moved.
*/
-void
+size_t
buf_move_all(buf_t *buf_out, buf_t *buf_in)
{
tor_assert(buf_out);
if (!buf_in)
- return;
+ return 0;
if (buf_datalen(buf_in) == 0)
- return;
+ return 0;
if (BUG(buf_out->datalen > BUF_MAX_LEN || buf_in->datalen > BUF_MAX_LEN))
- return;
+ return 0;
if (BUG(buf_out->datalen > BUF_MAX_LEN - buf_in->datalen))
- return;
+ return 0;
+
+ size_t n_bytes_moved = buf_in->datalen;
if (buf_out->head == NULL) {
buf_out->head = buf_in->head;
@@ -710,6 +713,8 @@ buf_move_all(buf_t *buf_out, buf_t *buf_in)
buf_out->datalen += buf_in->datalen;
buf_in->head = buf_in->tail = NULL;
buf_in->datalen = 0;
+
+ return n_bytes_moved;
}
/** Internal structure: represents a position in a buffer. */
diff --git a/src/lib/buf/buffers.h b/src/lib/buf/buffers.h
index d8a77feb72..1361a02eba 100644
--- a/src/lib/buf/buffers.h
+++ b/src/lib/buf/buffers.h
@@ -46,7 +46,7 @@ void buf_add_printf(buf_t *buf, const char *format, ...)
void buf_add_vprintf(buf_t *buf, const char *format, va_list args)
CHECK_PRINTF(2, 0);
int buf_move_to_buf(buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen);
-void buf_move_all(buf_t *buf_out, buf_t *buf_in);
+size_t buf_move_all(buf_t *buf_out, buf_t *buf_in);
void buf_peek(const buf_t *buf, char *string, size_t string_len);
void buf_drain(buf_t *buf, size_t n);
int buf_get_bytes(buf_t *buf, char *string, size_t string_len);
diff --git a/src/lib/conf/conftypes.h b/src/lib/conf/conftypes.h
index 081ebf397f..2207508ef9 100644
--- a/src/lib/conf/conftypes.h
+++ b/src/lib/conf/conftypes.h
@@ -273,7 +273,7 @@ typedef struct config_deprecation_t {
#endif /* !defined(COCCI) */
/**
- * Validation function: verify whether a configuation object is well-formed
+ * Validation function: verify whether a configuration object is well-formed
* and consistent.
*
* On success, return 0. On failure, set <b>msg_out</b> to a newly allocated
diff --git a/src/lib/confmgt/typedvar.c b/src/lib/confmgt/typedvar.c
index 1955302cdc..240c03a316 100644
--- a/src/lib/confmgt/typedvar.c
+++ b/src/lib/confmgt/typedvar.c
@@ -156,7 +156,7 @@ typed_var_copy(void *dest, const void *src, const var_type_def_t *def)
if (BUG(!def))
return -1; // LCOV_EXCL_LINE
if (def->fns->copy) {
- // If we have been provided a copy fuction, use it.
+ // If we have been provided a copy function, use it.
return def->fns->copy(dest, src, def);
}
diff --git a/src/lib/container/namemap.c b/src/lib/container/namemap.c
index e286cad947..5299c78e83 100644
--- a/src/lib/container/namemap.c
+++ b/src/lib/container/namemap.c
@@ -82,7 +82,7 @@ namemap_fmt_name(const namemap_t *map, unsigned id)
/**
* Helper: As namemap_get_id(), but requires that <b>name</b> is
- * <b>namelen</b> charaters long, and that <b>namelen</b> is no more than
+ * <b>namelen</b> characters long, and that <b>namelen</b> is no more than
* MAX_NAMEMAP_NAME_LEN.
*/
static unsigned
diff --git a/src/lib/crypt_ops/compat_openssl.h b/src/lib/crypt_ops/compat_openssl.h
index c2e1459078..aa66e0c3fa 100644
--- a/src/lib/crypt_ops/compat_openssl.h
+++ b/src/lib/crypt_ops/compat_openssl.h
@@ -34,7 +34,7 @@
#ifndef OPENSSL_1_1_API
#define OpenSSL_version(v) SSLeay_version(v)
-#define OpenSSL_version_num() SSLeay()
+#define tor_OpenSSL_version_num() SSLeay()
#define RAND_OpenSSL() RAND_SSLeay()
#define STATE_IS_SW_SERVER_HELLO(st) \
(((st) == SSL3_ST_SW_SRVR_HELLO_A) || \
@@ -42,6 +42,7 @@
#define OSSL_HANDSHAKE_STATE int
#define CONST_IF_OPENSSL_1_1_API
#else /* defined(OPENSSL_1_1_API) */
+#define tor_OpenSSL_version_num() OpenSSL_version_num()
#define STATE_IS_SW_SERVER_HELLO(st) \
((st) == TLS_ST_SW_SRVR_HELLO)
#define CONST_IF_OPENSSL_1_1_API const
diff --git a/src/lib/crypt_ops/crypto_curve25519.h b/src/lib/crypt_ops/crypto_curve25519.h
index 154a0b94bc..f1e5d1265d 100644
--- a/src/lib/crypt_ops/crypto_curve25519.h
+++ b/src/lib/crypt_ops/crypto_curve25519.h
@@ -9,6 +9,7 @@
#ifndef TOR_CRYPTO_CURVE25519_H
#define TOR_CRYPTO_CURVE25519_H
+#include <stdbool.h>
#include "lib/testsupport/testsupport.h"
#include "lib/cc/torint.h"
#include "lib/crypt_ops/crypto_digest.h"
@@ -77,7 +78,8 @@ STATIC int curve25519_basepoint_impl(uint8_t *output, const uint8_t *secret);
int curve25519_public_from_base64(curve25519_public_key_t *pkey,
const char *input);
void curve25519_public_to_base64(char *output,
- const curve25519_public_key_t *pkey);
+ const curve25519_public_key_t *pkey,
+ bool pad);
void curve25519_set_impl_params(int use_ed);
void curve25519_init(void);
diff --git a/src/lib/crypt_ops/crypto_dh_openssl.c b/src/lib/crypt_ops/crypto_dh_openssl.c
index c5f7271596..f05afd8497 100644
--- a/src/lib/crypt_ops/crypto_dh_openssl.c
+++ b/src/lib/crypt_ops/crypto_dh_openssl.c
@@ -163,7 +163,7 @@ crypto_dh_init_openssl(void)
/** Number of bits to use when choosing the x or y value in a Diffie-Hellman
* handshake. Since we exponentiate by this value, choosing a smaller one
- * lets our handhake go faster.
+ * lets our handshake go faster.
*/
#define DH_PRIVATE_KEY_BITS 320
diff --git a/src/lib/crypt_ops/crypto_format.c b/src/lib/crypt_ops/crypto_format.c
index 92b8b9372e..4483b7d2f5 100644
--- a/src/lib/crypt_ops/crypto_format.c
+++ b/src/lib/crypt_ops/crypto_format.c
@@ -131,9 +131,10 @@ crypto_read_tagged_contents_from_file(const char *fname,
return r;
}
-/** Encode <b>pkey</b> as a base64-encoded string, including trailing "="
- * characters, in the buffer <b>output</b>, which must have at least
- * CURVE25519_BASE64_PADDED_LEN+1 bytes available.
+/** Encode <b>pkey</b> as a base64-encoded string in the buffer <b>output</b>.
+ * If <b>pad</b> is false do not include trailing "=" characters, otherwise
+ * include them. <b>output</b> must have at least
+ * CURVE25519_BASE64_PADDED_LEN+1 bytes available, even if <b>pad</b> is false.
* Can not fail.
*
* Careful! CURVE25519_BASE64_PADDED_LEN is one byte longer than
@@ -141,17 +142,25 @@ crypto_read_tagged_contents_from_file(const char *fname,
*/
void
curve25519_public_to_base64(char *output,
- const curve25519_public_key_t *pkey)
+ const curve25519_public_key_t *pkey, bool pad)
{
- char buf[128];
- int n = base64_encode(buf, sizeof(buf),
- (const char*)pkey->public_key,
- CURVE25519_PUBKEY_LEN, 0);
+ int n, expected_len;
+ if (pad) {
+ n = base64_encode(output, CURVE25519_BASE64_PADDED_LEN+1,
+ (const char*)pkey->public_key,
+ CURVE25519_PUBKEY_LEN, 0);
+ expected_len = CURVE25519_BASE64_PADDED_LEN;
+ } else {
+ n = base64_encode_nopad(output, CURVE25519_BASE64_PADDED_LEN+1,
+ (const uint8_t*)pkey->public_key,
+ CURVE25519_PUBKEY_LEN);
+ expected_len = CURVE25519_BASE64_LEN;
+ }
+
/* These asserts should always succeed, unless there is a bug in
* base64_encode(). */
- tor_assert(n == CURVE25519_BASE64_PADDED_LEN);
- tor_assert(buf[CURVE25519_BASE64_PADDED_LEN] == '\0');
- memcpy(output, buf, CURVE25519_BASE64_PADDED_LEN+1);
+ tor_assert(n == expected_len);
+ tor_assert(output[expected_len] == '\0');
}
/** Try to decode a base64-encoded curve25519 public key from <b>input</b>
@@ -162,11 +171,11 @@ curve25519_public_from_base64(curve25519_public_key_t *pkey,
const char *input)
{
size_t len = strlen(input);
- if (len == CURVE25519_BASE64_PADDED_LEN - 1) {
+ if (len == CURVE25519_BASE64_LEN) {
/* not padded */
return digest256_from_base64((char*)pkey->public_key, input);
} else if (len == CURVE25519_BASE64_PADDED_LEN) {
- char buf[128];
+ char buf[CURVE25519_BASE64_PADDED_LEN+1];
if (base64_decode(buf, sizeof(buf), input, len) != CURVE25519_PUBKEY_LEN)
return -1;
memcpy(pkey->public_key, buf, CURVE25519_PUBKEY_LEN);
diff --git a/src/lib/crypt_ops/crypto_openssl_mgt.c b/src/lib/crypt_ops/crypto_openssl_mgt.c
index 065cbca1cc..e763491a11 100644
--- a/src/lib/crypt_ops/crypto_openssl_mgt.c
+++ b/src/lib/crypt_ops/crypto_openssl_mgt.c
@@ -222,7 +222,7 @@ crypto_openssl_early_init(void)
setup_openssl_threading();
- unsigned long version_num = OpenSSL_version_num();
+ unsigned long version_num = tor_OpenSSL_version_num();
const char *version_str = crypto_openssl_get_version_str();
if (version_num == OPENSSL_VERSION_NUMBER &&
!strcmp(version_str, OPENSSL_VERSION_TEXT)) {
diff --git a/src/lib/crypt_ops/crypto_openssl_mgt.h b/src/lib/crypt_ops/crypto_openssl_mgt.h
index c67ab6467c..91df084a15 100644
--- a/src/lib/crypt_ops/crypto_openssl_mgt.h
+++ b/src/lib/crypt_ops/crypto_openssl_mgt.h
@@ -57,7 +57,7 @@
#if OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) && \
!defined(LIBRESSL_VERSION_NUMBER)
/* OpenSSL as of 1.1.0pre4 has an "new" thread API, which doesn't require
- * seting up various callbacks.
+ * setting up various callbacks.
*
* OpenSSL 1.1.0pre4 has a messed up `ERR_remove_thread_state()` prototype,
* while the previous one was restored in pre5, and the function made a no-op
diff --git a/src/lib/defs/x25519_sizes.h b/src/lib/defs/x25519_sizes.h
index acb08c5e6a..e650f5a350 100644
--- a/src/lib/defs/x25519_sizes.h
+++ b/src/lib/defs/x25519_sizes.h
@@ -36,6 +36,9 @@
/** Length of a Curve25519 key when encoded in base 64, with padding. */
#define CURVE25519_BASE64_PADDED_LEN 44
+/** Length of a Curve25519 key when encoded in base 64, without padding. */
+#define CURVE25519_BASE64_LEN 43
+
/** 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. */
diff --git a/src/lib/dispatch/dispatch.h b/src/lib/dispatch/dispatch.h
index 9c7c4833c2..63e96bcf8d 100644
--- a/src/lib/dispatch/dispatch.h
+++ b/src/lib/dispatch/dispatch.h
@@ -37,7 +37,7 @@
* configure messages with their types, channels, and receivers. Then, use
* dispatch_new() with that dispatch_cfg_t to create the dispatch_t object.
*
- * (We use a two-phase contruction procedure here to enable better static
+ * (We use a two-phase construction procedure here to enable better static
* reasoning about publish/subscribe relationships.)
*
* Once you have a dispatch_t, you can queue messages on it with
diff --git a/src/lib/encoding/binascii.c b/src/lib/encoding/binascii.c
index 3e549eb8e3..5f68da183f 100644
--- a/src/lib/encoding/binascii.c
+++ b/src/lib/encoding/binascii.c
@@ -275,7 +275,7 @@ base64_encode(char *dest, size_t destlen, const char *src, size_t srclen,
}
switch (n_idx) {
case 0:
- /* 0 leftover bits, no pading to add. */
+ /* 0 leftover bits, no padding to add. */
break;
case 1:
/* 8 leftover bits, pad to 12 bits, write the 2 6-bit values followed
diff --git a/src/lib/fs/conffile.c b/src/lib/fs/conffile.c
index 9583093c12..0d0bdf09a6 100644
--- a/src/lib/fs/conffile.c
+++ b/src/lib/fs/conffile.c
@@ -19,8 +19,12 @@
#include "lib/fs/path.h"
#include "lib/log/log.h"
#include "lib/malloc/malloc.h"
+#include "lib/sandbox/sandbox.h"
#include "lib/string/printf.h"
+#include <stdbool.h>
+#include <errno.h>
+
static smartlist_t *config_get_file_list(const char *path,
smartlist_t *opened_files);
static int config_get_included_config(const char *path, int recursion_level,
@@ -50,62 +54,121 @@ config_get_lines_include(const char *string, config_line_t **result,
opened_lst, 1, NULL, config_process_include);
}
-/** Adds a list of configuration files present on <b>path</b> to
- * <b>file_list</b>. <b>path</b> can be a file or a directory. If it is a file,
- * only that file will be added to <b>file_list</b>. If it is a directory,
- * all paths for files on that directory root (no recursion) except for files
- * whose name starts with a dot will be added to <b>file_list</b>.
- * <b>opened_files</b> will have a list of files opened by this function
- * if provided. Return 0 on success, -1 on failure. Ignores empty files.
- */
+/** Return a list of paths obtained when expading globs in <b>pattern</b>.
+ * If <b>pattern</b> has no globs, return a list with <b>pattern</b> in it.
+ * If <b>opened_files</b> is provided, add paths opened by glob to it.
+ * Return NULL on failure. */
static smartlist_t *
-config_get_file_list(const char *path, smartlist_t *opened_files)
+expand_glob(const char *pattern, smartlist_t *opened_files)
{
- smartlist_t *file_list = smartlist_new();
+ if (! has_glob(pattern)) {
+ smartlist_t *matches = smartlist_new();
+ smartlist_add_strdup(matches, pattern);
+ return matches;
+ }
- if (opened_files) {
- smartlist_add_strdup(opened_files, path);
+ smartlist_t *matches = tor_glob(pattern);
+ if (!matches) {
+ if (errno == EPERM) {
+ log_err(LD_CONFIG, "Sandbox is active, but the configuration pattern "
+ "\"%s\" listed with %%include would access files or folders not "
+ "allowed by it. Cannot proceed.", pattern);
+ }
+ return NULL;
}
- file_status_t file_type = file_status(path);
- if (file_type == FN_FILE) {
- smartlist_add_strdup(file_list, path);
- return file_list;
- } else if (file_type == FN_DIR) {
- smartlist_t *all_files = tor_listdir(path);
- if (!all_files) {
- smartlist_free(file_list);
+ if (opened_files) {
+ smartlist_t *glob_opened = get_glob_opened_files(pattern);
+ if (!glob_opened) {
+ SMARTLIST_FOREACH(matches, char *, f, tor_free(f));
+ smartlist_free(matches);
return NULL;
}
- smartlist_sort_strings(all_files);
- SMARTLIST_FOREACH_BEGIN(all_files, char *, f) {
- if (f[0] == '.') {
- tor_free(f);
- continue;
- }
+ smartlist_add_all(opened_files, glob_opened);
+ smartlist_free(glob_opened);
+ }
+ smartlist_sort_strings(matches);
+ return matches;
+}
+
+/** Returns a list of configuration files present on paths that match
+ * <b>pattern</b>. The pattern is expanded and then all the paths are
+ * processed. A path can be a file or a directory. If it is a file, that file
+ * will be added to the list to be returned. If it is a directory,
+ * all paths for files on that directory root (no recursion) except for files
+ * whose name starts with a dot will be added to the list to be returned.
+ * <b>opened_files</b> will have a list of files opened by this function
+ * if provided. Return NULL on failure. Ignores empty files.
+ */
+static smartlist_t *
+config_get_file_list(const char *pattern, smartlist_t *opened_files)
+{
+ smartlist_t *glob_matches = expand_glob(pattern, opened_files);
+ if (!glob_matches) {
+ return NULL;
+ }
- char *fullname;
- tor_asprintf(&fullname, "%s"PATH_SEPARATOR"%s", path, f);
- tor_free(f);
+ bool error_found = false;
+ smartlist_t *file_list = smartlist_new();
+ SMARTLIST_FOREACH_BEGIN(glob_matches, char *, path) {
+ if (opened_files) {
+ smartlist_add_strdup(opened_files, path);
+ }
+ if (sandbox_interned_string_is_missing(path)) {
+ log_err(LD_CONFIG, "Sandbox is active, but a new configuration "
+ "file \"%s\" has been listed with %%include. Cannot proceed.",
+ path);
+ error_found = true;
+ break;
+ }
- if (opened_files) {
- smartlist_add_strdup(opened_files, fullname);
+ file_status_t file_type = file_status(path);
+ if (file_type == FN_FILE) {
+ smartlist_add_strdup(file_list, path);
+ } else if (file_type == FN_DIR) {
+ smartlist_t *all_files = tor_listdir(path);
+ if (!all_files) {
+ error_found = true;
+ break;
}
-
- if (file_status(fullname) != FN_FILE) {
- tor_free(fullname);
+ smartlist_sort_strings(all_files);
+ SMARTLIST_FOREACH_BEGIN(all_files, char *, f) {
+ if (f[0] == '.') {
+ continue;
+ }
+
+ char *fullname;
+ tor_asprintf(&fullname, "%s"PATH_SEPARATOR"%s", path, f);
+
+ if (opened_files) {
+ smartlist_add_strdup(opened_files, fullname);
+ }
+
+ if (file_status(fullname) != FN_FILE) {
+ tor_free(fullname);
+ continue;
+ }
+ smartlist_add(file_list, fullname);
+ } SMARTLIST_FOREACH_END(f);
+ SMARTLIST_FOREACH(all_files, char *, f, tor_free(f));
+ smartlist_free(all_files);
+ } else if (file_type == FN_EMPTY) {
continue;
- }
- smartlist_add(file_list, fullname);
- } SMARTLIST_FOREACH_END(f);
- smartlist_free(all_files);
- return file_list;
- } else if (file_type == FN_EMPTY) {
- return file_list;
- } else {
+ } else {
+ error_found = true;
+ break;
+ }
+ } SMARTLIST_FOREACH_END(path);
+ SMARTLIST_FOREACH(glob_matches, char *, f, tor_free(f));
+ smartlist_free(glob_matches);
+
+ if (error_found) {
+ SMARTLIST_FOREACH(file_list, char *, f, tor_free(f));
smartlist_free(file_list);
- return NULL;
+ file_list = NULL;
}
+
+ return file_list;
}
/** Creates a list of config lines present on included <b>path</b>.
@@ -133,25 +196,32 @@ config_get_included_config(const char *path, int recursion_level, int extended,
return 0;
}
-/** Process an %include <b>path</b> in a config file. Set <b>list</b> to the
+/** Process an %include <b>pattern</b> in a config file. Set <b>list</b> to the
* list of configuration settings obtained and <b>list_last</b> to the last
* element of the same list. <b>opened_lst</b> will have a list of opened
* files if provided. Return 0 on success, -1 on failure. */
static int
-config_process_include(const char *path, int recursion_level, int extended,
+config_process_include(const char *pattern, int recursion_level, int extended,
config_line_t **list, config_line_t **list_last,
smartlist_t *opened_lst)
{
config_line_t *ret_list = NULL;
config_line_t **next = &ret_list;
- smartlist_t *config_files = config_get_file_list(path, opened_lst);
+ smartlist_t *config_files = config_get_file_list(pattern, opened_lst);
if (!config_files) {
return -1;
}
int rv = -1;
SMARTLIST_FOREACH_BEGIN(config_files, const char *, config_file) {
+ if (sandbox_interned_string_is_missing(config_file)) {
+ log_err(LD_CONFIG, "Sandbox is active, but a new configuration "
+ "file \"%s\" has been listed with %%include. Cannot proceed.",
+ config_file);
+ goto done;
+ }
+
log_notice(LD_CONFIG, "Including configuration file \"%s\".", config_file);
config_line_t *included_config = NULL;
config_line_t *included_config_last = NULL;
diff --git a/src/lib/fs/files.c b/src/lib/fs/files.c
index a0b5a40aac..aff78db718 100644
--- a/src/lib/fs/files.c
+++ b/src/lib/fs/files.c
@@ -247,6 +247,22 @@ file_status(const char *fname)
}
}
+/** Returns true if <b>file_type</b> represents an existing file (even if
+ * empty). Returns false otherwise. */
+bool
+is_file(file_status_t file_type)
+{
+ return file_type != FN_ERROR && file_type != FN_NOENT && file_type != FN_DIR;
+}
+
+/** Returns true if <b>file_type</b> represents an existing directory. Returns
+ * false otherwise. */
+bool
+is_dir(file_status_t file_type)
+{
+ return file_type == FN_DIR;
+}
+
/** Create a file named <b>fname</b> with the contents <b>str</b>. Overwrite
* the previous <b>fname</b> if possible. Return 0 on success, -1 on failure.
*
@@ -718,6 +734,26 @@ read_file_to_str, (const char *filename, int flags, struct stat *stat_out))
return string;
}
+/** Attempt to read a file <b>fname</b>. If the file's contents is
+ * equal to the string <b>str</b>, return 0. Otherwise, attempt to
+ * overwrite the file with the contents of <b>str</b> and return
+ * the value of write_str_to_file().
+ */
+int
+write_str_to_file_if_not_equal(const char *fname, const char *str)
+{
+ char *fstr = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL);
+ int rv;
+
+ if (!fstr || strcmp(str, fstr)) {
+ rv = write_str_to_file(fname, str, 0);
+ } else {
+ rv = 0;
+ }
+ tor_free(fstr);
+ return rv;
+}
+
#if !defined(HAVE_GETDELIM) || defined(TOR_UNIT_TESTS)
#include "ext/getdelim.c"
#endif
diff --git a/src/lib/fs/files.h b/src/lib/fs/files.h
index a109cd6248..f0178e2b5b 100644
--- a/src/lib/fs/files.h
+++ b/src/lib/fs/files.h
@@ -55,6 +55,8 @@ MOCK_DECL(int,tor_unlink,(const char *pathname));
typedef enum { FN_ERROR, FN_NOENT, FN_FILE, FN_DIR, FN_EMPTY } file_status_t;
file_status_t file_status(const char *filename);
+bool is_file(file_status_t file_type);
+bool is_dir(file_status_t file_type);
int64_t tor_get_avail_disk_space(const char *path);
@@ -91,6 +93,8 @@ int append_bytes_to_file(const char *fname, const char *str, size_t len,
int write_bytes_to_new_file(const char *fname, const char *str, size_t len,
int bin);
+int write_str_to_file_if_not_equal(const char *fname, const char *str);
+
/** Flag for read_file_to_str: open the file in binary mode. */
#define RFTS_BIN 1
/** Flag for read_file_to_str: it's okay if the file doesn't exist. */
diff --git a/src/lib/fs/path.c b/src/lib/fs/path.c
index 0d57be4b06..81960bd69a 100644
--- a/src/lib/fs/path.c
+++ b/src/lib/fs/path.c
@@ -13,15 +13,34 @@
#include "lib/malloc/malloc.h"
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
+#include "lib/container/smartlist.h"
+#include "lib/sandbox/sandbox.h"
#include "lib/string/printf.h"
#include "lib/string/util_string.h"
#include "lib/string/compat_ctype.h"
+#include "lib/string/compat_string.h"
+#include "lib/fs/files.h"
+#include "lib/fs/dir.h"
#include "lib/fs/userdb.h"
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#ifdef _WIN32
+#include <windows.h>
+#include <shlwapi.h>
+#else /* !(defined(_WIN32)) */
+#include <dirent.h>
+#include <glob.h>
+#endif /* defined(_WIN32) */
+
#include <errno.h>
#include <string.h>
@@ -161,7 +180,7 @@ clean_fname_for_stat(char *name)
/** Modify <b>fname</b> to contain the name of its parent directory. Doesn't
* actually examine the filesystem; does a purely syntactic modification.
*
- * The parent of the root director is considered to be iteself.
+ * The parent of the root director is considered to be itself.
*
* Path separators are the forward slash (/) everywhere and additionally
* the backslash (\) on Win32.
@@ -294,3 +313,397 @@ make_path_absolute(const char *fname)
return absfname;
#endif /* defined(_WIN32) */
}
+
+/* The code below implements tor_glob and get_glob_opened_files. Because it is
+ * not easy to understand it by looking at individual functions, the big
+ * picture explanation here should be read first.
+ *
+ * Purpose of the functions:
+ * - tor_glob - receives a pattern and returns all the paths that result from
+ * its glob expansion, globs can be present on all path components.
+ * - get_glob_opened_files - receives a pattern and returns all the paths that
+ * are opened during its expansion (the paths before any path fragment that
+ * contains a glob as they have to be opened to check for glob matches). This
+ * is used to get the paths that have to be added to the seccomp sandbox
+ * allowed list.
+ *
+ * Due to OS API differences explained below, the implementation of tor_glob is
+ * completely different for Windows and POSIX systems, so we ended up with
+ * three different implementations:
+ * - tor_glob for POSIX - as POSIX glob does everything we need, we simply call
+ * it and process the results. This is completely implemented in tor_glob.
+ * - tor_glob for WIN32 - because the WIN32 API only supports expanding globs
+ * in the last path fragment, we need to expand the globs in each path
+ * fragment manually and call recursively to get the same behaviour as POSIX
+ * glob. When there are no globs in pattern, we know we are on the last path
+ * fragment and collect the full path.
+ * - get_glob_opened_files - because the paths before any path fragment with a
+ * glob will be opened to check for matches, we need to collect them and we
+ * need to expand the globs in each path fragments and call recursively until
+ * we find no more globs.
+ *
+ * As seen from the description above, both tor_glob for WIN32 and
+ * get_glob_opened_files receive a pattern and return a list of paths and have
+ * to expand all path fragments that contain globs and call themselves
+ * recursively. The differences are:
+ * - get_glob_opened_files collects paths before path fragments with globs
+ * while tor_glob for WIN32 collects full paths resulting from the expansion
+ * of all globs.
+ * - get_glob_opened_files can call tor_glob to expand path fragments with
+ * globs while tor_glob for WIN32 cannot because it IS tor_glob. For tor_glob
+ * for WIN32, an auxiliary function has to be used for this purpose.
+ *
+ * To avoid code duplication, the logic of tor_glob for WIN32 and
+ * get_glob_opened_files is implemented in get_glob_paths. The differences are
+ * configured by the extra function parameters:
+ * - final - if true, returns a list of paths obtained from expanding pattern
+ * (implements tor_glob). Otherwise, returns the paths before path fragments
+ * with globs (implements get_glob_opened_files).
+ * - unglob - function used to expand a path fragment. The function signature
+ * is defined by the unglob_fn typedef. Two implementations are available:
+ * - unglob_win32 - uses tor_listdir and PathMatchSpec (for tor_glob WIN32)
+ * - unglob_opened_files - uses tor_glob (for get_glob_opened_files)
+ */
+
+/** Returns true if the character at position <b>pos</b> in <b>pattern</b> is
+ * considered a glob. Returns false otherwise. Takes escaping into account on
+ * systems where escaping globs is supported. */
+static inline bool
+is_glob_char(const char *pattern, int pos)
+{
+ bool is_glob = pattern[pos] == '*' || pattern[pos] == '?';
+#ifdef _WIN32
+ return is_glob;
+#else /* !defined(_WIN32) */
+ bool is_escaped = pos > 0 && pattern[pos-1] == '\\';
+ return is_glob && !is_escaped;
+#endif /* defined(_WIN32) */
+}
+
+/** Expands the first path fragment of <b>pattern</b> that contains globs. The
+ * path fragment is between <b>prev_sep</b> and <b>next_sep</b>. If the path
+ * fragment is the last fragment of <b>pattern</b>, <b>next_sep</b> will be the
+ * index of the last char. Returns a list of paths resulting from the glob
+ * expansion of the path fragment. Anything after <b>next_sep</b> is not
+ * included in the returned list. Returns NULL on failure. */
+typedef struct smartlist_t * unglob_fn(const char *pattern, int prev_sep,
+ int next_sep);
+
+/** Adds <b>path</b> to <b>result</b> if it exists and is a file type we can
+ * handle. Returns false if <b>path</b> is a file type we cannot handle,
+ * returns true otherwise. Used on tor_glob for WIN32. */
+static bool
+add_non_glob_path(const char *path, struct smartlist_t *result)
+{
+ file_status_t file_type = file_status(path);
+ if (file_type == FN_ERROR) {
+ return false;
+ } else if (file_type != FN_NOENT) {
+ char *to_add = tor_strdup(path);
+ clean_fname_for_stat(to_add);
+ smartlist_add(result, to_add);
+ }
+ /* If WIN32 tor_glob is called with a non-existing path, we want it to
+ * return an empty list instead of error to match the regular version */
+ return true;
+}
+
+/** Auxiliary function used by get_glob_opened_files and WIN32 tor_glob.
+ * Returns a list of paths obtained from <b>pattern</b> using <b>unglob</b> to
+ * expand each path fragment. If <b>final</b> is true, the paths are the result
+ * of the glob expansion of <b>pattern</b> (implements tor_glob). Otherwise,
+ * the paths are the paths opened by glob while expanding <b>pattern</b>
+ * (implements get_glob_opened_files). Returns NULL on failure. */
+static struct smartlist_t *
+get_glob_paths(const char *pattern, unglob_fn unglob, bool final)
+{
+ smartlist_t *result = smartlist_new();
+ int i, prev_sep = -1, next_sep = -1;
+ bool is_glob = false, error_found = false, is_sep = false, is_last = false;
+
+ // find first path fragment with globs
+ for (i = 0; pattern[i]; i++) {
+ is_glob = is_glob || is_glob_char(pattern, i);
+ is_last = !pattern[i+1];
+ is_sep = pattern[i] == *PATH_SEPARATOR || pattern[i] == '/';
+ if (is_sep || is_last) {
+ prev_sep = next_sep;
+ next_sep = i; // next_sep+1 is start of next fragment or end of string
+ if (is_glob) {
+ break;
+ }
+ }
+ }
+
+ if (!is_glob) { // pattern fully expanded or no glob in pattern
+ if (final && !add_non_glob_path(pattern, result)) {
+ error_found = true;
+ goto end;
+ }
+ return result;
+ }
+
+ if (!final) {
+ // add path before the glob to result
+ int len = prev_sep < 1 ? prev_sep + 1 : prev_sep; // handle /*
+ char *path_until_glob = tor_strndup(pattern, len);
+ smartlist_add(result, path_until_glob);
+ }
+
+ smartlist_t *unglobbed_paths = unglob(pattern, prev_sep, next_sep);
+ if (!unglobbed_paths) {
+ error_found = true;
+ } else {
+ // for each path for current fragment, add the rest of the pattern
+ // and call recursively to get all expanded paths
+ SMARTLIST_FOREACH_BEGIN(unglobbed_paths, char *, current_path) {
+ char *next_path;
+ tor_asprintf(&next_path, "%s"PATH_SEPARATOR"%s", current_path,
+ &pattern[next_sep+1]);
+ smartlist_t *opened_next = get_glob_paths(next_path, unglob, final);
+ tor_free(next_path);
+ if (!opened_next) {
+ error_found = true;
+ break;
+ }
+ smartlist_add_all(result, opened_next);
+ smartlist_free(opened_next);
+ } SMARTLIST_FOREACH_END(current_path);
+ SMARTLIST_FOREACH(unglobbed_paths, char *, p, tor_free(p));
+ smartlist_free(unglobbed_paths);
+ }
+
+end:
+ if (error_found) {
+ SMARTLIST_FOREACH(result, char *, p, tor_free(p));
+ smartlist_free(result);
+ result = NULL;
+ }
+ return result;
+}
+
+#ifdef _WIN32
+/** Expands globs in <b>pattern</b> for the path fragment between
+ * <b>prev_sep</b> and <b>next_sep</b> using the WIN32 API. Returns NULL on
+ * failure. Used by the WIN32 implementation of tor_glob. Implements unglob_fn,
+ * see its description for more details. */
+static struct smartlist_t *
+unglob_win32(const char *pattern, int prev_sep, int next_sep)
+{
+ smartlist_t *result = smartlist_new();
+ int len = prev_sep < 1 ? prev_sep + 1 : prev_sep; // handle /*
+ char *path_until_glob = tor_strndup(pattern, len);
+
+ if (!is_file(file_status(path_until_glob))) {
+ smartlist_t *filenames = tor_listdir(path_until_glob);
+ if (!filenames) {
+ smartlist_free(result);
+ result = NULL;
+ } else {
+ SMARTLIST_FOREACH_BEGIN(filenames, char *, filename) {
+ TCHAR tpattern[MAX_PATH] = {0};
+ TCHAR tfile[MAX_PATH] = {0};
+ char *full_path;
+ tor_asprintf(&full_path, "%s"PATH_SEPARATOR"%s",
+ path_until_glob, filename);
+ char *path_curr_glob = tor_strndup(pattern, next_sep + 1);
+ // *\ must return only dirs, remove \ from the pattern so it matches
+ if (is_dir(file_status(full_path))) {
+ clean_fname_for_stat(path_curr_glob);
+ }
+#ifdef UNICODE
+ mbstowcs(tpattern, path_curr_glob, MAX_PATH);
+ mbstowcs(tfile, full_path, MAX_PATH);
+#else /* !defined(UNICODE) */
+ strlcpy(tpattern, path_curr_glob, MAX_PATH);
+ strlcpy(tfile, full_path, MAX_PATH);
+#endif /* defined(UNICODE) */
+ if (PathMatchSpec(tfile, tpattern)) {
+ smartlist_add(result, full_path);
+ } else {
+ tor_free(full_path);
+ }
+ tor_free(path_curr_glob);
+ } SMARTLIST_FOREACH_END(filename);
+ SMARTLIST_FOREACH(filenames, char *, p, tor_free(p));
+ smartlist_free(filenames);
+ }
+ }
+ tor_free(path_until_glob);
+ return result;
+}
+#elif HAVE_GLOB
+/** Same as opendir but calls sandbox_intern_string before */
+static DIR *
+prot_opendir(const char *name)
+{
+ if (sandbox_interned_string_is_missing(name)) {
+ errno = EPERM;
+ return NULL;
+ }
+ return opendir(sandbox_intern_string(name));
+}
+
+/** Same as stat but calls sandbox_intern_string before */
+static int
+prot_stat(const char *pathname, struct stat *buf)
+{
+ if (sandbox_interned_string_is_missing(pathname)) {
+ errno = EPERM;
+ return -1;
+ }
+ return stat(sandbox_intern_string(pathname), buf);
+}
+
+/** Same as lstat but calls sandbox_intern_string before */
+static int
+prot_lstat(const char *pathname, struct stat *buf)
+{
+ if (sandbox_interned_string_is_missing(pathname)) {
+ errno = EPERM;
+ return -1;
+ }
+ return lstat(sandbox_intern_string(pathname), buf);
+}
+/** As closedir, but has the right type for gl_closedir */
+static void
+wrap_closedir(void *arg)
+{
+ closedir(arg);
+}
+
+/** Function passed to glob to handle processing errors. <b>epath</b> is the
+ * path that caused the error and <b>eerrno</b> is the errno set by the
+ * function that failed. We want to ignore ENOENT and ENOTDIR because, in BSD
+ * systems, these are not ignored automatically, which makes glob fail when
+ * globs expand to non-existing paths and GLOB_ERR is set.
+ */
+static int
+glob_errfunc(const char *epath, int eerrno)
+{
+ (void)epath;
+ return eerrno == ENOENT || eerrno == ENOTDIR ? 0 : -1;
+}
+#endif /* defined(HAVE_GLOB) */
+
+/** Return a new list containing the paths that match the pattern
+ * <b>pattern</b>. Return NULL on error. On POSIX systems, errno is set by the
+ * glob function or is set to EPERM if glob tried to access a file not allowed
+ * by the seccomp sandbox.
+ */
+struct smartlist_t *
+tor_glob(const char *pattern)
+{
+ smartlist_t *result = NULL;
+
+#ifdef _WIN32
+ // PathMatchSpec does not support forward slashes, change them to backslashes
+ char *pattern_normalized = tor_strdup(pattern);
+ tor_strreplacechar(pattern_normalized, '/', *PATH_SEPARATOR);
+ result = get_glob_paths(pattern_normalized, unglob_win32, true);
+ tor_free(pattern_normalized);
+#elif HAVE_GLOB /* !(defined(_WIN32)) */
+ glob_t matches;
+ int flags = GLOB_NOSORT;
+#ifdef GLOB_ALTDIRFUNC
+ /* use functions that call sandbox_intern_string */
+ flags |= GLOB_ALTDIRFUNC;
+ typedef void *(*gl_opendir)(const char * name);
+ typedef struct dirent *(*gl_readdir)(void *);
+ typedef void (*gl_closedir)(void *);
+ matches.gl_opendir = (gl_opendir) &prot_opendir;
+ matches.gl_readdir = (gl_readdir) &readdir;
+ matches.gl_closedir = (gl_closedir) &wrap_closedir;
+ matches.gl_stat = &prot_stat;
+ matches.gl_lstat = &prot_lstat;
+#endif /* defined(GLOB_ALTDIRFUNC) */
+ // use custom error handler to workaround BSD quirks and do not set GLOB_ERR
+ // because it would make glob fail on error even if the error handler ignores
+ // the error
+ int ret = glob(pattern, flags, glob_errfunc, &matches);
+ if (ret == GLOB_NOMATCH) {
+ return smartlist_new();
+ } else if (ret != 0) {
+ return NULL;
+ }
+
+ // #40141: workaround for bug in glibc < 2.19 where patterns ending in path
+ // separator match files and folders instead of folders only
+ size_t pattern_len = strlen(pattern);
+ bool dir_only = has_glob(pattern) &&
+ pattern_len > 0 && pattern[pattern_len-1] == *PATH_SEPARATOR;
+
+ result = smartlist_new();
+ size_t i;
+ for (i = 0; i < matches.gl_pathc; i++) {
+ char *match = tor_strdup(matches.gl_pathv[i]);
+ size_t len = strlen(match);
+ if (len > 0 && match[len-1] == *PATH_SEPARATOR) {
+ match[len-1] = '\0';
+ }
+
+ if (!dir_only || (dir_only && is_dir(file_status(match)))) {
+ smartlist_add(result, match);
+ } else {
+ tor_free(match);
+ }
+ }
+ globfree(&matches);
+#else
+ (void)pattern;
+ return result;
+#endif /* !defined(HAVE_GLOB) */
+
+ return result;
+}
+
+/** Returns true if <b>s</b> contains characters that can be globbed.
+ * Returns false otherwise. */
+bool
+has_glob(const char *s)
+{
+ int i;
+ for (i = 0; s[i]; i++) {
+ if (is_glob_char(s, i)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/** Expands globs in <b>pattern</b> for the path fragment between
+ * <b>prev_sep</b> and <b>next_sep</b> using tor_glob. Returns NULL on
+ * failure. Used by get_glob_opened_files. Implements unglob_fn, see its
+ * description for more details. */
+static struct smartlist_t *
+unglob_opened_files(const char *pattern, int prev_sep, int next_sep)
+{
+ (void)prev_sep;
+ smartlist_t *result = smartlist_new();
+ // if the following fragments have no globs, we're done
+ if (has_glob(&pattern[next_sep+1])) {
+ // if there is a glob after next_sep, we know next_sep is a separator and
+ // not the last char and glob_path will have the path without the separator
+ char *glob_path = tor_strndup(pattern, next_sep);
+ smartlist_t *child_paths = tor_glob(glob_path);
+ tor_free(glob_path);
+ if (!child_paths) {
+ smartlist_free(result);
+ result = NULL;
+ } else {
+ smartlist_add_all(result, child_paths);
+ smartlist_free(child_paths);
+ }
+ }
+ return result;
+}
+
+/** Returns a list of files that are opened by the tor_glob function when
+ * called with <b>pattern</b>. Returns NULL on error. The purpose of this
+ * function is to create a list of files to be added to the sandbox white list
+ * before the sandbox is enabled. */
+struct smartlist_t *
+get_glob_opened_files(const char *pattern)
+{
+ return get_glob_paths(pattern, unglob_opened_files, false);
+}
diff --git a/src/lib/fs/path.h b/src/lib/fs/path.h
index f0e253c556..425bd12516 100644
--- a/src/lib/fs/path.h
+++ b/src/lib/fs/path.h
@@ -12,6 +12,10 @@
#ifndef TOR_PATH_H
#define TOR_PATH_H
+#include <stdbool.h>
+#ifdef _WIN32
+#include <windows.h>
+#endif
#include "lib/cc/compat_compiler.h"
#ifdef _WIN32
@@ -26,5 +30,8 @@ int path_is_relative(const char *filename);
void clean_fname_for_stat(char *name);
int get_parent_directory(char *fname);
char *make_path_absolute(const char *fname);
+struct smartlist_t *tor_glob(const char *pattern);
+bool has_glob(const char *s);
+struct smartlist_t *get_glob_opened_files(const char *pattern);
#endif /* !defined(TOR_PATH_H) */
diff --git a/src/lib/log/log.c b/src/lib/log/log.c
index 9ee87c0668..411408966b 100644
--- a/src/lib/log/log.c
+++ b/src/lib/log/log.c
@@ -51,10 +51,6 @@
#include "lib/fdio/fdio.h"
#include "lib/cc/ctassert.h"
-#ifdef HAVE_ANDROID_LOG_H
-#include <android/log.h>
-#endif // HAVE_ANDROID_LOG_H.
-
/** @{ */
/** The string we stick at the end of a log message when it is too long,
* and its length. */
@@ -78,8 +74,6 @@ typedef struct logfile_t {
int needs_close; /**< Boolean: true if the stream gets closed on shutdown. */
int is_temporary; /**< Boolean: close after initializing logging subsystem.*/
int is_syslog; /**< Boolean: send messages to syslog. */
- int is_android; /**< Boolean: send messages to Android's log subsystem. */
- char *android_tag; /**< Identity Tag used in Android's log subsystem. */
log_callback callback; /**< If not NULL, send messages to this function. */
log_severity_list_t *severities; /**< Which severity of messages should we
* log for each log domain? */
@@ -126,33 +120,6 @@ should_log_function_name(log_domain_mask_t domain, int severity)
}
}
-#ifdef HAVE_ANDROID_LOG_H
-/** Helper function to convert Tor's log severity into the matching
- * Android log priority.
- */
-static int
-severity_to_android_log_priority(int severity)
-{
- switch (severity) {
- case LOG_DEBUG:
- return ANDROID_LOG_VERBOSE;
- case LOG_INFO:
- return ANDROID_LOG_DEBUG;
- case LOG_NOTICE:
- return ANDROID_LOG_INFO;
- case LOG_WARN:
- return ANDROID_LOG_WARN;
- case LOG_ERR:
- return ANDROID_LOG_ERROR;
- default:
- // LCOV_EXCL_START
- raw_assert(0);
- return 0;
- // LCOV_EXCL_STOP
- }
-}
-#endif /* defined(HAVE_ANDROID_LOG_H) */
-
/** A mutex to guard changes to logfiles and logging. */
static tor_mutex_t log_mutex;
/** True iff we have initialized log_mutex */
@@ -475,13 +442,13 @@ pending_log_message_free_(pending_log_message_t *msg)
}
/** Helper function: returns true iff the log file, given in <b>lf</b>, is
- * handled externally via the system log API, the Android logging API, or is an
+ * handled externally via the system log API, or is an
* external callback function. */
static inline int
logfile_is_external(const logfile_t *lf)
{
raw_assert(lf);
- return lf->is_syslog || lf->is_android || lf->callback;
+ return lf->is_syslog || lf->callback;
}
/** Return true iff <b>lf</b> would like to receive a message with the
@@ -537,11 +504,6 @@ logfile_deliver(logfile_t *lf, const char *buf, size_t msg_len,
syslog(severity, "%s", msg_after_prefix);
#endif /* defined(MAXLINE) */
#endif /* defined(HAVE_SYSLOG_H) */
- } else if (lf->is_android) {
-#ifdef HAVE_ANDROID_LOG_H
- int priority = severity_to_android_log_priority(severity);
- __android_log_write(priority, lf->android_tag, msg_after_prefix);
-#endif // HAVE_ANDROID_LOG_H.
} else if (lf->callback) {
if (domain & LD_NOCB) {
if (!*callbacks_deferred && pending_cb_messages) {
@@ -677,7 +639,7 @@ tor_log_update_sigsafe_err_fds(void)
n_fds = 1;
for (lf = logfiles; lf; lf = lf->next) {
- /* Don't try callback to the control port, syslogs, android logs, or any
+ /* Don't try callback to the control port, syslogs, or any
* other non-file descriptor log: We can't call arbitrary functions from a
* signal handler.
*/
@@ -775,7 +737,6 @@ log_free_(logfile_t *victim)
return;
tor_free(victim->severities);
tor_free(victim->filename);
- tor_free(victim->android_tag);
tor_free(victim);
}
@@ -823,7 +784,7 @@ logs_free_all(void)
/** Flush the signal-safe log files.
*
- * This function is safe to call from a signal handler. It is currenly called
+ * This function is safe to call from a signal handler. It is currently called
* by the BUG() macros, when terminating the process on an abnormal condition.
*/
void
@@ -1247,39 +1208,6 @@ add_syslog_log(const log_severity_list_t *severity,
}
#endif /* defined(HAVE_SYSLOG_H) */
-#ifdef HAVE_ANDROID_LOG_H
-/**
- * Add a log handler to send messages to the Android platform log facility.
- */
-int
-add_android_log(const log_severity_list_t *severity,
- const char *android_tag)
-{
- logfile_t *lf = NULL;
-
- lf = tor_malloc_zero(sizeof(logfile_t));
- lf->fd = -1;
- lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
- lf->filename = tor_strdup("<android>");
- lf->is_android = 1;
-
- if (android_tag == NULL)
- lf->android_tag = tor_strdup("Tor");
- else {
- char buf[256];
- tor_snprintf(buf, sizeof(buf), "Tor-%s", android_tag);
- lf->android_tag = tor_strdup(buf);
- }
-
- LOCK_LOGS();
- lf->next = logfiles;
- logfiles = lf;
- log_global_min_severity_ = get_min_log_level();
- UNLOCK_LOGS();
- return 0;
-}
-#endif /* defined(HAVE_ANDROID_LOG_H) */
-
/** If <b>level</b> is a valid log severity, return the corresponding
* numeric value. Otherwise, return -1. */
int
@@ -1308,7 +1236,7 @@ log_level_to_string(int level)
/** NULL-terminated array of names for log domains such that domain_list[dom]
* is a description of <b>dom</b>.
*
- * Remember to update doc/tor.1.txt if you modify this list.
+ * Remember to update doc/man/tor.1.txt if you modify this list.
* */
static const char *domain_list[] = {
"GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM",
@@ -1457,8 +1385,7 @@ parse_log_severity_config(const char **cfg_ptr,
if (!strcasecmpstart(cfg, "file") ||
!strcasecmpstart(cfg, "stderr") ||
!strcasecmpstart(cfg, "stdout") ||
- !strcasecmpstart(cfg, "syslog") ||
- !strcasecmpstart(cfg, "android")) {
+ !strcasecmpstart(cfg, "syslog")) {
goto done;
}
if (got_an_unqualified_range > 1)
diff --git a/src/lib/log/log.h b/src/lib/log/log.h
index aafbf9be2f..fb8a5a28a6 100644
--- a/src/lib/log/log.h
+++ b/src/lib/log/log.h
@@ -175,10 +175,6 @@ MOCK_DECL(int, add_file_log,(const log_severity_list_t *severity,
int add_syslog_log(const log_severity_list_t *severity,
const char* syslog_identity_tag);
#endif // HAVE_SYSLOG_H.
-#ifdef HAVE_ANDROID_LOG_H
-int add_android_log(const log_severity_list_t *severity,
- const char *android_identity_tag);
-#endif // HAVE_ANDROID_LOG_H.
int add_callback_log(const log_severity_list_t *severity, log_callback cb);
typedef void (*pending_callback_callback)(void);
void logs_set_pending_callback_callback(pending_callback_callback cb);
diff --git a/src/lib/log/ratelim.c b/src/lib/log/ratelim.c
index ac401fb398..8dfaee3384 100644
--- a/src/lib/log/ratelim.c
+++ b/src/lib/log/ratelim.c
@@ -11,6 +11,7 @@
#include "lib/log/ratelim.h"
#include "lib/malloc/malloc.h"
#include "lib/string/printf.h"
+#include "lib/intmath/muldiv.h"
/** If the rate-limiter <b>lim</b> is ready at <b>now</b>, return the number
* of calls to rate_limit_is_ready (including this one!) since the last time
@@ -42,19 +43,24 @@ rate_limit_log(ratelim_t *lim, time_t now)
{
int n;
if ((n = rate_limit_is_ready(lim, now))) {
+ time_t started_limiting = lim->started_limiting;
+ lim->started_limiting = 0;
if (n == 1) {
return tor_strdup("");
} else {
char *cp=NULL;
const char *opt_over = (n >= RATELIM_TOOMANY) ? "over " : "";
- /* XXXX this is not exactly correct: the messages could have occurred
- * any time between the old value of lim->allowed and now. */
+ unsigned difference = (unsigned)(now - started_limiting);
+ difference = round_to_next_multiple_of(difference, 60);
tor_asprintf(&cp,
" [%s%d similar message(s) suppressed in last %d seconds]",
- opt_over, n-1, lim->rate);
+ opt_over, n-1, (int)difference);
return cp;
}
} else {
+ if (lim->started_limiting == 0) {
+ lim->started_limiting = now;
+ }
return NULL;
}
}
diff --git a/src/lib/log/ratelim.h b/src/lib/log/ratelim.h
index e9b55d40dc..9e202028cf 100644
--- a/src/lib/log/ratelim.h
+++ b/src/lib/log/ratelim.h
@@ -40,13 +40,19 @@
</pre>
*/
typedef struct ratelim_t {
+ /** How many seconds must elapse between log messages? */
int rate;
+ /** When did this limiter last allow a message to appear? */
time_t last_allowed;
+ /** When did this limiter start suppressing messages? */
+ time_t started_limiting;
+ /** How many messages has this limiter suppressed since it last allowed
+ * one to appear? */
int n_calls_since_last_time;
} ratelim_t;
#ifndef COCCI
-#define RATELIM_INIT(r) { (r), 0, 0 }
+#define RATELIM_INIT(r) { (r), 0, 0, 0 }
#endif
#define RATELIM_TOOMANY (16*1000*1000)
diff --git a/src/lib/math/prob_distr.c b/src/lib/math/prob_distr.c
index 31d485120e..b322b4db5c 100644
--- a/src/lib/math/prob_distr.c
+++ b/src/lib/math/prob_distr.c
@@ -891,7 +891,7 @@ icdf_genpareto(double p, double mu, double sigma, double xi)
/**
* Compute the inverse of the SF of the GeneralizedPareto(mu, sigma,
- * xi) distribution. Ill-conditioned for p near 1; conditon number is
+ * xi) distribution. Ill-conditioned for p near 1; condition number is
*
* -xi/(1 - p^{-xi})
*/
@@ -1000,7 +1000,7 @@ sample_uniform_interval(double p0, double a, double b)
* since if we treat subnormals as having an implicit
* zero bit before the `binary' point, their exponents
* are all the same. There is at most one carry/borrow
- * bit, which can always be acommodated either in a
+ * bit, which can always be accommodated either in a
* subnormal, or, at largest, in the implicit one bit
* of a normal.
*
diff --git a/src/lib/meminfo/.may_include b/src/lib/meminfo/.may_include
index 9e4d25fd6a..12fe36d134 100644
--- a/src/lib/meminfo/.may_include
+++ b/src/lib/meminfo/.may_include
@@ -5,4 +5,5 @@ lib/fs/*.h
lib/log/*.h
lib/malloc/*.h
lib/meminfo/*.h
+lib/string/*.h
lib/testsupport/*.h
diff --git a/src/lib/meminfo/meminfo.c b/src/lib/meminfo/meminfo.c
index b7d991e410..77da579f99 100644
--- a/src/lib/meminfo/meminfo.c
+++ b/src/lib/meminfo/meminfo.c
@@ -17,6 +17,7 @@
#include "lib/fs/files.h"
#include "lib/log/log.h"
#include "lib/malloc/malloc.h"
+#include "lib/string/util_string.h"
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
@@ -65,7 +66,7 @@ get_total_system_memory_impl(void)
s = read_file_to_str_until_eof(fd, 65536, &file_size);
if (!s)
goto err;
- cp = strstr(s, "MemTotal:");
+ cp = find_str_at_start_of_line(s, "MemTotal:");
if (!cp)
goto err;
/* Use the system sscanf so that space will match a wider number of space */
diff --git a/src/lib/metrics/include.am b/src/lib/metrics/include.am
new file mode 100644
index 0000000000..62c289446e
--- /dev/null
+++ b/src/lib/metrics/include.am
@@ -0,0 +1,25 @@
+
+noinst_LIBRARIES += src/lib/libtor-metrics.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-metrics-testing.a
+endif
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+src_lib_libtor_metrics_a_SOURCES = \
+ src/lib/metrics/metrics_store.c \
+ src/lib/metrics/metrics_store_entry.c \
+ src/lib/metrics/metrics_common.c \
+ src/lib/metrics/prometheus.c
+
+src_lib_libtor_metrics_testing_a_SOURCES = \
+ $(src_lib_libtor_metrics_a_SOURCES)
+src_lib_libtor_metrics_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_metrics_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/lib/metrics/metrics_store.h \
+ src/lib/metrics/metrics_store_entry.h \
+ src/lib/metrics/metrics_common.h \
+ src/lib/metrics/prometheus.h
diff --git a/src/lib/metrics/lib_metrics.md b/src/lib/metrics/lib_metrics.md
new file mode 100644
index 0000000000..e58680e237
--- /dev/null
+++ b/src/lib/metrics/lib_metrics.md
@@ -0,0 +1,12 @@
+@dir /lib/metrics
+@brief lib/metrics: Metrics collection API
+
+This module is used for adding "metrics" support to Tor.
+
+Metrics are a collection of counters that are defined per-subsystem and
+accessed through the MetricsPort. Each subsystem is responsible for populating
+metrics store(s) and providing access to them through the `.get_metrics()`
+call located in the `subsys_fns_t` object.
+
+These metrics are meant to be extremely lightweight and thus can be accessed
+without too much CPU cost.
diff --git a/src/lib/metrics/metrics_common.c b/src/lib/metrics/metrics_common.c
new file mode 100644
index 0000000000..5941a4d892
--- /dev/null
+++ b/src/lib/metrics/metrics_common.c
@@ -0,0 +1,29 @@
+/* 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file metrics_common.c
+ * @brief Common code for the metrics library
+ **/
+
+#include <stddef.h>
+
+#include "orconfig.h"
+
+#include "lib/log/util_bug.h"
+
+#include "lib/metrics/metrics_common.h"
+
+/** Return string representation of a metric type. */
+const char *
+metrics_type_to_str(const metrics_type_t type)
+{
+ switch (type) {
+ case METRICS_TYPE_COUNTER:
+ return "counter";
+ case METRICS_TYPE_GAUGE:
+ return "gauge";
+ default:
+ tor_assert_unreached();
+ }
+}
diff --git a/src/lib/metrics/metrics_common.h b/src/lib/metrics/metrics_common.h
new file mode 100644
index 0000000000..c684a3ec42
--- /dev/null
+++ b/src/lib/metrics/metrics_common.h
@@ -0,0 +1,45 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file metrics_common.h
+ * @brief Header for lib/metrics/metrics_common.c
+ **/
+
+#ifndef TOR_LIB_METRICS_METRICS_COMMON_H
+#define TOR_LIB_METRICS_METRICS_COMMON_H
+
+#include "lib/cc/torint.h"
+
+/** Helper macro that must be used to construct the right namespaced metrics
+ * name. A name is a string so stringify the result. */
+#define METRICS_STR(val) #val
+#define METRICS_NAME(name) METRICS_STR(tor_ ## name)
+
+/** Format output type. */
+typedef enum {
+ /** Prometheus data output format. */
+ METRICS_FORMAT_PROMETHEUS = 1,
+} metrics_format_t;
+
+/** Metric type. */
+typedef enum {
+ /* Increment only. */
+ METRICS_TYPE_COUNTER,
+ /* Can go up or down. */
+ METRICS_TYPE_GAUGE,
+} metrics_type_t;
+
+/** Metric counter object (METRICS_TYPE_COUNTER). */
+typedef struct metrics_counter_t {
+ uint64_t value;
+} metrics_counter_t;
+
+/** Metric gauge object (METRICS_TYPE_GAUGE). */
+typedef struct metrics_gauge_t {
+ int64_t value;
+} metrics_gauge_t;
+
+const char *metrics_type_to_str(const metrics_type_t type);
+
+#endif /* !defined(TOR_LIB_METRICS_METRICS_COMMON_H) */
diff --git a/src/lib/metrics/metrics_store.c b/src/lib/metrics/metrics_store.c
new file mode 100644
index 0000000000..57847cc37c
--- /dev/null
+++ b/src/lib/metrics/metrics_store.c
@@ -0,0 +1,140 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file metrics_store.c
+ * @brief Metrics interface to store them based on specific store type and get
+ * their MetricsPort output.
+ **/
+
+#define METRICS_STORE_ENTRY_PRIVATE
+
+#include "orconfig.h"
+
+#include "lib/container/map.h"
+#include "lib/log/util_bug.h"
+#include "lib/malloc/malloc.h"
+
+#include "lib/metrics/metrics_store.h"
+#include "lib/metrics/metrics_store_entry.h"
+
+/* Format Drivers. */
+#include "lib/metrics/prometheus.h"
+
+/** A metric store which contains a map of entries. */
+struct metrics_store_t {
+ /** Indexed by metrics entry name. An entry is a smartlist_t of one or more
+ * metrics_store_entry_t allowing for multiple metrics of the same name.
+ *
+ * The reason we allow multiple entries is because there are cases where one
+ * metrics can be used twice by the same entity but with different labels.
+ * One example is an onion service with multiple ports, the port specific
+ * metrics will have a port value as a label. */
+ strmap_t *entries;
+};
+
+/** Function pointer to the format function of a specific driver. */
+typedef void (fmt_driver_fn_t)(const metrics_store_entry_t *, buf_t *);
+
+/** Helper: Free a single entry in a metrics_store_t taking a void pointer
+ * parameter. */
+static void
+metrics_store_free_void(void *p)
+{
+ smartlist_t *list = p;
+ SMARTLIST_FOREACH(list, metrics_store_entry_t *, entry,
+ metrics_store_entry_free(entry));
+ smartlist_free(list);
+}
+
+/** Put the given store output in the buffer data and use the format function
+ * given in fmt to get it for each entry. */
+static void
+get_output(const metrics_store_t *store, buf_t *data, fmt_driver_fn_t fmt)
+{
+ tor_assert(store);
+ tor_assert(data);
+ tor_assert(fmt);
+
+ STRMAP_FOREACH(store->entries, key, const smartlist_t *, entries) {
+ SMARTLIST_FOREACH_BEGIN(entries, const metrics_store_entry_t *, entry) {
+ fmt(entry, data);
+ } SMARTLIST_FOREACH_END(entry);
+ } STRMAP_FOREACH_END;
+}
+
+/** Return a newly allocated and initialized store of the given type. */
+metrics_store_t *
+metrics_store_new(void)
+{
+ metrics_store_t *store = tor_malloc_zero(sizeof(*store));
+
+ store->entries = strmap_new();
+
+ return store;
+}
+
+/** Free the given store including all its entries. */
+void
+metrics_store_free_(metrics_store_t *store)
+{
+ if (store == NULL) {
+ return;
+ }
+
+ strmap_free(store->entries, metrics_store_free_void);
+ tor_free(store);
+}
+
+/** Find all metrics entry in the given store identified by name. If not found,
+ * NULL is returned. */
+smartlist_t *
+metrics_store_get_all(const metrics_store_t *store, const char *name)
+{
+ tor_assert(store);
+ tor_assert(name);
+
+ return strmap_get(store->entries, name);
+}
+
+/** Add a new metrics entry to the given store and type. The name MUST be the
+ * unique identifier. The help string can be omitted. */
+metrics_store_entry_t *
+metrics_store_add(metrics_store_t *store, metrics_type_t type,
+ const char *name, const char *help)
+{
+ smartlist_t *entries;
+ metrics_store_entry_t *entry;
+
+ tor_assert(store);
+ tor_assert(name);
+
+ entries = metrics_store_get_all(store, name);
+ if (!entries) {
+ entries = smartlist_new();
+ strmap_set(store->entries, name, entries);
+ }
+ entry = metrics_store_entry_new(type, name, help);
+ smartlist_add(entries, entry);
+
+ return entry;
+}
+
+/** Set the output of the given store of the format fmt into the given buffer
+ * data. */
+void
+metrics_store_get_output(const metrics_format_t fmt,
+ const metrics_store_t *store, buf_t *data)
+{
+ tor_assert(store);
+
+ switch (fmt) {
+ case METRICS_FORMAT_PROMETHEUS:
+ get_output(store, data, prometheus_format_store_entry);
+ break;
+ default:
+ // LCOV_EXCL_START
+ tor_assert_unreached();
+ // LCOV_EXCL_STOP
+ }
+}
diff --git a/src/lib/metrics/metrics_store.h b/src/lib/metrics/metrics_store.h
new file mode 100644
index 0000000000..9640a5e016
--- /dev/null
+++ b/src/lib/metrics/metrics_store.h
@@ -0,0 +1,42 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file metrics_store.h
+ * @brief Header for lib/metrics/metrics_store.c
+ **/
+
+#ifndef TOR_LIB_METRICS_METRICS_STORE_H
+#define TOR_LIB_METRICS_METRICS_STORE_H
+
+#include "lib/buf/buffers.h"
+#include "lib/container/smartlist.h"
+
+#include "lib/metrics/metrics_common.h"
+#include "lib/metrics/metrics_store_entry.h"
+
+/* Stub. */
+typedef struct metrics_store_t metrics_store_t;
+
+/* Allocators. */
+void metrics_store_free_(metrics_store_t *store);
+#define metrics_store_free(store) \
+ FREE_AND_NULL(metrics_store_t, metrics_store_free_, (store))
+metrics_store_t *metrics_store_new(void);
+
+/* Modifiers. */
+metrics_store_entry_t *metrics_store_add(metrics_store_t *store,
+ metrics_type_t type,
+ const char *name, const char *help);
+
+/* Accessors. */
+smartlist_t *metrics_store_get_all(const metrics_store_t *store,
+ const char *name);
+void metrics_store_get_output(const metrics_format_t fmt,
+ const metrics_store_t *store, buf_t *data);
+
+#ifdef METRICS_METRICS_STORE_PRIVATE
+
+#endif /* METRICS_METRICS_STORE_PRIVATE. */
+
+#endif /* !defined(TOR_LIB_METRICS_METRICS_STORE_H) */
diff --git a/src/lib/metrics/metrics_store_entry.c b/src/lib/metrics/metrics_store_entry.c
new file mode 100644
index 0000000000..44ebb5cb84
--- /dev/null
+++ b/src/lib/metrics/metrics_store_entry.c
@@ -0,0 +1,129 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file metrics_store_entry.c
+ * @brief Metrics store entry which contains the gathered data.
+ **/
+
+#define METRICS_STORE_ENTRY_PRIVATE
+
+#include <string.h>
+
+#include "orconfig.h"
+
+#include "lib/container/smartlist.h"
+#include "lib/log/util_bug.h"
+#include "lib/malloc/malloc.h"
+
+#include "lib/metrics/metrics_store_entry.h"
+
+/*
+ * Public API.
+ */
+
+/** Return newly allocated store entry of type COUNTER. */
+metrics_store_entry_t *
+metrics_store_entry_new(const metrics_type_t type, const char *name,
+ const char *help)
+{
+ metrics_store_entry_t *entry = tor_malloc_zero(sizeof(*entry));
+
+ tor_assert(name);
+
+ entry->type = type;
+ entry->name = tor_strdup(name);
+ entry->labels = smartlist_new();
+ if (help) {
+ entry->help = tor_strdup(help);
+ }
+
+ return entry;
+}
+
+/** Free a store entry. */
+void
+metrics_store_entry_free_(metrics_store_entry_t *entry)
+{
+ if (!entry) {
+ return;
+ }
+ SMARTLIST_FOREACH(entry->labels, char *, l, tor_free(l));
+ smartlist_free(entry->labels);
+ tor_free(entry->name);
+ tor_free(entry->help);
+ tor_free(entry);
+}
+
+/** Update a store entry with value. */
+void
+metrics_store_entry_update(metrics_store_entry_t *entry, const int64_t value)
+{
+ tor_assert(entry);
+
+ switch (entry->type) {
+ case METRICS_TYPE_COUNTER:
+ /* Counter can ONLY be positive. */
+ if (BUG(value < 0)) {
+ return;
+ }
+ entry->u.counter.value += value;
+ break;
+ case METRICS_TYPE_GAUGE:
+ /* Gauge can increment or decrement. And can be positive or negative. */
+ entry->u.gauge.value += value;
+ break;
+ }
+}
+
+/** Reset a store entry that is set its metric data to 0. */
+void
+metrics_store_entry_reset(metrics_store_entry_t *entry)
+{
+ tor_assert(entry);
+ /* Everything back to 0. */
+ memset(&entry->u, 0, sizeof(entry->u));
+}
+
+/** Return store entry value. */
+int64_t
+metrics_store_entry_get_value(const metrics_store_entry_t *entry)
+{
+ tor_assert(entry);
+
+ switch (entry->type) {
+ case METRICS_TYPE_COUNTER:
+ if (entry->u.counter.value > INT64_MAX) {
+ return INT64_MAX;
+ }
+ return entry->u.counter.value;
+ case METRICS_TYPE_GAUGE:
+ return entry->u.gauge.value;
+ }
+
+ // LCOV_EXCL_START
+ tor_assert_unreached();
+ // LCOV_EXCL_STOP
+}
+
+/** Add a label into the given entry.*/
+void
+metrics_store_entry_add_label(metrics_store_entry_t *entry,
+ const char *label)
+{
+ tor_assert(entry);
+ tor_assert(label);
+
+ smartlist_add(entry->labels, tor_strdup(label));
+}
+
+/** Return true iff the given entry has the given label. */
+bool
+metrics_store_entry_has_label(const metrics_store_entry_t *entry,
+ const char *label)
+{
+ tor_assert(entry);
+ tor_assert(label);
+
+ return smartlist_contains_string(entry->labels, label);
+}
diff --git a/src/lib/metrics/metrics_store_entry.h b/src/lib/metrics/metrics_store_entry.h
new file mode 100644
index 0000000000..8e8a8f3917
--- /dev/null
+++ b/src/lib/metrics/metrics_store_entry.h
@@ -0,0 +1,68 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file metrics_store_entry.h
+ * @brief Header for lib/metrics/metrics_store_entry.c
+ **/
+
+#ifndef TOR_LIB_METRICS_METRICS_STORE_ENTRY_H
+#define TOR_LIB_METRICS_METRICS_STORE_ENTRY_H
+
+#include "lib/cc/torint.h"
+
+#include "lib/metrics/metrics_common.h"
+
+#ifdef METRICS_STORE_ENTRY_PRIVATE
+
+/** Metrics store entry. They reside in a metrics_store_t object and are
+ * opaque to the outside world. */
+struct metrics_store_entry_t {
+ /** Type of entry. */
+ metrics_type_t type;
+
+ /** Name. */
+ char *name;
+
+ /** Help comment string. */
+ char *help;
+
+ /** Labels attached to that entry. If NULL, no labels.
+ *
+ * Labels are used to add extra context to a metrics. For example, a label
+ * could be an onion address so the metrics can be differentiate. */
+ smartlist_t *labels;
+
+ /* Actual data. */
+ union {
+ metrics_counter_t counter;
+ metrics_gauge_t gauge;
+ } u;
+};
+
+#endif /* METRICS_STORE_ENTRY_PRIVATE */
+
+typedef struct metrics_store_entry_t metrics_store_entry_t;
+
+/* Allocators. */
+metrics_store_entry_t *metrics_store_entry_new(const metrics_type_t type,
+ const char *name,
+ const char *help);
+
+void metrics_store_entry_free_(metrics_store_entry_t *entry);
+#define metrics_store_entry_free(entry) \
+ FREE_AND_NULL(metrics_store_entry_t, metrics_store_entry_free_, (entry));
+
+/* Accessors. */
+int64_t metrics_store_entry_get_value(const metrics_store_entry_t *entry);
+bool metrics_store_entry_has_label(const metrics_store_entry_t *entry,
+ const char *label);
+
+/* Modifiers. */
+void metrics_store_entry_add_label(metrics_store_entry_t *entry,
+ const char *label);
+void metrics_store_entry_reset(metrics_store_entry_t *entry);
+void metrics_store_entry_update(metrics_store_entry_t *entry,
+ const int64_t value);
+
+#endif /* !defined(TOR_LIB_METRICS_METRICS_STORE_ENTRY_H) */
diff --git a/src/lib/metrics/prometheus.c b/src/lib/metrics/prometheus.c
new file mode 100644
index 0000000000..c2b54e436f
--- /dev/null
+++ b/src/lib/metrics/prometheus.c
@@ -0,0 +1,56 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file prometheus.c
+ * @brief Metrics format driver for Prometheus data model.
+ **/
+
+#define METRICS_STORE_ENTRY_PRIVATE
+
+#include "orconfig.h"
+
+#include "lib/container/smartlist.h"
+#include "lib/log/util_bug.h"
+#include "lib/malloc/malloc.h"
+#include "lib/string/printf.h"
+
+#include "lib/metrics/prometheus.h"
+
+/** Return a static buffer containing all the labels properly formatted
+ * for the output as a string.
+ *
+ * Subsequent calls to this invalidates the previous result. */
+static const char *
+format_labels(smartlist_t *labels)
+{
+ static char buf[1024];
+ char *line = NULL;
+
+ if (smartlist_len(labels) == 0) {
+ buf[0] = '\0';
+ goto end;
+ }
+
+ line = smartlist_join_strings(labels, ",", 0, NULL);
+ tor_snprintf(buf, sizeof(buf), "{%s}", line);
+
+ end:
+ tor_free(line);
+ return buf;
+}
+
+/** Format the given entry in to the buffer data. */
+void
+prometheus_format_store_entry(const metrics_store_entry_t *entry, buf_t *data)
+{
+ tor_assert(entry);
+ tor_assert(data);
+
+ buf_add_printf(data, "# HELP %s %s\n", entry->name, entry->help);
+ buf_add_printf(data, "# TYPE %s %s\n", entry->name,
+ metrics_type_to_str(entry->type));
+ buf_add_printf(data, "%s%s %" PRIi64 "\n", entry->name,
+ format_labels(entry->labels),
+ metrics_store_entry_get_value(entry));
+}
diff --git a/src/lib/metrics/prometheus.h b/src/lib/metrics/prometheus.h
new file mode 100644
index 0000000000..eea26e8ac4
--- /dev/null
+++ b/src/lib/metrics/prometheus.h
@@ -0,0 +1,18 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file prometheus.h
+ * @brief Header for feature/metrics/prometheus.c
+ **/
+
+#ifndef TOR_LIB_METRICS_PROMETHEUS_H
+#define TOR_LIB_METRICS_PROMETHEUS_H
+
+#include "lib/buf/buffers.h"
+#include "lib/metrics/metrics_store_entry.h"
+
+void prometheus_format_store_entry(const metrics_store_entry_t *entry,
+ buf_t *data);
+
+#endif /* !defined(TOR_LIB_METRICS_PROMETHEUS_H) */
diff --git a/src/lib/net/address.c b/src/lib/net/address.c
index 6d46f9b955..21794fb4fc 100644
--- a/src/lib/net/address.c
+++ b/src/lib/net/address.c
@@ -764,6 +764,15 @@ tor_addr_is_v4(const tor_addr_t *addr)
return 0; /* Not IPv4 - unknown family or a full-blood IPv6 address */
}
+/** Determine whether an address <b>addr</b> is an IPv6 (AF_INET6). Return
+ * true if so else false. */
+int
+tor_addr_is_v6(const tor_addr_t *addr)
+{
+ tor_assert(addr);
+ return (tor_addr_family(addr) == AF_INET6);
+}
+
/** Determine whether an address <b>addr</b> is null, either all zeroes or
* belonging to family AF_UNSPEC.
*/
@@ -1217,20 +1226,28 @@ fmt_addr32(uint32_t addr)
return buf;
}
-/** Return a string representing the family of <b>addr</b>.
+/** Like fmt_addrport(), but takes <b>addr</b> as a host-order IPv4
+ * addresses. Also not thread-safe, also clobbers its return buffer on
+ * repeated calls. */
+const char *
+fmt_addr32_port(uint32_t addr, uint16_t port)
+{
+ static char buf[INET_NTOA_BUF_LEN + 6];
+ snprintf(buf, sizeof(buf), "%s:%u", fmt_addr32(addr), port);
+ return buf;
+}
+
+/** Return a string representing <b>family</b>.
*
* This string is a string constant, and must not be freed.
* This function is thread-safe.
*/
const char *
-fmt_addr_family(const tor_addr_t *addr)
+fmt_af_family(sa_family_t family)
{
static int default_bug_once = 0;
- IF_BUG_ONCE(!addr)
- return "NULL pointer";
-
- switch (tor_addr_family(addr)) {
+ switch (family) {
case AF_INET6:
return "IPv6";
case AF_INET:
@@ -1242,7 +1259,7 @@ fmt_addr_family(const tor_addr_t *addr)
default:
if (!default_bug_once) {
log_warn(LD_BUG, "Called with unknown address family %d",
- (int)tor_addr_family(addr));
+ (int)family);
default_bug_once = 1;
}
return "unknown";
@@ -1250,6 +1267,20 @@ fmt_addr_family(const tor_addr_t *addr)
//return "(unreachable code)";
}
+/** Return a string representing the family of <b>addr</b>.
+ *
+ * This string is a string constant, and must not be freed.
+ * This function is thread-safe.
+ */
+const char *
+fmt_addr_family(const tor_addr_t *addr)
+{
+ IF_BUG_ONCE(!addr)
+ return "NULL pointer";
+
+ return fmt_af_family(tor_addr_family(addr));
+}
+
/** Convert the string in <b>src</b> to a tor_addr_t <b>addr</b>. The string
* may be an IPv4 address, or an IPv6 address surrounded by square brackets.
*
@@ -1700,8 +1731,8 @@ get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr))
/* Get a list of public or internal IPs in arbitrary order */
addrs = get_interface_address6_list(severity, family, 1);
- /* Find the first non-internal address, or the last internal address
- * Ideally, we want the default route, see #12377 for details */
+ /* Find the first non-internal address, or the last internal address.
+ * Ideally, we want the default route; see #12377 for details. */
SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a) {
tor_addr_copy(addr, a);
const bool is_internal = tor_addr_is_internal(a, 0);
@@ -2083,7 +2114,19 @@ tor_addr_port_eq(const tor_addr_port_t *a,
return tor_addr_eq(&a->addr, &b->addr) && a->port == b->port;
}
-/** Return true if <b>string</b> represents a valid IPv4 adddress in
+/**
+ * Copy a tor_addr_port_t from @a source to @a dest.
+ **/
+void
+tor_addr_port_copy(tor_addr_port_t *dest,
+ const tor_addr_port_t *source)
+{
+ tor_assert(dest);
+ tor_assert(source);
+ memcpy(dest, source, sizeof(tor_addr_port_t));
+}
+
+/** Return true if <b>string</b> represents a valid IPv4 address in
* 'a.b.c.d' form.
*/
int
diff --git a/src/lib/net/address.h b/src/lib/net/address.h
index e5016ee4fe..4c79db69d2 100644
--- a/src/lib/net/address.h
+++ b/src/lib/net/address.h
@@ -95,6 +95,7 @@ static inline uint32_t tor_addr_to_ipv4n(const tor_addr_t *a);
static inline uint32_t tor_addr_to_ipv4h(const tor_addr_t *a);
static inline uint32_t tor_addr_to_mapped_ipv4h(const tor_addr_t *a);
static inline sa_family_t tor_addr_family(const tor_addr_t *a);
+static inline bool tor_addr_is_unspec(const tor_addr_t *a);
static inline const struct in_addr *tor_addr_to_in(const tor_addr_t *a);
static inline int tor_addr_eq_ipv4h(const tor_addr_t *a, uint32_t u);
@@ -188,6 +189,15 @@ tor_addr_family(const tor_addr_t *a)
return a->family;
}
+/**
+ * Return true if the address @a is in the UNSPEC family.
+ **/
+static inline bool
+tor_addr_is_unspec(const tor_addr_t *a)
+{
+ return a->family == AF_UNSPEC;
+}
+
/** 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 *
@@ -214,7 +224,7 @@ tor_addr_eq_ipv4h(const tor_addr_t *a, uint32_t u)
#define TOR_ADDR_BUF_LEN 48
/** Length of a buffer containing an IP address along with a port number and
- * a seperating colon.
+ * a separating colon.
*
* This allows enough space for
* "[ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255]:12345",
@@ -236,6 +246,8 @@ const char *fmt_addr_impl(const tor_addr_t *addr, int decorate);
const char *fmt_addrport(const tor_addr_t *addr, uint16_t port);
#define fmt_addrport_ap(ap) fmt_addrport(&(ap)->addr, (ap)->port)
const char *fmt_addr32(uint32_t addr);
+const char *fmt_addr32_port(uint32_t addr, uint16_t port);
+const char *fmt_af_family(sa_family_t family);
const char *fmt_addr_family(const tor_addr_t *addr);
MOCK_DECL(int,get_interface_address6,(int severity, sa_family_t family,
@@ -272,6 +284,7 @@ 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_v6(const tor_addr_t *addr);
int tor_addr_is_internal_(const tor_addr_t *ip, int for_listening,
const char *filename, int lineno);
#define tor_addr_is_internal(addr, for_listening) \
@@ -381,6 +394,7 @@ get_interface_address_list(int severity, int include_internal)
tor_addr_port_t *tor_addr_port_new(const tor_addr_t *addr, uint16_t port);
int tor_addr_port_eq(const tor_addr_port_t *a,
const tor_addr_port_t *b);
+void tor_addr_port_copy(tor_addr_port_t *dest, const tor_addr_port_t *source);
int string_is_valid_dest(const char *string);
int string_is_valid_nonrfc_hostname(const char *string);
diff --git a/src/lib/net/buffers_net.c b/src/lib/net/buffers_net.c
index 4dbf491e1a..4a0eb3bf16 100644
--- a/src/lib/net/buffers_net.c
+++ b/src/lib/net/buffers_net.c
@@ -137,13 +137,12 @@ buf_read_from_fd(buf_t *buf, int fd, size_t at_most,
}
/** Helper for buf_flush_to_socket(): try to write <b>sz</b> bytes from chunk
- * <b>chunk</b> of buffer <b>buf</b> onto file descriptor <b>fd</b>. On
- * success, deduct the bytes written from *<b>buf_flushlen</b>. Return the
- * number of bytes written on success, 0 on blocking, -1 on failure.
+ * <b>chunk</b> of buffer <b>buf</b> onto file descriptor <b>fd</b>. Return
+ * the number of bytes written on success, 0 on blocking, -1 on failure.
*/
static inline int
flush_chunk(tor_socket_t fd, buf_t *buf, chunk_t *chunk, size_t sz,
- size_t *buf_flushlen, bool is_socket)
+ bool is_socket)
{
ssize_t write_result;
@@ -168,7 +167,6 @@ flush_chunk(tor_socket_t fd, buf_t *buf, chunk_t *chunk, size_t sz,
log_debug(LD_NET,"write() would block, returning.");
return 0;
} else {
- *buf_flushlen -= write_result;
buf_drain(buf, write_result);
tor_assert(write_result <= BUF_MAX_LEN);
return (int)write_result;
@@ -176,27 +174,22 @@ flush_chunk(tor_socket_t fd, buf_t *buf, chunk_t *chunk, size_t sz,
}
/** Write data from <b>buf</b> to the file descriptor <b>fd</b>. Write at most
- * <b>sz</b> bytes, decrement *<b>buf_flushlen</b> by
- * the number of bytes actually written, and remove the written bytes
+ * <b>sz</b> bytes, and remove the written bytes
* from the buffer. Return the number of bytes written on success,
* -1 on failure. Return 0 if write() would block.
*/
static int
buf_flush_to_fd(buf_t *buf, int fd, size_t sz,
- size_t *buf_flushlen, bool is_socket)
+ bool is_socket)
{
/* XXXX It's stupid to overload the return values for these functions:
* "error status" and "number of bytes flushed" are not mutually exclusive.
*/
int r;
size_t flushed = 0;
- tor_assert(buf_flushlen);
tor_assert(SOCKET_OK(fd));
- if (BUG(*buf_flushlen > buf->datalen)) {
- *buf_flushlen = buf->datalen;
- }
- if (BUG(sz > *buf_flushlen)) {
- sz = *buf_flushlen;
+ if (BUG(sz > buf->datalen)) {
+ sz = buf->datalen;
}
check();
@@ -208,7 +201,7 @@ buf_flush_to_fd(buf_t *buf, int fd, size_t sz,
else
flushlen0 = buf->head->datalen;
- r = flush_chunk(fd, buf, buf->head, flushlen0, buf_flushlen, is_socket);
+ r = flush_chunk(fd, buf, buf->head, flushlen0, is_socket);
check();
if (r < 0)
return r;
@@ -228,10 +221,9 @@ buf_flush_to_fd(buf_t *buf, int fd, size_t sz,
* -1 on failure. Return 0 if write() would block.
*/
int
-buf_flush_to_socket(buf_t *buf, tor_socket_t s, size_t sz,
- size_t *buf_flushlen)
+buf_flush_to_socket(buf_t *buf, tor_socket_t s, size_t sz)
{
- return buf_flush_to_fd(buf, s, sz, buf_flushlen, true);
+ return buf_flush_to_fd(buf, s, sz, true);
}
/** Read from socket <b>s</b>, writing onto end of <b>buf</b>. Read at most
@@ -254,10 +246,9 @@ buf_read_from_socket(buf_t *buf, tor_socket_t s, size_t at_most,
* -1 on failure. Return 0 if write() would block.
*/
int
-buf_flush_to_pipe(buf_t *buf, int fd, size_t sz,
- size_t *buf_flushlen)
+buf_flush_to_pipe(buf_t *buf, int fd, size_t sz)
{
- return buf_flush_to_fd(buf, fd, sz, buf_flushlen, false);
+ return buf_flush_to_fd(buf, fd, sz, false);
}
/** Read from pipe <b>fd</b>, writing onto end of <b>buf</b>. Read at most
diff --git a/src/lib/net/buffers_net.h b/src/lib/net/buffers_net.h
index a45c23a273..556575c3dc 100644
--- a/src/lib/net/buffers_net.h
+++ b/src/lib/net/buffers_net.h
@@ -21,14 +21,12 @@ int buf_read_from_socket(struct buf_t *buf, tor_socket_t s, size_t at_most,
int *reached_eof,
int *socket_error);
-int buf_flush_to_socket(struct buf_t *buf, tor_socket_t s, size_t sz,
- size_t *buf_flushlen);
+int buf_flush_to_socket(struct buf_t *buf, tor_socket_t s, size_t sz);
int buf_read_from_pipe(struct buf_t *buf, int fd, size_t at_most,
int *reached_eof,
int *socket_error);
-int buf_flush_to_pipe(struct buf_t *buf, int fd, size_t sz,
- size_t *buf_flushlen);
+int buf_flush_to_pipe(struct buf_t *buf, int fd, size_t sz);
#endif /* !defined(TOR_BUFFERS_NET_H) */
diff --git a/src/lib/osinfo/include.am b/src/lib/osinfo/include.am
index 84bd7feb00..df8c98500c 100644
--- a/src/lib/osinfo/include.am
+++ b/src/lib/osinfo/include.am
@@ -7,7 +7,8 @@ endif
# ADD_C_FILE: INSERT SOURCES HERE.
src_lib_libtor_osinfo_a_SOURCES = \
- src/lib/osinfo/uname.c
+ src/lib/osinfo/uname.c \
+ src/lib/osinfo/libc.c
src_lib_libtor_osinfo_testing_a_SOURCES = \
$(src_lib_libtor_osinfo_a_SOURCES)
@@ -16,4 +17,5 @@ src_lib_libtor_osinfo_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
# ADD_C_FILE: INSERT HEADERS HERE.
noinst_HEADERS += \
- src/lib/osinfo/uname.h
+ src/lib/osinfo/uname.h \
+ src/lib/osinfo/libc.h
diff --git a/src/lib/osinfo/libc.c b/src/lib/osinfo/libc.c
new file mode 100644
index 0000000000..32cbad0fa2
--- /dev/null
+++ b/src/lib/osinfo/libc.c
@@ -0,0 +1,66 @@
+/* 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 libc.c
+ * @brief Functions to get the name and version of the system libc.
+ **/
+
+#include "orconfig.h"
+#include "lib/osinfo/libc.h"
+#include <stdlib.h>
+
+#ifdef HAVE_GNU_LIBC_VERSION_H
+#include <gnu/libc-version.h>
+#endif
+
+#ifdef HAVE_GNU_LIBC_VERSION_H
+#ifdef HAVE_GNU_GET_LIBC_VERSION
+#define CHECK_LIBC_VERSION
+#endif
+#endif
+
+#define STR_IMPL(x) #x
+#define STR(x) STR_IMPL(x)
+
+/** Return the name of the compile time libc. Returns NULL if we
+ * cannot identify the libc. */
+const char *
+tor_libc_get_name(void)
+{
+#ifdef __GLIBC__
+ return "Glibc";
+#else /* !defined(__GLIBC__) */
+ return NULL;
+#endif /* defined(__GLIBC__) */
+}
+
+/** Return a string representation of the version of the currently running
+ * version of Glibc. */
+const char *
+tor_libc_get_version_str(void)
+{
+#ifdef CHECK_LIBC_VERSION
+ const char *version = gnu_get_libc_version();
+ if (version == NULL)
+ return "N/A";
+ return version;
+#else /* !defined(CHECK_LIBC_VERSION) */
+ return "N/A";
+#endif /* defined(CHECK_LIBC_VERSION) */
+}
+
+/** Return a string representation of the version of Glibc that was used at
+ * compilation time. */
+const char *
+tor_libc_get_header_version_str(void)
+{
+#ifdef __GLIBC__
+ return STR(__GLIBC__) "." STR(__GLIBC_MINOR__);
+#else
+ return "N/A";
+#endif /* defined(__GLIBC__) */
+}
diff --git a/src/lib/osinfo/libc.h b/src/lib/osinfo/libc.h
new file mode 100644
index 0000000000..f4303f8c9c
--- /dev/null
+++ b/src/lib/osinfo/libc.h
@@ -0,0 +1,19 @@
+/* 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 libc.h
+ * @brief Header for lib/osinfo/libc.c
+ **/
+
+#ifndef TOR_LIB_OSINFO_LIBC_H
+#define TOR_LIB_OSINFO_LIBC_H
+
+const char *tor_libc_get_name(void);
+const char *tor_libc_get_version_str(void);
+const char *tor_libc_get_header_version_str(void);
+
+#endif /* !defined(TOR_LIB_OSINFO_LIBC_H) */
diff --git a/src/lib/process/process.c b/src/lib/process/process.c
index 12c1f9a772..d69b0ca115 100644
--- a/src/lib/process/process.c
+++ b/src/lib/process/process.c
@@ -374,7 +374,7 @@ process_get_protocol(const process_t *process)
return process->protocol;
}
-/** Set opague pointer to data. This function allows you to store a pointer to
+/** Set opaque pointer to data. This function allows you to store a pointer to
* your own data in the given process. Use <b>process_get_data()</b> in the
* various callback functions to retrieve the data again.
*
diff --git a/src/lib/process/process_unix.c b/src/lib/process/process_unix.c
index 2b47e1874d..82b2630a5d 100644
--- a/src/lib/process/process_unix.c
+++ b/src/lib/process/process_unix.c
@@ -418,7 +418,7 @@ process_unix_write(process_t *process, buf_t *buffer)
/* We have data to write and the kernel have told us to write it. */
return buf_flush_to_pipe(buffer,
process_get_unix_process(process)->stdin_handle.fd,
- max_to_write, &buffer_flush_len);
+ max_to_write);
}
/** Read data from the given process's standard output and put it into
diff --git a/src/lib/process/process_win32.c b/src/lib/process/process_win32.c
index 8683e17fc2..203df136aa 100644
--- a/src/lib/process/process_win32.c
+++ b/src/lib/process/process_win32.c
@@ -366,7 +366,7 @@ process_win32_write(struct process_t *process, buf_t *buffer)
/* Because of the slightly weird API for WriteFileEx() we must set this to 0
* before we call WriteFileEx() because WriteFileEx() does not reset the last
- * error itself when it's succesful. See comment below after the call to
+ * error itself when it's successful. See comment below after the call to
* GetLastError(). */
SetLastError(0);
@@ -479,9 +479,9 @@ process_win32_trigger_completion_callbacks(void)
}
}
-/** Start the periodic timer which is reponsible for checking whether processes
- * are still alive and to make sure that the Tor process is periodically being
- * moved into an alertable state. */
+/** Start the periodic timer which is responsible for checking whether
+ * processes are still alive and to make sure that the Tor process is
+ * periodically being moved into an alertable state. */
void
process_win32_timer_start(void)
{
@@ -547,7 +547,7 @@ process_win32_timer_callback(periodic_timer_t *timer, void *data)
/* If process_win32_timer_test_process() returns true, it means that
* smartlist_remove() might have been called on the list returned by
* process_get_all_processes(). We start the loop over again until we
- * have a succesful run over the entire list where the list was not
+ * have a successful run over the entire list where the list was not
* modified. */
if (process_win32_timer_test_process(process)) {
done = false;
@@ -573,7 +573,7 @@ process_win32_timer_test_process(process_t *process)
BOOL ret = FALSE;
DWORD exit_code = 0;
- /* Sometimes the Windows kernel wont give us the EOF/Broken Pipe error
+ /* Sometimes the Windows kernel won't give us the EOF/Broken Pipe error
* message until some time after the process have actually terminated. We
* make sure that our ReadFileEx() calls for the process have *all* returned
* and both standard out and error have been marked as EOF before we try to
@@ -619,7 +619,7 @@ process_win32_timer_test_process(process_t *process)
/** Create a new overlapped named pipe. This function creates a new connected,
* named, pipe in <b>*read_pipe</b> and <b>*write_pipe</b> if the function is
- * succesful. Returns true on sucess, false on failure. */
+ * successful. Returns true on success, false on failure. */
STATIC bool
process_win32_create_pipe(HANDLE *read_pipe,
HANDLE *write_pipe,
@@ -840,7 +840,7 @@ process_win32_stdin_write_done(DWORD error_code,
return;
if (error_code == 0) {
- /** Our data have been succesfully written. Clear our state and schedule
+ /** Our data have been successfully written. Clear our state and schedule
* the next write. */
win32_process->stdin_handle.data_available = 0;
memset(win32_process->stdin_handle.buffer, 0,
@@ -850,7 +850,7 @@ process_win32_stdin_write_done(DWORD error_code,
process_notify_event_stdin(process);
} else if (error_code == ERROR_HANDLE_EOF ||
error_code == ERROR_BROKEN_PIPE) {
- /* Our WriteFileEx() call was succesful, but we reached the end of our
+ /* Our WriteFileEx() call was successful, but we reached the end of our
* file. We mark our handle as having reached EOF and returns. */
tor_assert(byte_count == 0);
@@ -906,7 +906,7 @@ process_win32_read_from_handle(process_win32_handle_t *handle,
/* Because of the slightly weird API for ReadFileEx() we must set this to 0
* before we call ReadFileEx() because ReadFileEx() does not reset the last
- * error itself when it's succesful. See comment below after the call to
+ * error itself when it's successful. See comment below after the call to
* GetLastError(). */
SetLastError(0);
@@ -972,7 +972,7 @@ process_win32_handle_read_completion(process_win32_handle_t *handle,
handle->busy = false;
if (error_code == 0) {
- /* Our ReadFileEx() call was succesful and there is data for us. */
+ /* Our ReadFileEx() call was successful and there is data for us. */
/* This cast should be safe since byte_count should never be larger than
* BUFFER_SIZE. */
diff --git a/src/lib/process/restrict.c b/src/lib/process/restrict.c
index cd2a1c57b5..bf5ae8e500 100644
--- a/src/lib/process/restrict.c
+++ b/src/lib/process/restrict.c
@@ -44,7 +44,7 @@ tor_disable_debugger_attach(void)
{
int r = -1;
log_debug(LD_CONFIG,
- "Attemping to disable debugger attachment to Tor for "
+ "Attempting to disable debugger attachment to Tor for "
"unprivileged users.");
#if defined(__linux__) && defined(HAVE_SYS_PRCTL_H) \
&& defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
diff --git a/src/lib/process/waitpid.c b/src/lib/process/waitpid.c
index 33798f65f0..014bcf2927 100644
--- a/src/lib/process/waitpid.c
+++ b/src/lib/process/waitpid.c
@@ -113,7 +113,7 @@ clear_waitpid_callback(waitpid_callback_t *ent)
tor_free(ent);
}
-/** Helper: find the callack for <b>pid</b>; if there is one, run it,
+/** Helper: find the callback for <b>pid</b>; if there is one, run it,
* reporting the exit status as <b>status</b>. */
static void
notify_waitpid_callback_by_pid(pid_t pid, int status)
diff --git a/src/lib/pubsub/pub_binding_st.h b/src/lib/pubsub/pub_binding_st.h
index d7c562fc35..e35f246c57 100644
--- a/src/lib/pubsub/pub_binding_st.h
+++ b/src/lib/pubsub/pub_binding_st.h
@@ -30,7 +30,7 @@ typedef struct pub_binding_t {
/**
* A template for the msg_t fields that are filled in for this message.
* This is copied into outgoing messages, ensuring that their fields are set
- * corretly.
+ * correctly.
**/
msg_t msg_template;
} pub_binding_t;
diff --git a/src/lib/pubsub/pubsub_build.h b/src/lib/pubsub/pubsub_build.h
index 2781b8251a..87fcaf458e 100644
--- a/src/lib/pubsub/pubsub_build.h
+++ b/src/lib/pubsub/pubsub_build.h
@@ -55,7 +55,7 @@ void pubsub_builder_free_(pubsub_builder_t *);
/**
* Create a pubsub connector that a single subsystem will use to
- * register its messages. The main-init code does this during susbsystem
+ * register its messages. The main-init code does this during subsystem
* initialization.
*/
struct pubsub_connector_t *pubsub_connector_for_subsystem(pubsub_builder_t *,
diff --git a/src/lib/pubsub/pubsub_check.c b/src/lib/pubsub/pubsub_check.c
index dbcbb14746..84958e101a 100644
--- a/src/lib/pubsub/pubsub_check.c
+++ b/src/lib/pubsub/pubsub_check.c
@@ -31,7 +31,7 @@ static void pubsub_adjmap_add(pubsub_adjmap_t *map,
const pubsub_cfg_t *item);
/**
- * Helper: contruct and return a new pubsub_adjacency_map from <b>cfg</b>.
+ * Helper: construct and return a new pubsub_adjacency_map from <b>cfg</b>.
* Return NULL on error.
**/
static pubsub_adjmap_t *
diff --git a/src/lib/pubsub/pubsub_macros.h b/src/lib/pubsub/pubsub_macros.h
index e5ffbe501a..4f5b60c19b 100644
--- a/src/lib/pubsub/pubsub_macros.h
+++ b/src/lib/pubsub/pubsub_macros.h
@@ -135,7 +135,7 @@
#include "lib/pubsub/pubsub_flags.h"
#include "lib/pubsub/pubsub_publish.h"
-/* Implemenation notes:
+/* Implementation notes:
*
* For a messagename "foo", the DECLARE_MESSAGE*() macros must declare:
*
diff --git a/src/lib/sandbox/sandbox.c b/src/lib/sandbox/sandbox.c
index d4f0da8397..168dfd943c 100644
--- a/src/lib/sandbox/sandbox.c
+++ b/src/lib/sandbox/sandbox.c
@@ -204,6 +204,8 @@ static int filter_nopar_gen[] = {
#ifdef __NR__llseek
SCMP_SYS(_llseek),
#endif
+ // glob uses this..
+ SCMP_SYS(lstat),
SCMP_SYS(mkdir),
SCMP_SYS(mlockall),
#ifdef __NR_mmap
@@ -308,6 +310,8 @@ static int filter_nopar_gen[] = {
#define seccomp_rule_add_4(ctx,act,call,f1,f2,f3,f4) \
seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4))
+static const char *sandbox_get_interned_string(const char *str);
+
/**
* Function responsible for setting up the rt_sigaction syscall for
* the seccomp filter sandbox.
@@ -997,7 +1001,7 @@ sb_epoll_ctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
* the seccomp filter sandbox.
*
* NOTE: if multiple filters need to be added, the PR_SECCOMP parameter needs
- * to be whitelisted in this function.
+ * to be allowlisted in this function.
*/
static int
sb_prctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
@@ -1222,9 +1226,42 @@ static sandbox_filter_func_t filter_func[] = {
sb_kill
};
+/**
+ * Return the interned (and hopefully sandbox-permitted) string equal
+ * to @a str.
+ *
+ * Return NULL if `str` is NULL, or `str` is not an interned string.
+ **/
const char *
sandbox_intern_string(const char *str)
{
+ const char *interned = sandbox_get_interned_string(str);
+
+ if (sandbox_active && str != NULL && interned == NULL) {
+ log_warn(LD_BUG, "No interned sandbox parameter found for %s", str);
+ }
+
+ return interned ? interned : str;
+}
+
+/**
+ * Return true if the sandbox is running and we are missing an interned string
+ * equal to @a str.
+ */
+bool
+sandbox_interned_string_is_missing(const char *str)
+{
+ return sandbox_active && sandbox_get_interned_string(str) == NULL;
+}
+
+/**
+ * Try to find and return the interned string equal to @a str.
+ *
+ * If there is no such string, return NULL.
+ **/
+static const char *
+sandbox_get_interned_string(const char *str)
+{
sandbox_cfg_t *elem;
if (str == NULL)
@@ -1243,9 +1280,7 @@ sandbox_intern_string(const char *str)
}
}
- if (sandbox_active)
- log_warn(LD_BUG, "No interned sandbox parameter found for %s", str);
- return str;
+ return NULL;
}
/* DOCDOC */
diff --git a/src/lib/sandbox/sandbox.h b/src/lib/sandbox/sandbox.h
index a2b3227b90..eba99afbde 100644
--- a/src/lib/sandbox/sandbox.h
+++ b/src/lib/sandbox/sandbox.h
@@ -104,12 +104,11 @@ typedef struct {
#endif /* defined(USE_LIBSECCOMP) */
#ifdef USE_LIBSECCOMP
-/** Returns a registered protected string used with the sandbox, given that
- * it matches the parameter.
- */
const char* sandbox_intern_string(const char *param);
+bool sandbox_interned_string_is_missing(const char *s);
#else /* !defined(USE_LIBSECCOMP) */
#define sandbox_intern_string(s) (s)
+#define sandbox_interned_string_is_missing(s) (false)
#endif /* defined(USE_LIBSECCOMP) */
/** Creates an empty sandbox configuration file.*/
diff --git a/src/lib/string/compat_string.h b/src/lib/string/compat_string.h
index f05265bdcc..5c9bf05ebd 100644
--- a/src/lib/string/compat_string.h
+++ b/src/lib/string/compat_string.h
@@ -42,7 +42,7 @@ static inline int strcasecmp(const char *a, const char *b) {
* (If --enable-fragile-hardening is passed to configure, we use the hardened
* variants, which do not suffer from this issue.)
*
- * See https://trac.torproject.org/projects/tor/ticket/15205
+ * See https://bugs.torproject.org/tpo/core/tor/15205.
*/
#undef strlcat
#undef strlcpy
diff --git a/src/lib/string/util_string.c b/src/lib/string/util_string.c
index c8f12d780e..ba5f9f2203 100644
--- a/src/lib/string/util_string.c
+++ b/src/lib/string/util_string.c
@@ -143,6 +143,15 @@ tor_strupper(char *s)
}
}
+/** Replaces <b>old</b> with <b>replacement</b> in <b>s</b> */
+void
+tor_strreplacechar(char *s, char find, char replacement)
+{
+ for (s = strchr(s, find); s; s = strchr(s + 1, find)) {
+ *s = replacement;
+ }
+}
+
/** Return 1 if every character in <b>s</b> is printable, else return 0.
*/
int
diff --git a/src/lib/string/util_string.h b/src/lib/string/util_string.h
index e89233df88..15d35415fe 100644
--- a/src/lib/string/util_string.h
+++ b/src/lib/string/util_string.h
@@ -31,6 +31,7 @@ int tor_digest256_is_zero(const char *digest);
#define HEX_CHARACTERS "0123456789ABCDEFabcdef"
void tor_strlower(char *s);
void tor_strupper(char *s);
+void tor_strreplacechar(char *s, char find, char replacement);
int tor_strisprint(const char *s);
int tor_strisnonupper(const char *s);
int tor_strisspace(const char *s);
diff --git a/src/lib/subsys/initialization.md b/src/lib/subsys/initialization.md
index 012ab7000d..ee3104324d 100644
--- a/src/lib/subsys/initialization.md
+++ b/src/lib/subsys/initialization.md
@@ -50,7 +50,7 @@ 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
+In simplest terms, a **subsystem** is a logically separate part of Tor that
can be initialized, shut down, managed, and configured somewhat independently
of the rest of the program.
@@ -59,7 +59,7 @@ 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
+After defining a subsystem, it must be inserted in subsystem_list.c. At that
point, table-driven mechanisms in subsysmgr.c will invoke its functions when
appropriate.
diff --git a/src/lib/subsys/subsys.h b/src/lib/subsys/subsys.h
index 62c0de026d..abfc82d56a 100644
--- a/src/lib/subsys/subsys.h
+++ b/src/lib/subsys/subsys.h
@@ -15,6 +15,7 @@
struct pubsub_connector_t;
struct config_format_t;
+struct smartlist_t;
/**
* A subsystem is a part of Tor that is initialized, shut down, configured,
@@ -190,6 +191,17 @@ typedef struct subsys_fns_t {
* to disk.
**/
int (*flush_state)(void *);
+
+ /**
+ * Return a list of metrics store of this subsystem. This is called
+ * every time a request arrives on the MetricsPort.
+ *
+ * The list MUST contain metrics_store_t object and contains entries so it
+ * can be formatted for the metrics port.
+ *
+ * This can return NULL or be NULL.
+ **/
+ const struct smartlist_t *(*get_metrics)(void);
} subsys_fns_t;
#ifndef COCCI
diff --git a/src/lib/thread/compat_winthreads.c b/src/lib/thread/compat_winthreads.c
index 2ca5620d23..fcc9c0279b 100644
--- a/src/lib/thread/compat_winthreads.c
+++ b/src/lib/thread/compat_winthreads.c
@@ -10,18 +10,32 @@
* functions.
*/
+#include "orconfig.h"
+
#ifdef _WIN32
+/* For condition variable support */
+#ifndef WINVER
+#error "orconfig.h didn't define WINVER"
+#endif
+#ifndef _WIN32_WINNT
+#error "orconfig.h didn't define _WIN32_WINNT"
+#endif
+#if WINVER < 0x0600
+#error "winver too low"
+#endif
+#if _WIN32_WINNT < 0x0600
+#error "winver too low"
+#endif
#include <windows.h>
#include <process.h>
+#include <time.h>
+
#include "lib/thread/threads.h"
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/log/win32err.h"
-/* This value is more or less total cargo-cult */
-#define SPIN_COUNT 2000
-
/** Minimalist interface to run a void function in the background. On
* Unix calls fork, on win32 calls beginthread. Returns -1 on failure.
* func should not return, but rather should call spawn_exit.
@@ -64,45 +78,24 @@ tor_get_thread_id(void)
int
tor_cond_init(tor_cond_t *cond)
{
- memset(cond, 0, sizeof(tor_cond_t));
- if (InitializeCriticalSectionAndSpinCount(&cond->lock, SPIN_COUNT)==0) {
- return -1;
- }
- if ((cond->event = CreateEvent(NULL,TRUE,FALSE,NULL)) == NULL) {
- DeleteCriticalSection(&cond->lock);
- return -1;
- }
- cond->n_waiting = cond->n_to_wake = cond->generation = 0;
+ InitializeConditionVariable(&cond->cond);
return 0;
}
void
tor_cond_uninit(tor_cond_t *cond)
{
- DeleteCriticalSection(&cond->lock);
- CloseHandle(cond->event);
+ (void) cond;
}
-static void
-tor_cond_signal_impl(tor_cond_t *cond, int broadcast)
-{
- EnterCriticalSection(&cond->lock);
- if (broadcast)
- cond->n_to_wake = cond->n_waiting;
- else
- ++cond->n_to_wake;
- cond->generation++;
- SetEvent(cond->event);
- LeaveCriticalSection(&cond->lock);
-}
void
tor_cond_signal_one(tor_cond_t *cond)
{
- tor_cond_signal_impl(cond, 0);
+ WakeConditionVariable(&cond->cond);
}
void
tor_cond_signal_all(tor_cond_t *cond)
{
- tor_cond_signal_impl(cond, 1);
+ WakeAllConditionVariable(&cond->cond);
}
int
@@ -152,66 +145,23 @@ int
tor_cond_wait(tor_cond_t *cond, tor_mutex_t *lock_, const struct timeval *tv)
{
CRITICAL_SECTION *lock = &lock_->mutex;
- int generation_at_start;
- int waiting = 1;
- int result = -1;
- DWORD ms = INFINITE, ms_orig = INFINITE, startTime, endTime;
- if (tv)
- ms_orig = ms = tv->tv_sec*1000 + (tv->tv_usec+999)/1000;
-
- EnterCriticalSection(&cond->lock);
- ++cond->n_waiting;
- generation_at_start = cond->generation;
- LeaveCriticalSection(&cond->lock);
-
- LeaveCriticalSection(lock);
-
- startTime = GetTickCount();
- do {
- DWORD res;
- res = WaitForSingleObject(cond->event, ms);
- EnterCriticalSection(&cond->lock);
- if (cond->n_to_wake &&
- cond->generation != generation_at_start) {
- --cond->n_to_wake;
- --cond->n_waiting;
- result = 0;
- waiting = 0;
- goto out;
- } else if (res != WAIT_OBJECT_0) {
- result = (res==WAIT_TIMEOUT) ? 1 : -1;
- --cond->n_waiting;
- waiting = 0;
- goto out;
- } else if (ms != INFINITE) {
- endTime = GetTickCount();
- if (startTime + ms_orig <= endTime) {
- result = 1; /* Timeout */
- --cond->n_waiting;
- waiting = 0;
- goto out;
- } else {
- ms = startTime + ms_orig - endTime;
- }
- }
- /* If we make it here, we are still waiting. */
- if (cond->n_to_wake == 0) {
- /* There is nobody else who should wake up; reset
- * the event. */
- ResetEvent(cond->event);
- }
- out:
- LeaveCriticalSection(&cond->lock);
- } while (waiting);
-
- EnterCriticalSection(lock);
-
- EnterCriticalSection(&cond->lock);
- if (!cond->n_waiting)
- ResetEvent(cond->event);
- LeaveCriticalSection(&cond->lock);
+ DWORD ms = INFINITE;
+ if (tv) {
+ ms = tv->tv_sec*1000 + (tv->tv_usec+999)/1000;
+ }
- return result;
+ BOOL ok = SleepConditionVariableCS(&cond->cond, lock, ms);
+ if (!ok) {
+ DWORD err = GetLastError();
+ if (err == ERROR_TIMEOUT) {
+ return 1;
+ }
+ char *msg = format_win32_error(err);
+ log_err(LD_GENERAL, "Error waiting for condition variable: %s", msg);
+ tor_free(msg);
+ return -1;
+ }
+ return 0;
}
void
diff --git a/src/lib/thread/threads.h b/src/lib/thread/threads.h
index fcc0c23a87..ead4dc3874 100644
--- a/src/lib/thread/threads.h
+++ b/src/lib/thread/threads.h
@@ -42,12 +42,7 @@ typedef struct tor_cond_t {
#ifdef USE_PTHREADS
pthread_cond_t cond;
#elif defined(USE_WIN32_THREADS)
- HANDLE event;
-
- CRITICAL_SECTION lock;
- int n_waiting;
- int n_to_wake;
- int generation;
+ CONDITION_VARIABLE cond;
#else
#error no known condition implementation.
#endif /* defined(USE_PTHREADS) || ... */
diff --git a/src/lib/time/compat_time.h b/src/lib/time/compat_time.h
index 5089e16ca5..08fd0f0c25 100644
--- a/src/lib/time/compat_time.h
+++ b/src/lib/time/compat_time.h
@@ -60,7 +60,7 @@
*
* Q: So, what backends is monotime_coarse using?
*
- * A: Generally speaking, it uses "whatever monotonic-ish time implemenation
+ * A: Generally speaking, it uses "whatever monotonic-ish time implementation
* does not require a context switch." The various implementations provide
* this by having a view of the current time in a read-only memory page that
* is updated with a frequency corresponding to the kernel's tick count.
diff --git a/src/lib/time/tvdiff.c b/src/lib/time/tvdiff.c
index cbad5a48b8..14a89bc76e 100644
--- a/src/lib/time/tvdiff.c
+++ b/src/lib/time/tvdiff.c
@@ -30,7 +30,7 @@ tv_secdiff_impl(const struct timeval *start, const struct timeval *end)
const int64_t s = (int64_t)start->tv_sec;
const int64_t e = (int64_t)end->tv_sec;
- /* This may not be the most efficient way of implemeting this check,
+ /* This may not be the most efficient way of implementing this check,
* but it's easy to see that it's correct and doesn't overflow */
if (s > 0 && e < INT64_MIN + s) {
diff --git a/src/lib/tls/buffers_tls.c b/src/lib/tls/buffers_tls.c
index b92a14d6a1..de0e9cb4ef 100644
--- a/src/lib/tls/buffers_tls.c
+++ b/src/lib/tls/buffers_tls.c
@@ -59,6 +59,9 @@ read_to_chunk_tls(buf_t *buf, chunk_t *chunk, tor_tls_t *tls,
* Second, the TLS stream's events do not correspond directly to network
* events: sometimes, before a TLS stream can read, the network must be
* ready to write -- or vice versa.
+ *
+ * On success, return the number of bytes read. On error, a TOR_TLS_* negative
+ * code is returned (expect any of them except TOR_TLS_DONE).
*/
int
buf_read_from_tls(buf_t *buf, tor_tls_t *tls, size_t at_most)
@@ -92,8 +95,6 @@ buf_read_from_tls(buf_t *buf, tor_tls_t *tls, size_t at_most)
return r; /* Error */
tor_assert(total_read+r <= BUF_MAX_LEN);
total_read += r;
- if ((size_t)r < readlen) /* eof, block, or no more to read. */
- break;
}
return (int)total_read;
}
@@ -105,8 +106,7 @@ buf_read_from_tls(buf_t *buf, tor_tls_t *tls, size_t at_most)
* written on success, and a TOR_TLS error code on failure or blocking.
*/
static inline int
-flush_chunk_tls(tor_tls_t *tls, buf_t *buf, chunk_t *chunk,
- size_t sz, size_t *buf_flushlen)
+flush_chunk_tls(tor_tls_t *tls, buf_t *buf, chunk_t *chunk, size_t sz)
{
int r;
size_t forced;
@@ -125,13 +125,9 @@ flush_chunk_tls(tor_tls_t *tls, buf_t *buf, chunk_t *chunk,
r = tor_tls_write(tls, data, sz);
if (r < 0)
return r;
- if (*buf_flushlen > (size_t)r)
- *buf_flushlen -= r;
- else
- *buf_flushlen = 0;
buf_drain(buf, r);
- log_debug(LD_NET,"flushed %d bytes, %d ready to flush, %d remain.",
- r,(int)*buf_flushlen,(int)buf->datalen);
+ log_debug(LD_NET,"flushed %d bytes, %d remain.",
+ r,(int)buf->datalen);
return r;
}
@@ -139,18 +135,13 @@ flush_chunk_tls(tor_tls_t *tls, buf_t *buf, chunk_t *chunk,
* more than <b>flushlen</b> bytes.
*/
int
-buf_flush_to_tls(buf_t *buf, tor_tls_t *tls, size_t flushlen,
- size_t *buf_flushlen)
+buf_flush_to_tls(buf_t *buf, tor_tls_t *tls, size_t flushlen)
{
int r;
size_t flushed = 0;
ssize_t sz;
- tor_assert(buf_flushlen);
- IF_BUG_ONCE(*buf_flushlen > buf->datalen) {
- *buf_flushlen = buf->datalen;
- }
- IF_BUG_ONCE(flushlen > *buf_flushlen) {
- flushlen = *buf_flushlen;
+ IF_BUG_ONCE(flushlen > buf->datalen) {
+ flushlen = buf->datalen;
}
sz = (ssize_t) flushlen;
@@ -169,7 +160,7 @@ buf_flush_to_tls(buf_t *buf, tor_tls_t *tls, size_t flushlen,
flushlen0 = 0;
}
- r = flush_chunk_tls(tls, buf, buf->head, flushlen0, buf_flushlen);
+ r = flush_chunk_tls(tls, buf, buf->head, flushlen0);
if (r < 0)
return r;
flushed += r;
diff --git a/src/lib/tls/buffers_tls.h b/src/lib/tls/buffers_tls.h
index 587426801d..ed391cefbd 100644
--- a/src/lib/tls/buffers_tls.h
+++ b/src/lib/tls/buffers_tls.h
@@ -18,6 +18,6 @@ struct tor_tls_t;
int buf_read_from_tls(struct buf_t *buf,
struct tor_tls_t *tls, size_t at_most);
int buf_flush_to_tls(struct buf_t *buf, struct tor_tls_t *tls,
- size_t sz, size_t *buf_flushlen);
+ size_t sz);
#endif /* !defined(TOR_BUFFERS_TLS_H) */
diff --git a/src/lib/tls/tortls_openssl.c b/src/lib/tls/tortls_openssl.c
index 2269714141..ad9b49ab4f 100644
--- a/src/lib/tls/tortls_openssl.c
+++ b/src/lib/tls/tortls_openssl.c
@@ -342,7 +342,7 @@ tor_tls_init(void)
#if (SIZEOF_VOID_P >= 8 && \
OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,1))
- long version = OpenSSL_version_num();
+ long version = tor_OpenSSL_version_num();
/* LCOV_EXCL_START : we can't test these lines on the same machine */
if (version >= OPENSSL_V_SERIES(1,0,1)) {
diff --git a/src/lib/trace/.may_include b/src/lib/trace/.may_include
index 45cd13676b..1ed533cc7a 100644
--- a/src/lib/trace/.may_include
+++ b/src/lib/trace/.may_include
@@ -1,3 +1,4 @@
orconfig.h
lib/log/*.h
lib/trace/*.h
+lib/subsys/*.h
diff --git a/src/lib/trace/debug.h b/src/lib/trace/debug.h
index 87b3074e0b..4ee14fab8d 100644
--- a/src/lib/trace/debug.h
+++ b/src/lib/trace/debug.h
@@ -6,8 +6,10 @@
* \brief Macros for debugging our event-trace support.
**/
-#ifndef TOR_TRACE_LOG_DEBUG_H
-#define TOR_TRACE_LOG_DEBUG_H
+#ifndef TOR_TRACE_DEBUG_H
+#define TOR_TRACE_DEBUG_H
+
+#ifdef USE_TRACING_INSTRUMENTATION_LOG_DEBUG
#include "lib/log/log.h"
@@ -17,14 +19,20 @@
/* Send every event to a debug log level. This is useful to debug new trace
* events without implementing them for a specific event tracing framework.
- * Note that the arguments are ignored since at this step we do not know the
- * types and amount there is. */
+ *
+ * NOTE: arguments can't be used because there is no easy generic ways to learn
+ * their type and amount. It is probably doable with massive C pre-processor
+ * trickery but this is meant to be simple. */
+
+#define TOR_TRACE_LOG_DEBUG(subsystem, event_name, ...) \
+ log_debug(LD_GENERAL, "Tracepoint \"" XSTR(event_name) "\" from " \
+ "subsystem \"" XSTR(subsystem) "\" hit.")
+
+#else /* defined(USE_TRACING_INSTRUMENTATION_LOG_DEBUG) */
+
+/* NOP the debug event. */
+#define TOR_TRACE_LOG_DEBUG(subsystem, name, ...)
-/* Example on how to map a tracepoint to log_debug(). */
-#undef tor_trace
-#define tor_trace(subsystem, name, args...) \
- log_debug(LD_GENERAL, "Trace event \"" XSTR(name) "\" from " \
- "\"" XSTR(subsystem) "\" hit. " \
- "(line "XSTR(__LINE__) ")")
+#endif /* defined(USE_TRACING_INSTRUMENTATION_LOG_DEBUG) */
-#endif /* !defined(TOR_TRACE_LOG_DEBUG_H) */
+#endif /* !defined(TOR_TRACE_DEBUG_H) */
diff --git a/src/lib/trace/events.h b/src/lib/trace/events.h
index 368f85dd02..ce1604de22 100644
--- a/src/lib/trace/events.h
+++ b/src/lib/trace/events.h
@@ -3,43 +3,75 @@
/**
* \file events.h
- * \brief Header file for Tor event tracing.
+ * \brief Header file for Tor tracing instrumentation definition.
**/
-#ifndef TOR_TRACE_EVENTS_H
-#define TOR_TRACE_EVENTS_H
+#ifndef TOR_LIB_TRACE_EVENTS_H
+#define TOR_LIB_TRACE_EVENTS_H
+
+#include "orconfig.h"
/*
- * The following defines a generic event tracing function name that has to be
- * used to trace events in the code base.
+ * A tracepoint signature is defined as follow:
+ *
+ * tor_trace(<subsystem>, <event_name>, <args>...)
+ *
+ * If tracing is enabled, the tor_trace() macro is mapped to all possible
+ * instrumentations (defined below). Each instrumentation type MUST define a
+ * top level macro (TOR_TRACE_<type>) so it can be inserted into each
+ * tracepoint.
+ *
+ * In case no tracing is enabled (HAVE_TRACING), tracepoints are NOP and thus
+ * have no execution cost.
*
- * That generic function is then defined by a event tracing framework. For
- * instance, the "log debug" framework sends all trace events to log_debug()
- * which is defined in src/trace/debug.h which can only be enabled at compile
- * time (--enable-event-tracing-debug).
+ * Currently, three types of instrumentation are supported:
*
- * By default, every trace events in the code base are replaced by a NOP. See
- * doc/HACKING/Tracing.md for more information on how to use event tracing or
- * add events.
+ * log-debug: Every tracepoints is mapped to a log_debug() statement.
+ *
+ * User Statically-Defined Tracing (USDT): Probes that can be used with perf,
+ * dtrace, SystemTap, DTrace and BPF Compiler Collection (BCC).
+ *
+ * LTTng-UST: Probes for the LTTng Userspace Tracer. If USDT interface
+ * (sdt.h) is available, the USDT probes are also generated by LTTng thus
+ * enabling this instrumentation provides both probes.
*/
-#ifdef TOR_EVENT_TRACING_ENABLED
-/* Map every trace event to a per subsystem macro. */
-#define tor_trace(subsystem, name, ...) \
- tor_trace_##subsystem(name, __VA_ARGS__)
+/** Helper to disambiguate these identifiers in the code base. They should
+ * only be used with tor_trace() like so:
+ *
+ * tor_trace(TR_SUBSYS(circuit), TR_EV(opened), ...);
+ */
+
+#define TR_SUBSYS(name) tor_ ## name
+#define TR_EV(name) name
+
+#ifdef HAVE_TRACING
-/* Enable event tracing for the debug framework where all trace events are
- * mapped to a log_debug(). */
-#ifdef USE_EVENT_TRACING_DEBUG
+#define tor_trace(subsystem, event_name, ...) \
+ do { \
+ TOR_TRACE_LOG_DEBUG(subsystem, event_name); \
+ TOR_TRACE_USDT(subsystem, event_name, ## __VA_ARGS__); \
+ TOR_TRACE_LTTNG(subsystem, event_name, ## __VA_ARGS__); \
+ } while (0)
+
+/* This corresponds to the --enable-tracing-instrumentation-log-debug
+ * configure option which maps all tracepoints to a log_debug() statement. */
#include "lib/trace/debug.h"
-#endif
-#else /* !defined(TOR_EVENT_TRACING_ENABLED) */
+/* This corresponds to the --enable-tracing-instrumentation-usdt configure
+ * option which will generate USDT probes for each tracepoints. */
+#include "lib/trace/usdt/usdt.h"
+
+/* This corresponds to the --enable-tracing-instrumentation-lttng configure
+ * option which will generate LTTng probes for each tracepoints. */
+#include "lib/trace/lttng/lttng.h"
+
+#else /* !defined(HAVE_TRACING) */
-/* Reaching this point, we NOP every event declaration because event tracing
- * is not been enabled at compile time. */
-#define tor_trace(subsystem, name, args...)
+/* Reaching this point, tracing is disabled thus we NOP every tracepoints
+ * declaration so we have no execution cost at runtime. */
+#define tor_trace(subsystem, name, ...)
-#endif /* defined(TOR_EVENT_TRACING_ENABLED) */
+#endif /* defined(HAVE_TRACING) */
-#endif /* !defined(TOR_TRACE_EVENTS_H) */
+#endif /* !defined(TOR_LIB_TRACE_EVENTS_H) */
diff --git a/src/lib/trace/include.am b/src/lib/trace/include.am
index 98098c87f4..6fe1365652 100644
--- a/src/lib/trace/include.am
+++ b/src/lib/trace/include.am
@@ -2,18 +2,34 @@
noinst_LIBRARIES += \
src/lib/libtor-trace.a
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_TRACE_A_SOURCES = \
+ src/lib/trace/trace.c \
+ src/lib/trace/trace_sys.c
+
# ADD_C_FILE: INSERT HEADERS HERE.
TRACEHEADERS = \
- src/lib/trace/trace.h \
+ src/lib/trace/trace.h \
+ src/lib/trace/trace_sys.h \
src/lib/trace/events.h
-if USE_EVENT_TRACING_DEBUG
+if USE_TRACING_INSTRUMENTATION_LOG_DEBUG
TRACEHEADERS += \
src/lib/trace/debug.h
endif
-# ADD_C_FILE: INSERT SOURCES HERE.
-src_lib_libtor_trace_a_SOURCES = \
- src/lib/trace/trace.c
+if USE_TRACING_INSTRUMENTATION_USDT
+include src/lib/trace/usdt/include.am
+endif
+
+if USE_TRACING_INSTRUMENTATION_LTTNG
+include src/lib/trace/lttng/include.am
+endif
+
+if USE_TRACING
+src_lib_libtor_trace_a_SOURCES = $(LIBTOR_TRACE_A_SOURCES)
+else
+src_lib_libtor_trace_a_SOURCES = src/lib/trace/trace_stub.c
+endif
noinst_HEADERS+= $(TRACEHEADERS)
diff --git a/src/lib/trace/lttng/include.am b/src/lib/trace/lttng/include.am
new file mode 100644
index 0000000000..4495ce0900
--- /dev/null
+++ b/src/lib/trace/lttng/include.am
@@ -0,0 +1,3 @@
+# ADD_C_FILE: INSERT HEADERS HERE.
+TRACEHEADERS += \
+ src/lib/trace/lttng/lttng.h
diff --git a/src/lib/trace/lttng/lttng.h b/src/lib/trace/lttng/lttng.h
new file mode 100644
index 0000000000..8ede98bb02
--- /dev/null
+++ b/src/lib/trace/lttng/lttng.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file lttng.h
+ * \brief Header file for lttng.c.
+ **/
+
+#ifndef TOR_TRACE_LTTNG_LTTNG_H
+#define TOR_TRACE_LTTNG_LTTNG_H
+
+#ifdef USE_TRACING_INSTRUMENTATION_LTTNG
+
+#include <lttng/tracepoint.h>
+
+/* Map event to an LTTng tracepoint. */
+#define TOR_TRACE_LTTNG(subsystem, event_name, ...) \
+ tracepoint(subsystem, event_name, ## __VA_ARGS__)
+
+#else /* !defined(USE_TRACING_INSTRUMENTATION_LTTNG) */
+
+/* NOP event. */
+#define TOR_TRACE_LTTNG(subsystem, event_name, ...)
+
+#endif /* !defined(USE_TRACING_INSTRUMENTATION_LTTNG) */
+
+#endif /* TOR_TRACE_LTTNG_LTTNG_H */
+
diff --git a/src/lib/trace/trace.c b/src/lib/trace/trace.c
index 4e5c66b4c6..10d11c17c5 100644
--- a/src/lib/trace/trace.c
+++ b/src/lib/trace/trace.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2020, The Tor Project, Inc. */
+/* Copyright (c) 2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,3 +15,9 @@ void
tor_trace_init(void)
{
}
+
+/** Free all the tracing library. */
+void
+tor_trace_free_all(void)
+{
+}
diff --git a/src/lib/trace/trace.h b/src/lib/trace/trace.h
index 5e24678c3c..22589dbe94 100644
--- a/src/lib/trace/trace.h
+++ b/src/lib/trace/trace.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2020, The Tor Project, Inc. */
+/* Copyright (c) 2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -6,9 +6,31 @@
* \brief Header for trace.c
**/
-#ifndef TOR_TRACE_TRACE_H
-#define TOR_TRACE_TRACE_H
+#ifndef TOR_LIB_TRACE_TRACE_H
+#define TOR_LIB_TRACE_TRACE_H
+
+#include "orconfig.h"
void tor_trace_init(void);
+void tor_trace_free_all(void);
+
+#ifdef HAVE_TRACING
+
+#include "lib/log/log.h"
+
+static inline void
+tracing_log_warning(void)
+{
+ log_warn(LD_GENERAL,
+ "Tracing capabilities have been built in. If this is NOT on "
+ "purpose, your tor is NOT safe to run.");
+}
+
+#else
+
+/* NOP it. */
+#define tracing_log_warning()
+
+#endif /* defined(HAVE_TRACING) */
-#endif /* !defined(TOR_TRACE_TRACE_H) */
+#endif /* !defined(TOR_LIB_TRACE_TRACE_H) */
diff --git a/src/lib/trace/trace_stub.c b/src/lib/trace/trace_stub.c
new file mode 100644
index 0000000000..fddf8c63f0
--- /dev/null
+++ b/src/lib/trace/trace_stub.c
@@ -0,0 +1,19 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file trace_stub.c
+ * \brief Stub declarations for use when trace library is disabled.
+ **/
+
+#include "lib/subsys/subsys.h"
+
+#include "lib/trace/trace_sys.h"
+
+const subsys_fns_t sys_tracing = {
+ SUBSYS_DECLARE_LOCATION(),
+
+ .name = "tracing",
+ .supported = false,
+ .level = TRACE_SUBSYS_LEVEL,
+};
diff --git a/src/lib/trace/trace_sys.c b/src/lib/trace/trace_sys.c
new file mode 100644
index 0000000000..2ba0258407
--- /dev/null
+++ b/src/lib/trace/trace_sys.c
@@ -0,0 +1,36 @@
+/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file log_sys.c
+ * \brief Setup and tear down the tracing module.
+ **/
+
+#include "lib/subsys/subsys.h"
+
+#include "lib/trace/trace.h"
+#include "lib/trace/trace_sys.h"
+
+static int
+subsys_tracing_initialize(void)
+{
+ tor_trace_init();
+ return 0;
+}
+
+static void
+subsys_tracing_shutdown(void)
+{
+ tor_trace_free_all();
+}
+
+const subsys_fns_t sys_tracing = {
+ SUBSYS_DECLARE_LOCATION(),
+
+ .name = "tracing",
+ .supported = true,
+ .level = TRACE_SUBSYS_LEVEL,
+
+ .initialize = subsys_tracing_initialize,
+ .shutdown = subsys_tracing_shutdown,
+};
diff --git a/src/lib/trace/trace_sys.h b/src/lib/trace/trace_sys.h
new file mode 100644
index 0000000000..d4da5a9701
--- /dev/null
+++ b/src/lib/trace/trace_sys.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file log_sys.h
+ * \brief Declare subsystem object for the logging module.
+ **/
+
+#ifndef TOR_TRACE_SYS_H
+#define TOR_TRACE_SYS_H
+
+extern const struct subsys_fns_t sys_tracing;
+
+/**
+ * Subsystem level for the tracing system.
+ *
+ * Defined here so that it can be shared between the real and stub
+ * definitions.
+ **/
+#define TRACE_SUBSYS_LEVEL (-85)
+
+#endif /* !defined(TOR_TRACE_SYS_H) */
diff --git a/src/lib/trace/usdt/include.am b/src/lib/trace/usdt/include.am
new file mode 100644
index 0000000000..4e7e04c326
--- /dev/null
+++ b/src/lib/trace/usdt/include.am
@@ -0,0 +1,3 @@
+# ADD_C_FILE: INSERT HEADERS HERE.
+TRACEHEADERS += \
+ src/lib/trace/usdt/usdt.h
diff --git a/src/lib/trace/usdt/usdt.h b/src/lib/trace/usdt/usdt.h
new file mode 100644
index 0000000000..0b5fd6c444
--- /dev/null
+++ b/src/lib/trace/usdt/usdt.h
@@ -0,0 +1,33 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file trace.h
+ * \brief Header for usdt.h
+ **/
+
+#ifndef TOR_TRACE_USDT_USDT_H
+#define TOR_TRACE_USDT_USDT_H
+
+#ifdef USE_TRACING_INSTRUMENTATION_USDT
+
+#ifdef HAVE_SYS_SDT_H
+#define SDT_USE_VARIADIC
+#include <sys/sdt.h>
+#define TOR_STAP_PROBEV STAP_PROBEV
+#else /* defined(HAVE_SYS_SDT_H) */
+#define TOR_STAP_PROBEV(...)
+#endif
+
+/* Map events to an USDT probe. */
+#define TOR_TRACE_USDT(subsystem, event_name, ...) \
+ TOR_STAP_PROBEV(subsystem, event_name, ## __VA_ARGS__);
+
+#else /* !defined(USE_TRACING_INSTRUMENTATION_USDT) */
+
+/* NOP event. */
+#define TOR_TRACE_USDT(subsystem, event_name, ...)
+
+#endif /* !defined(USE_TRACING_INSTRUMENTATION_USDT) */
+
+#endif /* !defined(TOR_TRACE_USDT_USDT_H) */
diff --git a/src/mainpage.md b/src/mainpage.md
index 2c4c494354..91ceb7dbf7 100644
--- a/src/mainpage.md
+++ b/src/mainpage.md
@@ -83,8 +83,9 @@ 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{ext} -- Code maintained elsewhere that we include in the Tor
+ source distribution. You should not edit this code if you can
+ avoid it: we try to keep it identical to the upstream versions.
- \refdir{lib} -- Lower-level utility code, not necessarily
tor-specific.
diff --git a/src/rust/crypto/rand/rng.rs b/src/rust/crypto/rand/rng.rs
index 96e112799e..644a5c20b1 100644
--- a/src/rust/crypto/rand/rng.rs
+++ b/src/rust/crypto/rand/rng.rs
@@ -33,7 +33,7 @@ mod internal {
/// A wrapper around OpenSSL's RNG.
pub struct TorRng {
// This private, zero-length field forces the struct to be treated the
- // same as its opaque C couterpart.
+ // same as its opaque C counterpart.
_unused: [u8; 0],
}
@@ -83,7 +83,7 @@ mod internal {
/// obtained from the operating system.
pub struct TorStrongestRng {
// This private, zero-length field forces the struct to be treated the
- // same as its opaque C couterpart.
+ // same as its opaque C counterpart.
_unused: [u8; 0],
}
diff --git a/src/rust/external/crypto_digest.rs b/src/rust/external/crypto_digest.rs
index 454f836bad..873f75e7a3 100644
--- a/src/rust/external/crypto_digest.rs
+++ b/src/rust/external/crypto_digest.rs
@@ -79,7 +79,7 @@ const N_COMMON_DIGEST_ALGORITHMS: usize = DIGEST_SHA256 as usize + 1;
#[allow(non_camel_case_types)]
struct crypto_digest_t {
// This private, zero-length field forces the struct to be treated the same
- // as its opaque C couterpart.
+ // as its opaque C counterpart.
_unused: [u8; 0],
}
@@ -89,7 +89,7 @@ struct crypto_digest_t {
#[allow(non_camel_case_types)]
struct crypto_xof_t {
// This private, zero-length field forces the struct to be treated the same
- // as its opaque C couterpart.
+ // as its opaque C counterpart.
_unused: [u8; 0],
}
@@ -254,7 +254,7 @@ impl CryptoDigest {
/// * `crypto_digest256_new`
/// * `crypto_digest512_new`
/// * `tor_malloc` (called by `crypto_digest256_new`, but we make
- /// assumptions about its behvaiour and return values here)
+ /// assumptions about its behaviour and return values here)
pub fn new(algorithm: Option<DigestAlgorithm>) -> CryptoDigest {
let digest: *mut crypto_digest_t;
diff --git a/src/rust/protover/ffi.rs b/src/rust/protover/ffi.rs
index 14170d0353..2bf8d3a987 100644
--- a/src/rust/protover/ffi.rs
+++ b/src/rust/protover/ffi.rs
@@ -84,7 +84,7 @@ pub extern "C" fn protocol_list_supports_protocol(
version: uint32_t,
) -> c_int {
if c_protocol_list.is_null() {
- return 1;
+ return 0;
}
// Require an unsafe block to read the version from a C string. The pointer
@@ -93,7 +93,7 @@ pub extern "C" fn protocol_list_supports_protocol(
let protocol_list = match c_str.to_str() {
Ok(n) => n,
- Err(_) => return 1,
+ Err(_) => return 0,
};
let proto_entry: UnvalidatedProtoEntry = match protocol_list.parse() {
Ok(n) => n,
@@ -140,7 +140,7 @@ pub extern "C" fn protocol_list_supports_protocol_or_later(
version: uint32_t,
) -> c_int {
if c_protocol_list.is_null() {
- return 1;
+ return 0;
}
// Require an unsafe block to read the version from a C string. The pointer
@@ -149,7 +149,7 @@ pub extern "C" fn protocol_list_supports_protocol_or_later(
let protocol_list = match c_str.to_str() {
Ok(n) => n,
- Err(_) => return 1,
+ Err(_) => return 0,
};
let protocol = match translate_to_rust(c_protocol) {
@@ -159,7 +159,7 @@ pub extern "C" fn protocol_list_supports_protocol_or_later(
let proto_entry: UnvalidatedProtoEntry = match protocol_list.parse() {
Ok(n) => n,
- Err(_) => return 1,
+ Err(_) => return 0,
};
if proto_entry.supports_protocol_or_later(&protocol.into(), &version) {
diff --git a/src/rust/protover/protover.rs b/src/rust/protover/protover.rs
index 06c4dd2398..da87509ffa 100644
--- a/src/rust/protover/protover.rs
+++ b/src/rust/protover/protover.rs
@@ -160,31 +160,31 @@ pub(crate) fn get_supported_protocols_cstr() -> &'static CStr {
cstr!(
"Cons=1-2 \
Desc=1-2 \
- DirCache=1-2 \
+ DirCache=2 \
FlowCtrl=1 \
HSDir=1-2 \
- HSIntro=3-4 \
+ HSIntro=3-5 \
HSRend=1-2 \
Link=1-5 \
LinkAuth=3 \
Microdesc=1-2 \
Padding=2 \
- Relay=1-2"
+ Relay=1-3"
)
} else {
cstr!(
"Cons=1-2 \
Desc=1-2 \
- DirCache=1-2 \
+ DirCache=2 \
FlowCtrl=1 \
HSDir=1-2 \
- HSIntro=3-4 \
+ HSIntro=3-5 \
HSRend=1-2 \
Link=1-5 \
LinkAuth=1,3 \
Microdesc=1-2 \
Padding=2 \
- Relay=1-2"
+ Relay=1-3"
)
}
}
@@ -253,6 +253,11 @@ impl FromStr for ProtoEntry {
/// Otherwise, the `Err` value of this `Result` is a `ProtoverError`.
fn from_str(protocol_entry: &str) -> Result<ProtoEntry, ProtoverError> {
let mut proto_entry: ProtoEntry = ProtoEntry::default();
+
+ if protocol_entry.is_empty() {
+ return Ok(proto_entry);
+ }
+
let entries = protocol_entry.split(' ');
for entry in entries {
@@ -501,6 +506,10 @@ impl UnvalidatedProtoEntry {
) -> Result<Vec<(&'a str, &'a str)>, ProtoverError> {
let mut protovers: Vec<(&str, &str)> = Vec::new();
+ if protocol_string.is_empty() {
+ return Ok(protovers);
+ }
+
for subproto in protocol_string.split(' ') {
let mut parts = subproto.splitn(2, '=');
@@ -859,7 +868,8 @@ mod test {
#[test]
fn test_protoentry_from_str_empty() {
- assert_protoentry_is_unparseable!("");
+ assert_protoentry_is_parseable!("");
+ assert!(UnvalidatedProtoEntry::from_str("").is_ok());
}
#[test]
@@ -883,11 +893,6 @@ mod test {
}
#[test]
- fn test_protoentry_from_str_() {
- assert_protoentry_is_unparseable!("");
- }
-
- #[test]
fn test_protoentry_all_supported_single_protocol_single_version() {
let protocol: UnvalidatedProtoEntry = "Cons=1".parse().unwrap();
let unsupported: Option<UnvalidatedProtoEntry> = protocol.all_supported();
diff --git a/src/rust/protover/tests/protover.rs b/src/rust/protover/tests/protover.rs
index d563202d87..a6305ac39a 100644
--- a/src/rust/protover/tests/protover.rs
+++ b/src/rust/protover/tests/protover.rs
@@ -70,18 +70,6 @@ fn protocol_all_supported_with_one_value() {
}
#[test]
-#[should_panic]
-fn parse_protocol_unvalidated_with_empty() {
- let _: UnvalidatedProtoEntry = "".parse().unwrap();
-}
-
-#[test]
-#[should_panic]
-fn parse_protocol_validated_with_empty() {
- let _: UnvalidatedProtoEntry = "".parse().unwrap();
-}
-
-#[test]
fn protocol_all_supported_with_three_values() {
let protocols: UnvalidatedProtoEntry = "LinkAuth=1 Microdesc=1-2 Relay=2".parse().unwrap();
let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported();
@@ -156,7 +144,6 @@ fn parse_protocol_with_unexpected_characters() {
}
#[test]
-#[should_panic]
fn protover_compute_vote_returns_empty_for_empty_string() {
let protocols: &[UnvalidatedProtoEntry] = &["".parse().unwrap()];
let listed = ProtoverVote::compute(protocols, &1);
diff --git a/src/rust/tor_allocate/tor_allocate.rs b/src/rust/tor_allocate/tor_allocate.rs
index 682a524ee7..7b35e2451f 100644
--- a/src/rust/tor_allocate/tor_allocate.rs
+++ b/src/rust/tor_allocate/tor_allocate.rs
@@ -60,7 +60,7 @@ pub fn allocate_and_copy_string(src: &str) -> *mut c_char {
unsafe { ptr::copy_nonoverlapping(bytes.as_ptr(), dest, size) };
// set the last byte as null, using the ability to index into a slice
- // rather than doing pointer arithmatic
+ // rather than doing pointer arithmetic
let slice = unsafe { slice::from_raw_parts_mut(dest, size_with_null_byte) };
slice[size] = 0; // add a null terminator
diff --git a/src/rust/tor_log/tor_log.rs b/src/rust/tor_log/tor_log.rs
index bbaf97129c..391cb32ab3 100644
--- a/src/rust/tor_log/tor_log.rs
+++ b/src/rust/tor_log/tor_log.rs
@@ -103,7 +103,7 @@ pub mod log {
static LD_GENERAL_: u64;
}
- /// Translate Rust defintions of log domain levels to C. This exposes a 1:1
+ /// Translate Rust definitions of log domain levels to C. This exposes a 1:1
/// mapping between types.
#[inline]
pub unsafe fn translate_domain(domain: LogDomain) -> u64 {
@@ -113,7 +113,7 @@ pub mod log {
}
}
- /// Translate Rust defintions of log severity levels to C. This exposes a
+ /// Translate Rust definitions of log severity levels to C. This exposes a
/// 1:1 mapping between types.
#[inline]
pub unsafe fn translate_severity(severity: LogSeverity) -> c_int {
diff --git a/src/test/conf_examples/bug_31495_1/expected b/src/test/conf_examples/bug_31495_1/expected
new file mode 100644
index 0000000000..246347b668
--- /dev/null
+++ b/src/test/conf_examples/bug_31495_1/expected
@@ -0,0 +1,2 @@
+Bridge 127.0.0.1:9050
+UseBridges 1
diff --git a/src/test/conf_examples/bug_31495_1/expected_log b/src/test/conf_examples/bug_31495_1/expected_log
new file mode 100644
index 0000000000..a4b98345d6
--- /dev/null
+++ b/src/test/conf_examples/bug_31495_1/expected_log
@@ -0,0 +1 @@
+Configuration was valid \ No newline at end of file
diff --git a/src/test/conf_examples/bug_31495_1/torrc b/src/test/conf_examples/bug_31495_1/torrc
new file mode 100644
index 0000000000..ed6cccab3f
--- /dev/null
+++ b/src/test/conf_examples/bug_31495_1/torrc
@@ -0,0 +1,2 @@
+UseBridges 1
+Bridge 127.0.0.1:9050 \ No newline at end of file
diff --git a/src/test/conf_examples/bug_31495_2/error b/src/test/conf_examples/bug_31495_2/error
new file mode 100644
index 0000000000..1417806c60
--- /dev/null
+++ b/src/test/conf_examples/bug_31495_2/error
@@ -0,0 +1 @@
+Failed to parse/validate config: You cannot set both UseBridges and EntryNodes. \ No newline at end of file
diff --git a/src/test/conf_examples/bug_31495_2/torrc b/src/test/conf_examples/bug_31495_2/torrc
new file mode 100644
index 0000000000..f629fff673
--- /dev/null
+++ b/src/test/conf_examples/bug_31495_2/torrc
@@ -0,0 +1,3 @@
+UseBridges 1
+Bridge 127.0.0.1:9050
+EntryNodes 127.0.0.1 \ No newline at end of file
diff --git a/src/test/conf_examples/bug_31495_3/cmdline b/src/test/conf_examples/bug_31495_3/cmdline
new file mode 100644
index 0000000000..478c1abe74
--- /dev/null
+++ b/src/test/conf_examples/bug_31495_3/cmdline
@@ -0,0 +1 @@
+/EntryNodes \ No newline at end of file
diff --git a/src/test/conf_examples/bug_31495_3/expected b/src/test/conf_examples/bug_31495_3/expected
new file mode 100644
index 0000000000..246347b668
--- /dev/null
+++ b/src/test/conf_examples/bug_31495_3/expected
@@ -0,0 +1,2 @@
+Bridge 127.0.0.1:9050
+UseBridges 1
diff --git a/src/test/conf_examples/bug_31495_3/expected_log b/src/test/conf_examples/bug_31495_3/expected_log
new file mode 100644
index 0000000000..a4b98345d6
--- /dev/null
+++ b/src/test/conf_examples/bug_31495_3/expected_log
@@ -0,0 +1 @@
+Configuration was valid \ No newline at end of file
diff --git a/src/test/conf_examples/bug_31495_3/torrc b/src/test/conf_examples/bug_31495_3/torrc
new file mode 100644
index 0000000000..f629fff673
--- /dev/null
+++ b/src/test/conf_examples/bug_31495_3/torrc
@@ -0,0 +1,3 @@
+UseBridges 1
+Bridge 127.0.0.1:9050
+EntryNodes 127.0.0.1 \ No newline at end of file
diff --git a/src/test/conf_examples/crypto_accel/expected_log_nss b/src/test/conf_examples/crypto_accel/expected_log_nss
index c0fe7b003c..bcbfa2cf6b 100644
--- a/src/test/conf_examples/crypto_accel/expected_log_nss
+++ b/src/test/conf_examples/crypto_accel/expected_log_nss
@@ -1 +1 @@
-Tor 0.* running on .* with Libevent .*, NSS .*, Zlib .*, Liblzma .*, and Libzstd .*
+Tor 0.* running on .* with Libevent .*, NSS .*, Zlib .*, Liblzma .*, Libzstd .* and .* .* as libc
diff --git a/src/test/conf_examples/crypto_accel_req/expected_log_nss b/src/test/conf_examples/crypto_accel_req/expected_log_nss
index c0fe7b003c..bcbfa2cf6b 100644
--- a/src/test/conf_examples/crypto_accel_req/expected_log_nss
+++ b/src/test/conf_examples/crypto_accel_req/expected_log_nss
@@ -1 +1 @@
-Tor 0.* running on .* with Libevent .*, NSS .*, Zlib .*, Liblzma .*, and Libzstd .*
+Tor 0.* running on .* with Libevent .*, NSS .*, Zlib .*, Liblzma .*, Libzstd .* and .* .* as libc
diff --git a/src/test/conf_examples/dirauth_3/error_no_dirauth b/src/test/conf_examples/dirauth_3/error_no_dirauth
new file mode 100644
index 0000000000..e6bd5db69c
--- /dev/null
+++ b/src/test/conf_examples/dirauth_3/error_no_dirauth
@@ -0,0 +1 @@
+This tor was built with dirauth mode disabled.
diff --git a/src/test/conf_examples/dirauth_3/error_no_dirauth_relay b/src/test/conf_examples/dirauth_3/error_no_dirauth_relay
new file mode 100644
index 0000000000..e6bd5db69c
--- /dev/null
+++ b/src/test/conf_examples/dirauth_3/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with dirauth mode disabled.
diff --git a/src/test/conf_examples/dirauth_3/expected b/src/test/conf_examples/dirauth_3/expected
new file mode 100644
index 0000000000..23eac3a5f8
--- /dev/null
+++ b/src/test/conf_examples/dirauth_3/expected
@@ -0,0 +1,9 @@
+Address 192.0.2.1
+AuthoritativeDirectory 1
+ContactInfo tor_parse_test@example.net
+DirPort 192.0.2.1:2
+DownloadExtraInfo 1
+Nickname Unnamed
+ORPort 192.0.2.1:1
+ORPort [2001:DB8::1]:3
+V3AuthoritativeDirectory 1
diff --git a/src/test/conf_examples/dirauth_3/expected_log b/src/test/conf_examples/dirauth_3/expected_log
new file mode 100644
index 0000000000..3127c9b125
--- /dev/null
+++ b/src/test/conf_examples/dirauth_3/expected_log
@@ -0,0 +1 @@
+Read configuration file .*dirauth_3[./]*torrc
diff --git a/src/test/conf_examples/dirauth_3/torrc b/src/test/conf_examples/dirauth_3/torrc
new file mode 100644
index 0000000000..9663a9bc0c
--- /dev/null
+++ b/src/test/conf_examples/dirauth_3/torrc
@@ -0,0 +1,13 @@
+# Authority with IPv6 address
+
+AuthoritativeDirectory 1
+V3AuthoritativeDirectory 1
+
+ContactInfo tor_parse_test@example.net
+
+Address 192.0.2.1
+
+ORPort 192.0.2.1:1
+DirPort 192.0.2.1:2
+
+ORPort [2001:DB8::1]:3
diff --git a/src/test/conf_examples/large_1/expected b/src/test/conf_examples/large_1/expected
index 99a12ffc84..fcd19db3df 100644
--- a/src/test/conf_examples/large_1/expected
+++ b/src/test/conf_examples/large_1/expected
@@ -3,7 +3,6 @@ AccountingRule sum
AccountingStart day 05:15
Address 128.66.8.8
AllowNonRFC953Hostnames 1
-AndroidIdentityTag droidy
AutomapHostsOnResolve 1
AutomapHostsSuffixes .onions
AvoidDiskWrites 1
@@ -111,7 +110,6 @@ NumDirectoryGuards 4
NumEntryGuards 5
NumPrimaryGuards 8
OfflineMasterKey 1
-OptimisticData 1
ORPort 2222
OutboundBindAddress 10.0.0.7
OutboundBindAddressExit 10.0.0.8
diff --git a/src/test/conf_examples/large_1/expected_no_dirauth b/src/test/conf_examples/large_1/expected_no_dirauth
index 26a33bdc7c..4a19bc546c 100644
--- a/src/test/conf_examples/large_1/expected_no_dirauth
+++ b/src/test/conf_examples/large_1/expected_no_dirauth
@@ -3,7 +3,6 @@ AccountingRule sum
AccountingStart day 05:15
Address 128.66.8.8
AllowNonRFC953Hostnames 1
-AndroidIdentityTag droidy
AutomapHostsOnResolve 1
AutomapHostsSuffixes .onions
AvoidDiskWrites 1
@@ -110,7 +109,6 @@ NumDirectoryGuards 4
NumEntryGuards 5
NumPrimaryGuards 8
OfflineMasterKey 1
-OptimisticData 1
ORPort 2222
OutboundBindAddress 10.0.0.7
OutboundBindAddressExit 10.0.0.8
diff --git a/src/test/conf_examples/large_1/torrc b/src/test/conf_examples/large_1/torrc
index 20ddf00e16..3f5b1e179f 100644
--- a/src/test/conf_examples/large_1/torrc
+++ b/src/test/conf_examples/large_1/torrc
@@ -3,7 +3,6 @@ AccountingRule sum
AccountingStart day 05:15
Address 128.66.8.8
AllowNonRFC953Hostnames 1
-AndroidIdentityTag droidy
AutomapHostsOnResolve 1
AutomapHostsSuffixes .onions
AvoidDiskWrites 1
diff --git a/src/test/conf_examples/lzma_zstd_1/expected_log b/src/test/conf_examples/lzma_zstd_1/expected_log
index a5531ca21e..f143b23102 100644
--- a/src/test/conf_examples/lzma_zstd_1/expected_log
+++ b/src/test/conf_examples/lzma_zstd_1/expected_log
@@ -1 +1 @@
-Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma N/A, and Libzstd N/A
+Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma N/A, Libzstd N/A and .* .* as libc
diff --git a/src/test/conf_examples/lzma_zstd_1/expected_log_lzma b/src/test/conf_examples/lzma_zstd_1/expected_log_lzma
index 2947e5991b..abb4731abc 100644
--- a/src/test/conf_examples/lzma_zstd_1/expected_log_lzma
+++ b/src/test/conf_examples/lzma_zstd_1/expected_log_lzma
@@ -1 +1 @@
-Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma .*, and Libzstd N/A
+Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma .*, Libzstd N/A and .* .* as libc
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
index e76e4357f8..b4e45772dd 100644
--- a/src/test/conf_examples/lzma_zstd_1/expected_log_lzma_zstd
+++ b/src/test/conf_examples/lzma_zstd_1/expected_log_lzma_zstd
@@ -1 +1 @@
-Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma .*, and Libzstd .* \ No newline at end of file
+Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma .*, Libzstd .* and .* .* as libc \ 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
index c8b174423b..994b46974b 100644
--- a/src/test/conf_examples/lzma_zstd_1/expected_log_zstd
+++ b/src/test/conf_examples/lzma_zstd_1/expected_log_zstd
@@ -1 +1 @@
-Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma N/A, and Libzstd .* \ No newline at end of file
+Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma N/A, Libzstd .* and .* .* as libc \ No newline at end of file
diff --git a/src/test/conf_examples/multiple_routerset_1/expected b/src/test/conf_examples/multiple_routerset_1/expected
new file mode 100644
index 0000000000..9087aaff06
--- /dev/null
+++ b/src/test/conf_examples/multiple_routerset_1/expected
@@ -0,0 +1 @@
+EntryNodes 127.0.0.1,127.0.0.2,127.0.0.3
diff --git a/src/test/conf_examples/multiple_routerset_1/expected_log b/src/test/conf_examples/multiple_routerset_1/expected_log
new file mode 100644
index 0000000000..a4b98345d6
--- /dev/null
+++ b/src/test/conf_examples/multiple_routerset_1/expected_log
@@ -0,0 +1 @@
+Configuration was valid \ No newline at end of file
diff --git a/src/test/conf_examples/multiple_routerset_1/torrc b/src/test/conf_examples/multiple_routerset_1/torrc
new file mode 100644
index 0000000000..44978e4b38
--- /dev/null
+++ b/src/test/conf_examples/multiple_routerset_1/torrc
@@ -0,0 +1,2 @@
+EntryNodes 127.0.0.1
+EntryNodes 127.0.0.2,127.0.0.3 \ No newline at end of file
diff --git a/src/test/conf_examples/multiple_routerset_2/cmdline b/src/test/conf_examples/multiple_routerset_2/cmdline
new file mode 100644
index 0000000000..d6e7970e53
--- /dev/null
+++ b/src/test/conf_examples/multiple_routerset_2/cmdline
@@ -0,0 +1 @@
+EntryNodes 127.0.0.4 \ No newline at end of file
diff --git a/src/test/conf_examples/multiple_routerset_2/expected b/src/test/conf_examples/multiple_routerset_2/expected
new file mode 100644
index 0000000000..34c893df79
--- /dev/null
+++ b/src/test/conf_examples/multiple_routerset_2/expected
@@ -0,0 +1 @@
+EntryNodes 127.0.0.4
diff --git a/src/test/conf_examples/multiple_routerset_2/expected_log b/src/test/conf_examples/multiple_routerset_2/expected_log
new file mode 100644
index 0000000000..a4b98345d6
--- /dev/null
+++ b/src/test/conf_examples/multiple_routerset_2/expected_log
@@ -0,0 +1 @@
+Configuration was valid \ No newline at end of file
diff --git a/src/test/conf_examples/multiple_routerset_2/torrc b/src/test/conf_examples/multiple_routerset_2/torrc
new file mode 100644
index 0000000000..44978e4b38
--- /dev/null
+++ b/src/test/conf_examples/multiple_routerset_2/torrc
@@ -0,0 +1,2 @@
+EntryNodes 127.0.0.1
+EntryNodes 127.0.0.2,127.0.0.3 \ No newline at end of file
diff --git a/src/test/conf_examples/multiple_routerset_3/cmdline b/src/test/conf_examples/multiple_routerset_3/cmdline
new file mode 100644
index 0000000000..425f383bc3
--- /dev/null
+++ b/src/test/conf_examples/multiple_routerset_3/cmdline
@@ -0,0 +1 @@
++EntryNodes 127.0.0.4 \ No newline at end of file
diff --git a/src/test/conf_examples/multiple_routerset_3/expected b/src/test/conf_examples/multiple_routerset_3/expected
new file mode 100644
index 0000000000..196b4814f8
--- /dev/null
+++ b/src/test/conf_examples/multiple_routerset_3/expected
@@ -0,0 +1 @@
+EntryNodes 127.0.0.1,127.0.0.2,127.0.0.3,127.0.0.4
diff --git a/src/test/conf_examples/multiple_routerset_3/expected_log b/src/test/conf_examples/multiple_routerset_3/expected_log
new file mode 100644
index 0000000000..a4b98345d6
--- /dev/null
+++ b/src/test/conf_examples/multiple_routerset_3/expected_log
@@ -0,0 +1 @@
+Configuration was valid \ No newline at end of file
diff --git a/src/test/conf_examples/multiple_routerset_3/torrc b/src/test/conf_examples/multiple_routerset_3/torrc
new file mode 100644
index 0000000000..44978e4b38
--- /dev/null
+++ b/src/test/conf_examples/multiple_routerset_3/torrc
@@ -0,0 +1,2 @@
+EntryNodes 127.0.0.1
+EntryNodes 127.0.0.2,127.0.0.3 \ No newline at end of file
diff --git a/src/test/conf_examples/multiple_routerset_4/cmdline b/src/test/conf_examples/multiple_routerset_4/cmdline
new file mode 100644
index 0000000000..478c1abe74
--- /dev/null
+++ b/src/test/conf_examples/multiple_routerset_4/cmdline
@@ -0,0 +1 @@
+/EntryNodes \ No newline at end of file
diff --git a/src/test/conf_examples/multiple_routerset_4/expected b/src/test/conf_examples/multiple_routerset_4/expected
new file mode 100644
index 0000000000..bc790c86e3
--- /dev/null
+++ b/src/test/conf_examples/multiple_routerset_4/expected
@@ -0,0 +1 @@
+ControlSocket 1234
diff --git a/src/test/conf_examples/multiple_routerset_4/expected_log b/src/test/conf_examples/multiple_routerset_4/expected_log
new file mode 100644
index 0000000000..a4b98345d6
--- /dev/null
+++ b/src/test/conf_examples/multiple_routerset_4/expected_log
@@ -0,0 +1 @@
+Configuration was valid \ No newline at end of file
diff --git a/src/test/conf_examples/multiple_routerset_4/torrc b/src/test/conf_examples/multiple_routerset_4/torrc
new file mode 100644
index 0000000000..dad8cb694e
--- /dev/null
+++ b/src/test/conf_examples/multiple_routerset_4/torrc
@@ -0,0 +1,3 @@
+ControlSocket 1234 # dummy to prevent empty output
+EntryNodes 127.0.0.1
+EntryNodes 127.0.0.2,127.0.0.3 \ No newline at end of file
diff --git a/src/test/conf_examples/nss_1/expected_log b/src/test/conf_examples/nss_1/expected_log
index 32e8cfc2f8..38f1febda5 100644
--- a/src/test/conf_examples/nss_1/expected_log
+++ b/src/test/conf_examples/nss_1/expected_log
@@ -1 +1 @@
-Tor 0.* running on .* with Libevent .*, OpenSSL .*, Zlib .*, Liblzma .*, and Libzstd .*
+Tor 0.* running on .* with Libevent .*, OpenSSL .*, Zlib .*, Liblzma .*, Libzstd .* and .* .* as libc
diff --git a/src/test/conf_examples/nss_1/expected_log_nss b/src/test/conf_examples/nss_1/expected_log_nss
index c0fe7b003c..bcbfa2cf6b 100644
--- a/src/test/conf_examples/nss_1/expected_log_nss
+++ b/src/test/conf_examples/nss_1/expected_log_nss
@@ -1 +1 @@
-Tor 0.* running on .* with Libevent .*, NSS .*, Zlib .*, Liblzma .*, and Libzstd .*
+Tor 0.* running on .* with Libevent .*, NSS .*, Zlib .*, Liblzma .*, Libzstd .* and .* .* as libc
diff --git a/src/test/ed25519_exts_ref.py b/src/test/ed25519_exts_ref.py
index ae537ff15b..dcc0a7c25a 100644
--- a/src/test/ed25519_exts_ref.py
+++ b/src/test/ed25519_exts_ref.py
@@ -53,7 +53,7 @@ def blindPK(pk, param):
def expandSK(sk):
h = H(sk)
a = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2))
- k = ''.join([h[i] for i in range(b/8,b/4)])
+ k = bytes(h[i] for i in range(b//8,b//4))
assert len(k) == 32
return encodeint(a)+k
@@ -64,7 +64,7 @@ def publickeyFromESK(h):
def signatureWithESK(m,h,pk):
a = decodeint(h[:32])
- r = Hint(''.join([h[i] for i in range(b/8,b/4)]) + m)
+ r = Hint(bytes([h[i] for i in range(b//8,b//4)]) + m)
R = scalarmult(B,r)
S = (r + Hint(encodepoint(R) + pk + m) * a) % l
return encodepoint(R) + encodeint(S)
@@ -263,5 +263,3 @@ if __name__ == '__main__':
unittest.main()
else:
makeTestVectors()
-
-
diff --git a/src/test/example_extrainfo.inc b/src/test/example_extrainfo.inc
index 0bf2341ef5..94708e6812 100644
--- a/src/test/example_extrainfo.inc
+++ b/src/test/example_extrainfo.inc
@@ -1,25 +1,42 @@
+/* These entries are automatically generated by makedesc.py to make sure
+ * that their keys and signatures are right except when otherwise
+ * specified. */
+
static const char EX_EI_MINIMAL[] =
- "extra-info bob 3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B\n"
- "published 2014-10-05 20:07:00\n"
+ "extra-info HomersRelay 3390094906366A15D5CD78550424FAD141CF1067\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstTAd17tFTNejNRgbv721EkIcbFOsiQYWMvXPIwupcMVOSRAQAgBABG7Eha\n"
+ "cQElmfndkTBiOJBk18P4nP6BtRWGhYEz9th4chXWqOuA+/8IfLPYb39YuFUOadAE\n"
+ "cgKPEa14EHB7K5QbGToAm91E0H5kVX6A9GDAc7QKKMYLGO4Tcu2WntzSmgY=\n"
+ "-----END ED25519 CERT-----\n"
+ "published 2020-10-14 20:58:04\n"
+ "router-sig-ed25519 3c5gw2tHzcjS0zKSdZrL2Mx3pdEe2j8Gc62nQWKl8m2DLhWqrTz9dC6LimoiipWuV0Xo8tT2f/fStMBGbayRAQ\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "K5GAkVjpUlofL78NIOE1VDxFn8yYbHK50rVuZG2HxqG/727bon+uMprv4MHjfDcP\n"
- "V3l9u1uUdGiUPOl8j+hRNw4z/ODeCj/24r2+L32MTjyfUhK49Ld2IlK9iZKlgKYi\n"
- "zyoatxdAjU8Xc5WPX692HO4/R9CGLsUfYcEEFU2R3EA=\n"
+ "tcFC3oRyHAaZTQn0g5G5rsjq3CI9Ky/GlhIQz1G5VWczjTXIb0fGGyerraq5HW7v\n"
+ "UEDQrA3dYjuFB3ACyKesoR9HbMSVOPSHkge4WWtlm9XoPzgU6IGWPhlnWjYC9ozV\n"
+ "2m8J8Gx+3IUy4xWWIDOXLV0Wlp6PWwXbYHWllHQLjKM=\n"
"-----END SIGNATURE-----\n"
;
-
-static const char EX_EI_MINIMAL_FP[] = "3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B";
+ATTR_UNUSED static const char EX_EI_MINIMAL_FP[] = "3390094906366A15D5CD78550424FAD141CF1067";
+ATTR_UNUSED
static const char EX_EI_MINIMAL_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBALSppIF3t3wOAm4fzxRvK+q/wh1gGAWwS0JEn8d+c/x+rt1oQabGkqsB\n"
- "GU6rz1z1AN02W0P2+EcyJQVBjGR3gHQNoDGx0KIdnr3caGAw3XmQXrJLPaViEk28\n"
- "RJMxx6umpP27YKSyEMHgVTDXblKImT0mE7fVOx8tD0EWRYazmp4NAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n";
-
+ "MIGJAoGBANNVP8AEuktLfk1QmK5SYrfPF9KBxub5dubqaPGMGEHwtOpR8Mo8ZfKZ\n"
+ "bi3nmpO273uVZDz0toqgcI9v87x6v/2ZPaksRcFXl2vVdJ2L8R51yvr6EjhatEi/\n"
+ "ntPRQ67oSEA9sqeI4R1NRcrfEpzLyBOGZ/SHsctGX+9edZGZVpkrAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ ;
static const char EX_EI_MAXIMAL[] =
- "extra-info bob FF8248FE780A7236D3FA5D62DEA642055135F942\n"
- "published 2014-10-05 20:07:00\n"
+ "extra-info HomersRelay 7369E5BE5E183609D08A766F6FF36F9F5DE2AD32\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstTAY8EcZ8LbMYKiBCrVu1KMM1b0nM5amNOdjzblJezWiJSAQAgBABdtyfT\n"
+ "YOvrB4cdPm0k7IoyXzVi3qYFtr82nshImKJ/tGO8H7DhU7s+7lsOKInn4RVaUS1/\n"
+ "r2Z05Qb7lj9q/jhVnruoiG/N6Ii0rjWuRZmmR7sZdCpAGzJoRx0hO1vshAU=\n"
+ "-----END ED25519 CERT-----\n"
+ "published 2020-10-14 20:58:04\n"
"opt foobarbaz\n"
"read-history 900 1,2,3\n"
"write-history 900 1,2,3\n"
@@ -46,390 +63,322 @@ static const char EX_EI_MAXIMAL[] =
"exit-kibibytes-written FOO\n"
"exit-kibibytes-read FOO\n"
"exit-streams-opened FOO\n"
+ "router-sig-ed25519 JKJB3EvFZUOff5RgwgSowwTB/TP6VB+IbbeqGPA0Mp9ft9KiulgCuoWqGiUdu/1Zm02dSdYWIlKNf2AijTy0Cg\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "ZO79bLlWVNIruCnWW9duDcOKydPWbL5DfrpUv5IRLF4MMFoacMUdJPDUs9e+wY2C\n"
- "zndHe6i2JK7yKJj+uCOSC8cx61OLG+kVxMLJ/qhA4H5thrYb+GpzMKwbHzQc3PTH\n"
- "zHRzj041iWXTL7/DMaQlpJOBoac/wTSIKzoV2B00jBw=\n"
+ "rk8hYNILFc+Ka3a8vyVg3O4Qs5++ih5KmCP1f/onm++fUM/kGCA13KP3hF0conRH\n"
+ "bTdDas6PJALVgNq1bWsCbuqtz2eIf8r22+gE5nRuahh5u0JLzJzEXeZo/jpHQDAM\n"
+ "ZbMqs2SOKQk8QmGyUa+ul89FR9El0mBE8dMPwYnWl14=\n"
"-----END SIGNATURE-----\n"
;
-
-static const char EX_EI_MAXIMAL_FP[] = "FF8248FE780A7236D3FA5D62DEA642055135F942";
+ATTR_UNUSED static const char EX_EI_MAXIMAL_FP[] = "7369E5BE5E183609D08A766F6FF36F9F5DE2AD32";
+ATTR_UNUSED
static const char EX_EI_MAXIMAL_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANSpkYhHUW1EqodY4d3JRbvEM1vjjR/vEE8gjONiJ5t2Sten53jzt8bh\n"
- "8/VJn7pQGs8zR5CIxCw4P68xMtZJJedS3hhjqubheOE/yW1DtpkiCf+zVEaLpeA8\n"
- "fYQChkRICnR/BZd4W9bbohLVII5ym2PaJt2ihB3FeVZIsGXm4wxhAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n";
-
+ "MIGJAoGBAMJ9qPjQ0i7LGsRDIBJw+gMZLx1rYNCmu0KPSf7BixQP1Tk7u8TVL+/O\n"
+ "jmzOP8L2etdsl5ousnDjulXbxF3wn5pU1+d35XxkfUbcuYzKc90SwYsXp0HOdH0q\n"
+ "XdKofHK0TyTfWknBp9JId1r6lmjR2Sk+o88yES05NS95evaRkX2/AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ ;
static const char EX_EI_BAD_SIG1[] =
- "extra-info bob 3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B\n"
- "published 2014-10-05 20:07:00\n"
+ "extra-info HomersRelay 2F6C040BC5154D4A0F5BDFC1D6560EBD33B735C7\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstTAQhl8HDHWPB6RgLDaVIHfzcJ0CKg6wZINNChtW8QyAacAQAgBAA0yzGH\n"
+ "Ny+LC1czePmvy4QZMKgiyWIhrqqtT5cYgTnnF+oBcVpKEYkEvl/z2/bOTcIFW46U\n"
+ "wqGWJkQxqMbrxYKRo3dspN5Z7E1E8inkI3+oAv2rn4Xj+ZG7lWTwwuw97wc=\n"
+ "-----END ED25519 CERT-----\n"
+ "published 2020-10-14 20:58:04\n"
+ "router-sig-ed25519 1O2wsG/FhFdr117eNcqlB0RSJy5G4ExPCSAS8VG5yDirv6SepYLn99ppqGDH80WtOTc1+LzwZYkQ8tyko1vYAw\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "K5GAkVjpUlofL78NIOE1VDxFn8yYbHK50rVuZG2HxqG/727bon+uMprv4MHjfDcP\n"
"V3l9u1uUdGiUPOl8j+hXXw4z/ODeCj/24r2+L32MTjyfUhK49Ld2IlK9iZKlgKYi\n"
"zyoatxdAjU8Xc5WPX692HO4/R9CGLsUfYcEEFU2R3EA=\n"
"-----END SIGNATURE-----\n"
;
-
-static const char EX_EI_BAD_SIG2[] =
- "extra-info bob 3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B\n"
- "published 2014-10-06 20:07:00\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "K5GAkVjpUlofL78NIOE1VDxFn8yYbHK50rVuZG2HxqG/727bon+uMprv4MHjfDcP\n"
- "V3l9u1uUdGiUPOl8j+hRNw4z/ODeCj/24r2+L32MTjyfUhK49Ld2IlK9iZKlgKYi\n"
- "zyoatxdAjU8Xc5WPX692HO4/R9CGLsUfYcEEFU2R3EA=\n"
- "-----END SIGNATURE-----\n"
- ;
-
-static const char EX_EI_BAD_SIG3[] =
- "extra-info bob 3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B\n"
- "published 2014-10-05 20:07:00\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "K5GAkVjpUlofL78NIOE1VDxFn8yYbHK50rVuZG2HxqG/727bon+uMprv4MHjfDcP\n"
- "V3l9u1uUdGiUPOl8j+hRNw4z/ODeCj/24r2+L32MTjyfUhK49Ld2IlK9iZKlgKYi\n"
- "zyoatxdAjU8Xc5WPX692HO4/R9CGLsUfYcEEFU2=\n"
- "-----END SIGNATURE-----\n"
+ATTR_UNUSED static const char EX_EI_BAD_SIG1_FP[] = "2F6C040BC5154D4A0F5BDFC1D6560EBD33B735C7";
+ATTR_UNUSED
+static const char EX_EI_BAD_SIG1_KEY[] =
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKN5UTDCnsKYmUa2kORmJZUbpNv+dn66Fy4tj3x4rwFHKp7MOlgwK0Zj\n"
+ "C4dh77PUXRvnqM0yb3hDCiVJ9XsMbql8JCO8KrMoCoBvKXCVud30/gCY7G0Nf+Py\n"
+ "Z8j1NnOmKLuXnvX5saLtFKLEgAGMf/JTUExWmTAWKk0Ax9rQjVtVAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
;
-
-static const char EX_EI_BAD_FP[] =
- "extra-info bob C34293303F0F1E42CB14E593717B834E8E53797D8888\n"
- "published 2014-10-05 20:07:00\n"
+static const char EX_EI_BAD_SIG2[] =
+ "extra-info HomersRelay 292CB24DC90BEB8210E33B54F63271ED4034ABF9\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstTAS/RMEB+g3lPq9f9/tSb67KQWzKS1B8ujutOZv0byqpyAQAgBABZsEqr\n"
+ "UbN2SrNDRAIWkC7EL8hpUJOCbIRYKRuQ9HQFDrIM8ZI7h542JOKJexNOQmiZA5Ut\n"
+ "cWa/cJvraK48DChLlOZq62S2fNpX43pTktDVV6WqGp/P8IJwT+l6zBqFZQQ=\n"
+ "-----END ED25519 CERT-----\n"
+ "published 2020-10-14 20:58:04\n"
+ "router-sig-ed25519 XFBQj7H4bitpx5Bq9c0Od7dO4qiZKDHbeLGeV4FP+SsGfpft2VvY8/V0oHx2z2Sl3938MIfNxQMjBQ+EtHrdYDA\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "IDA8ryUYeMx7+Au/xQmX7Y8fXksoHUOXmePND2JYM4rPfishQJ1LpQ15KrolOZDH\n"
- "FVIk3RmCefNlJeS1/UgWPcU8u2nGw1YQuRBHF4ViTmZ0OevI1pTsSApl4+oIx2dy\n"
- "DGgCQmKfMbaOixIK8Ioh1Z2NUfMkjbUUE2WWgFTAsac=\n"
+ "sb8tYPSeSmaTEUpu7v374PVPEoYqTbIpaHezqbC/PfldVenXRLkoB893hP72IJQZ\n"
+ "ru9go6Kc6LuobMuVtpwey8nsPqhu8WZn3E4pSL8lCXosttvxtZnDD7/Fu6Ddj05A\n"
+ "ehZpDi2oyBVdR0b5JI7a+m6/j5snn0TTjbGmHHnDPY0=\n"
"-----END SIGNATURE-----\n"
;
-
-static const char EX_EI_BAD_FP_FP[] = "C34293303F0F1E42CB14E593717B834E8E53797D";
-static const char EX_EI_BAD_FP_KEY[] =
+ATTR_UNUSED static const char EX_EI_BAD_SIG2_FP[] = "292CB24DC90BEB8210E33B54F63271ED4034ABF9";
+ATTR_UNUSED
+static const char EX_EI_BAD_SIG2_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAKXMSbif4fG+BW/5lIq5V1tMRondIUfKiNizp0E6EcBw5LvYfQV6zrj8\n"
- "HmMFbB/WGf9XGVMxIBzxzeQBRvCQJh+0QH7+ju5/isIHJZsACMILepr6ywmCcjVU\n"
- "iYRtC8zGQLqfkf2cNoo7AhcI5i/YzyW2u1zmbPX5J+8sUErfxydbAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n";
-
+ "MIGJAoGBAM3PF/tml0dOEm53J54liJStfBBlK8cgYhApmm9NMDxqK1DssZBIL4v7\n"
+ "6KTx4yTr9U/rIBHF/0rISy9l86J38eT4twFxuIGcFtGSEFnUgp21uVysev+svQdW\n"
+ "s+RrFLkPu0Wus9v72f7QeAdFA2GKQmZnybsvRhLiGfomQls062wDAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ ;
static const char EX_EI_BAD_NICKNAME[] =
- "extra-info bobhasaverylongnameandidontthinkweshouldlethim A4EA2389A52459B3F7C7121A46012F098BDFC2A4\n"
- "published 2014-10-05 20:07:00\n"
+ "extra-info bobhasaverylongnameandidontthinkweshouldlethim AB6C1ABB2A8F6D48ABE641912C8829F686BC6A9D\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstTAdi62xiknL6gvZDhCF37r7jL281WUDop4iImEX8bTeSYAQAgBAAfBLo2\n"
+ "i4Yuo3t/HGACeJZoHvVww8HTJq4NyDH5HBdU594t+qpdy/3rlQDsZFxTdh6nYV27\n"
+ "F6aZ6ZkgUSKW//XfX9Vn2xCSGhhwM2kkbWPQCelHAeVUwkCmScz4/rWo0wg=\n"
+ "-----END ED25519 CERT-----\n"
+ "published 2020-10-14 20:58:04\n"
+ "router-sig-ed25519 2YBjWS4B6+ZmLDt7DXxyckF/RgAu9PnaVgpJQTEbrogAjyeoiOplwzx86nc1YtxggCde1KsqicqsYENa+kgiCA\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "e2wLJFThRMGawxKrQPuH2XCLek/LJsg4XOB8waAjE0xdHOrzjur9x1jIxy7DVU6t\n"
- "z1edbIoL24qucMJvFy2xjSQhFRX4OsyNc0nWr3LfJnTW9aEmxuwXM+mltUD2uFN1\n"
- "2vYOIQjUmJwS2yfeSKnhXEl2PWVUmgzYL3r4S5kHco4=\n"
+ "YiYQB9RBEDxJf729Qgil/pzRqKNR5hsvTD3ODN2IcF/hbwKTtjURCTQYBDXAIB1q\n"
+ "mRpS1R+Rxcp6ta2kfKv5xeuDTcoYcCLeee6Cwivq8/JHhoqQcndG+2Bh8WUGPrRN\n"
+ "8X2AKAVVy/OF+/AZmTAhvWqYfJEZ9HaKEj+k8Ot/u5w=\n"
"-----END SIGNATURE-----\n"
;
-
-static const char EX_EI_BAD_NICKNAME_FP[] = "A4EA2389A52459B3F7C7121A46012F098BDFC2A4";
+ATTR_UNUSED static const char EX_EI_BAD_NICKNAME_FP[] = "AB6C1ABB2A8F6D48ABE641912C8829F686BC6A9D";
+ATTR_UNUSED
static const char EX_EI_BAD_NICKNAME_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAKfq7oxD1kMu1+zeG2UVXN4vOu6FDp0V/olA3ttmXpUCgCiBxWTgtwNl\n"
- "nPf0HcKMaCp/0D9XrbhvIoOsg0OTf1TcJfGsA/zPG7jrWYa4xhD50KYvty9EINK9\n"
- "/UBWNSyXCFDMqnddb/LZ8+VgttmxfYkpeRzSSmDijN3RbOvYJhhBAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n";
-
+ "MIGJAoGBAMhug5Yec6r7TIViU3V4BeGGIckfWDVS1ewrhWe/mK5JP2jWZ8JJov7v\n"
+ "Wc2WArhMWYm8idmA+QwFKMmywdfkwc4jHu2jTcIFxTxl2zjFddThSgMgIGXtaBwc\n"
+ "Rn4kuIAG8PekuNNL903rol5OakE6EUvLmJcMYB3rO4W8C6oMhvalAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ ;
static const char EX_EI_BAD_TOKENS[] =
- "extra-info bob 6F314FB01A31162BD5E473D4977AC570DC5B86BB\n"
- "published 2014-10-05 20:07:00\n"
- "published 2014-10-05 20:07:00\n"
+ "extra-info HomersRelay 50AF9F6CE4107055260137181DEA24095D292F81\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstTAfELNKA/8+s09sVWDRCVk0hfX3+ysqp2vFE6atiPZ4hGAQAgBADVXm9g\n"
+ "BXoEjAjHvPwNPaZmrtjYTIc4ssiqud7/XKN1R1Ys+yJuZv23pJrGktXHiNBPI3UX\n"
+ "JOfbtNtw8depsxsDa232u1ZSLWCQ6LtaoalyT/mqs47ASSyYwcvgauWPYQY=\n"
+ "-----END ED25519 CERT-----\n"
+ "published 2020-10-14 20:58:04\n"
+ "published 2020-10-14 20:58:04\n"
+ "router-sig-ed25519 8ggCNPsFzbfbILBVpiKRlUqEaATq5F17Xo+5op/aoPPhp0pCmucYpl0aGX0hbJCGAOjShBmX362ARmpBBDoADQ\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "lhRIafrkKoQmnUoBLiq4XC8XKXrleGJZ5vefkLcgjOJ5IffsvVdIA7Vqq/ISbPrG\n"
- "b/Zs0sJNL6naHPxJBglgHJqksSyiYHaeOetXg2Rb+vZ1v2S5BrVgk1nPMDhyIzqc\n"
- "zU7eCxFf/1sXKtWlEKxGdX4LmVfnIln5aI31Bc4xRrE=\n"
+ "LW/DIzbGzTmvvr/wKQo41utHqwAbHvrtF/X4wCQ0Db4GDHgDlac2gtzhz++X8Rrh\n"
+ "fiLBdby4omYP/uPkk9pTwvNaSHpsE17zCWrg6re7lUfgq/mJ7VB8eRGzd8NIELEQ\n"
+ "gBK/DQ9oF4yHHRTbNRusUBwtU/UB8wNdkvTYAVw9VWw=\n"
"-----END SIGNATURE-----\n"
;
-
-static const char EX_EI_BAD_TOKENS_FP[] =
- "6F314FB01A31162BD5E473D4977AC570DC5B86BB";
+ATTR_UNUSED static const char EX_EI_BAD_TOKENS_FP[] = "50AF9F6CE4107055260137181DEA24095D292F81";
+ATTR_UNUSED
static const char EX_EI_BAD_TOKENS_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAL7Z8tz45Tb4tnEFS2sAyjubBV/giSfZdmXRkDV8Jo4xqWqhWFJn7+zN\n"
- "AXBWBThGeVH2WXrpz5seNJXgZJPxMTMsrnSCGcRXZw0Npti2MkLuQ6+prZa+OPwE\n"
- "OyC6jivtAaY/o9iYQjDC2avLXD3N4LvoygyF418KnNcjbzuFygffAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n";
-
+ "MIGJAoGBAMOlFKzgAdxLVePfB0epCUtq3v4vVptYdQNLpqtjhNVZaNwrYKcyO6Wd\n"
+ "115iHgAwbeh7Eva0qb/S3F1KKspiCoTNC2O54Yn8i3kIWfWXjDsdWEJ/CtOZumwH\n"
+ "DbcAQuczG0D8nTxxn42+QaoHFzTMo1sJ2c91qY7OV7kWYqMB++2VAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ ;
static const char EX_EI_BAD_START[] =
- "published 2014-10-05 20:07:00\n"
- "extra-info bob 5CCCACE71A9BDB5E8E0C942AB3407452350434C0\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstTAT5Axv+qhd0NtmmMe+AXThBG1h3cs559MPKDxbV5Y5TzAQAgBABOa2zh\n"
+ "7y8bgCx3/uQCJ+v9kxNGZDQu+soUPbXyd7OZEaUE/2S7+YtdmqEtQNaF5T+MfEe8\n"
+ "6zDRnfXeNQaQSVGM2mhrkvWGYJkKecOQzuBsnlUmicLqyDV3HY9iefo8Two=\n"
+ "-----END ED25519 CERT-----\n"
+ "published 2020-10-14 20:58:04\n"
+ "router-sig-ed25519 Q3p7pd9YoXRgrRJN9dVqmR382KLxsGQu0zBr0JrfFaqow2fmTwXHnKYJZb5SzQeeYIjnHG/uSRWMmAcQoHnrBw\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "BOiWgexqCAMZ8uyJ7jwBwRkz7Ox8cT4BImkmkV3bQiZgcWvPiYA3EnCm2ye48Ldg\n"
- "zBST2p6zJM5o4MEDYGMxfViS86Abj/z7DOY1gtLhjmAaVjIIpXc3koxEZtzCecqy\n"
- "JQz6xEg9/KoEuoT0DRrfYQ+KtQfzBDWrotfOvEa1rvc=\n"
+ "mk0iHF8QMUfJUCjFWXihHQQjFflulpFDYeBgvCwUqrnIlbufuzLdoKEnrio0HCMq\n"
+ "VcJ+84iAW0likR4qflmerDobhbEpeA21pZx1zCkLdi4KzV1u79xvY5qHKHxWBbeY\n"
+ "W8yDErz6jVoGEqGOlg9Whlo6QSukttdKK974ugebVTw=\n"
"-----END SIGNATURE-----\n"
;
-
-static const char EX_EI_BAD_START_FP[] = "5CCCACE71A9BDB5E8E0C942AB3407452350434C0";
+ATTR_UNUSED static const char EX_EI_BAD_START_FP[] = "0B6D931123DA9B41F901D6EFCCD64CFBB89C6010";
+ATTR_UNUSED
static const char EX_EI_BAD_START_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAK2OCIfM6Cin/lq99Z3w9tl6HeyGlkBZu9MQEPHxqGIHTq78lIC1UkrC\n"
- "6NTqlrHBV9dmfzdwJn4GgMWsCZafL0FPIH3HNyNKUxLgyjixyKljHx2rfErSfOxI\n"
- "bMoOGBKv7m1EZZ0O5uG9ly9MBiNGdJyLdlnVvH7wSCnYciizpO4lAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n";
-
-static const char EX_EI_BAD_PUBLISHED[] =
- "extra-info bob E67C477E3536BDE348BD407426D9679E5AE0BC16\n"
- "published 2014-99-05 20:07:00\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "l45IziBaXRKIjPAIUogMFNjQgH6k6Vm0+6r5+oByr4sP+B3ufNdUA6+WqBs43F0Z\n"
- "IqcJiT9nFn0DuNd/liOyOCixppDLx5h5NrhoGqcT3ySADEEXhzjlmc35TI3YBNVO\n"
- "v98fotmwIEg9YRWVGPg6XuIn2PRyiboFyjUpaYGCV0Q=\n"
- "-----END SIGNATURE-----\n"
+ "MIGJAoGBAMfN4ZtcZcKFtmMakKEghsW4SWYPlxg5DTtSD3OSbarO0mucpQqsQnkx\n"
+ "Nr4yFOGHmJiZxkKbqVwAq78ZUfFzWVW+I2TaPCWKvCdEib6SlMXueufgcsW2eQLz\n"
+ "URbswEArwivNzY2wcnweGI6fdoN1FZloE1pk6YR9aZLI91RaWhHNAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
;
-
-static const char EX_EI_BAD_PUBLISHED_FP[] = "E67C477E3536BDE348BD407426D9679E5AE0BC16";
-static const char EX_EI_BAD_PUBLISHED_KEY[] =
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAL7q8GEI18iv8Fo0QbNHmFatQ2FNacalPldpmKUdMJYEVZtdOR0nhcrY\n"
- "BvG6303md3INygg+KP49RvWEJR/cU4RZ9QfHpORxH2OocMyRedw2rLex2E7jNNSi\n"
- "52yd1sHFYI8ZQ4aff+ZHUjJUGKRyqpbc8okVbq/Rl7vug0dd12eHAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n";
-
-static const char EX_EI_GOOD_ED_EI[] =
- "extra-info emma A692FE045C32B5E3A54B52882EF678A9DAC46A73\n"
+static const char EX_EI_BAD_PUBLISHED[] =
+ "extra-info HomersRelay 94C608B2CB50E5D488D345A0F54D1C78D13C69E1\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf55AYgHn/OKR8GHBlscN5VkO73wA9jSci8QgTM30615ZT44AQAgBAC08woT\n"
- "MBZpKzRcaoEJhEG7+RmuYtnB2+nODk9IRIs8ZoyYPTZ6dLzI+MLMmtzUuo/Wmvw0\n"
- "PflTyCb2RlWitOEhAErWH3Z9UmYGnzM/COId0Fe3ScSriyvRoFnJY1+GVAQ=\n"
+ "AQQABstTAUUzHVvllaO8HwZE3nF9kV7fqSK3WzuS3GvWRF69YHJ3AQAgBACUuECr\n"
+ "PwY0R1fw7rzTgcYuoWCeHhAbePuO6SNk39cQYsI26HPCQakL3yK4258tXsxC4LGN\n"
+ "DzH21SnS5gopeyg17C3ME6LtV1AAUz3Ytmf+2iNHIEJG9FHruZUeX7vCmA0=\n"
"-----END ED25519 CERT-----\n"
- "published 2014-10-05 20:07:00\n"
- "router-sig-ed25519 a7K8nwfg+HrdlSGQwr9rnLBq0qozkyZZs6d6aiLEiXGdhV1r9KJncmlQ5SNoY/zMQlyQm8EV5rCyBiVliKQ1Bw\n"
+ "published 2020-99-14 20:58:04\n"
+ "router-sig-ed25519 9AtZy5azhX81mxtY/ujFfZvoR3biUDtkZnnFMMLg25A2zmjou6WAQeoRQkPH/lN7sBN68NSiJ9+qF2Ef9m+qCQ\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "GvmCmIGgbC1DeawRyRuChy62VmBOG0EviryG/a2qSZiFy0iPPwqSp5ZyZDQEIEId\n"
- "kkk1zPzK1+S3fmgOAXyXGH0r4YFkoLGnhMk07BoEwi6HEXzjJsabmcNkOHfaOWgs\n"
- "/5nvnLfcmxL4c6FstZ7t9VQpE06y3GU0zwBeIy1qjp0=\n"
+ "eBc/YKRfl2OLethfPnK+rp6WF4Q//dCEI63eYMesUuLomAiOWdvPjW8Ispl9auPx\n"
+ "DLw5BQR4bYuO2oTNWS0fGyh7sykepCkuuvfcxRMDuGDGz9KmfJezKOiHgPENpzD+\n"
+ "hlTqtTKRwD1TP3hJtHSxYi8ZTR9XuR0MuZ/uQxVSwW8=\n"
"-----END SIGNATURE-----\n"
- "\n"
- "\n"
;
-static const char EX_EI_GOOD_ED_EI_FP[] =
- "A692FE045C32B5E3A54B52882EF678A9DAC46A73";
-static const char EX_EI_GOOD_ED_EI_KEY[] =
+ATTR_UNUSED static const char EX_EI_BAD_PUBLISHED_FP[] = "94C608B2CB50E5D488D345A0F54D1C78D13C69E1";
+ATTR_UNUSED
+static const char EX_EI_BAD_PUBLISHED_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAM3jdYwjwGxDWYj/vyFkQT7RgeCNIn89Ei6D2+L/fdtFnqrMXOreFFHL\n"
- "C7CK2v2uN3v+uXxfb5lADz3NcalxJrCfGTGtaBk7PwMZraTSh2luFKOvSRBQCmB1\n"
- "yD5N0QqnIhBJoGr6NITpbWyiTKWvYLjl9PZd9af8e8jQCAa5P1j1AgMBAAE=\n"
+ "MIGJAoGBALSDc0v0jfhvfcx7rxGQhCGzBGPZepZoJQY/dQrjBlMo0EqZg3KjYXiv\n"
+ "JpukXfXMgbiTyTv2Kknsbhjx1WhVTwNs+smdea6RryQJX/PbO7HzriaCm99XFO/b\n"
+ "IlJ918osvoU1VIhiPTzTJPUT6hmP4RNHXJe2ZTjDACGa/Kk16SLlAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
;
-
static const char EX_EI_ED_MISSING_SIG[] =
- "extra-info rachel 2A7521497B91A8437021515308A47491164EDBA1\n"
+ "extra-info HomersRelay 961B50E8433A0ECDAFFB51FBC951B869BD89A7E5\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf55AT2/T71LFYHiI1ppwNiuaewIu2Hq+GWWQ85O8gpWcUxeAQAgBAC2dgYu\n"
- "moxhtuip7GVlthT9iomZKba1IllVa7uE1u2uO9BUYZQWXciFt7OnNzMH5mlffwxB\n"
- "1dWCl+G5nbOsV5jYLbfhrF5afZotf+EQTfob4cCH79AV223LPcySbTHTtQ4=\n"
+ "AQQABstTAWCgrsRHajn+P0SbnvG/WcI46/wS061O1ImRCajjJY8WAQAgBADH8/EZ\n"
+ "onxMi+CrbK3/xNGakEevRzyE2bFAF45l/y8SYeBhcvfzQuGaxuHgIt6D6UAFiVyV\n"
+ "jM+vwjyLTrSicJAPFiVJkbu4tbDijcjr34IlwsAVV/NYX05bX8hVpaSSPQU=\n"
"-----END ED25519 CERT-----\n"
- "published 2014-10-05 20:07:00\n"
+ "published 2020-10-14 20:58:04\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "oypRD2IZQ5EttOE8dvofrW80nnBfijSkvYzBrM6H4KVeayRYvWfmi96dYO6ybMqm\n"
- "Yp7Gs3ngqeeNdfHtkRPuQVUXUGYZgBTvYItuagnFlFgRqaHy0knwUIVOL35eqWYx\n"
- "xSbQKA7fglxEDMFs/RK7FRP4dWc731ZMt5wzzfJHZ8E=\n"
+ "fcD3kYMeOBr4wwKKuRKz7KoHSDIInwYFVnm/kFAMKrSeU+z1MOqchobpp4AuN2p0\n"
+ "BiOLYz621PcTxpURvagwoPcqulkIoWazng9fKyy+ZUk2z9QOjZ2A1PXZVnSKNLxm\n"
+ "P5nNO78Ev5qg6fsYcE40UppOu6mOAXKaKhwyl7ZEvNc=\n"
"-----END SIGNATURE-----\n"
- "\n"
- "\n"
;
-static const char EX_EI_ED_MISSING_SIG_FP[] =
- "2A7521497B91A8437021515308A47491164EDBA1";
+ATTR_UNUSED static const char EX_EI_ED_MISSING_SIG_FP[] = "961B50E8433A0ECDAFFB51FBC951B869BD89A7E5";
+ATTR_UNUSED
static const char EX_EI_ED_MISSING_SIG_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAOOB8ccxbtk2dB5FuKFhGndDcO6STNjB6KiG0b9X2QwKrOZMfmXSigto\n"
- "mtC1JfPTxECayRjLSiP/9UD8iTVvlcnc8mMWBGM12Pa/KoCZRn7McHI3JJ7n9lfn\n"
- "qw9+iZ9b/rBimzOb3W6k3uxzg9r8secdq4jJwTnwSjTObgxZtC8/AgMBAAE=\n"
+ "MIGJAoGBALlAaT9rapqG8s8WuOI/wt9hdIMEZrjFyywelTuY3wDMvWMqKJUX0VCT\n"
+ "TtRco0+Q0QiQcMmcbvWz+BknC7L457XAeBmKckLjSGhu8Ett1/nYiT/wKv4eCOtT\n"
+ "KxkSGkrJX4L9mgdrquwCY6Eq4pUXFHHA2OkE/w25wmbud5GiZ7stAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
;
-
static const char EX_EI_ED_MISSING_CERT[] =
- "extra-info lynne E88E43E86015345A323D93D825C33E4AD1028F65\n"
- "published 2014-10-05 20:07:00\n"
- "router-sig-ed25519 H4gKIKm5K9Pfkriy7SlMUD6BdYVp6B5mXKzR/rTyYlpH0tEZ4Fx2hlHNfNNdWXJieXzKZQZo8e7SOVzvrAC3CQ\n"
+ "extra-info HomersRelay 65EE5370C2EFEC112E351206CF00C4DB89670356\n"
+ "published 2020-10-14 20:58:04\n"
+ "router-sig-ed25519 VaqCeYmnufCStWecAdhxAUs2tBY7DlWBVVtkduk1dJkBzRi9aDTi+7lU80wrYbH1Hb3lykXM+TI5GOabbO8uBQ\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "dIrbQjK5T9t5KM8CpsMF85hh2i060oPIxzYQMgE1q4j99dtb/n7SE8nhj1Sjij4D\n"
- "7JvTjGdLHi3bFSxXaSmla0wxD9PUYFN7VsBQmwSaDrqrzJFb1SGwZuzW1IEZ7BBi\n"
- "H0czsxEteg5hcNRwISj5WVthuWmau9v13MijtZGSK40=\n"
+ "Bum6OqCQ4asVALAzusLhkn9YgjazJo1Ta4Ff/qubOGcY7JqIC0f7oUfd6D+EhsZS\n"
+ "nRuZjp3KS1jM3gLPaWDI1cGNIG2RwS7QoWjFhjsUAQuBtKVmfBNtdiS9syNLxIlw\n"
+ "zxhm2sGMJ9gxhTIK2noGd36ur+XaQrRousdbkjpwiRk=\n"
"-----END SIGNATURE-----\n"
- "\n"
- "\n"
- "\n"
;
-static const char EX_EI_ED_MISSING_CERT_FP[] =
- "E88E43E86015345A323D93D825C33E4AD1028F65";
+ATTR_UNUSED static const char EX_EI_ED_MISSING_CERT_FP[] = "65EE5370C2EFEC112E351206CF00C4DB89670356";
+ATTR_UNUSED
static const char EX_EI_ED_MISSING_CERT_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBALjA/geb0TR9rp/UPvLhABQpB0XUDYuZAnLkrv+i7AAV7FemTDveEGnc\n"
- "XdXNSusO1mHOquvr0YYKPhwauInxD56S8QOzLYiWWajGq8XHARQ33b4/9K2TUrAx\n"
- "W9HTHV1U1zrPlCJtrkbjxsYoHpUg5ljzM7FGYGY5xuvyHu18SQvzAgMBAAE=\n"
+ "MIGJAoGBALir3RWzz5UpiEP+kV4qPtsKzt3C2cwZ0c/k/UusCnszyCVRFJSRa/Iw\n"
+ "Er59Y+Qe/r8ehHts7KXlv9r4CIKGUlXv2YKMI6Dernxnl8e68F3sUyy+GY4a0UJd\n"
+ "sQyMwWcVlOkD6kSUPT4ryAGw3wlL8MAA2xllNl+7Lexpb7VficZLAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
;
static const char EX_EI_ED_BAD_CERT1[] =
- "extra-info marcie F78D8A655607D32281D02144817A4F1D26AE520F\n"
+ "extra-info HomersRelay 82D64A389FBADE8BB38C8F7027EE15B34BBA0CB3\n"
"identity-ed25519\n"
"-----BEGIN PLAGICAL SPELL-----\n"
"aaaa\n"
- "-----END PLAGICAL SPELL\n"
- "published 2014-10-05 20:07:00\n"
- "router-sig-ed25519 KQJ+2AH7EkkjrD0RtDtUAIr+Vc7wndwILYnoUxFLSJiTP+5fMi54eFF/f1OgkG8gYyTh8phMij9WOxK/dsOpBg\n"
+ "-----END PLAGICAL SPELL-----\n"
+ "published 2020-10-14 20:58:04\n"
+ "router-sig-ed25519 q0SZRiMpJ4CG7rebOJk6HzR/TNEmsU7wXDjFYxLMdJgvkQZf9ynsyEIvS9buInsY09czmAFQOUnY2poCBkHeCw\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "XWD+P25AH6moi79j20Si3hqKGcJDws+FORL1MTu+GeJLV1mp5CR9N83UH4ffulcL\n"
- "CpSSBDL/j74HqapzW7QvBx3FilaNT55GvcobZDFK4TKkCEyEmcuWKpEceBS7JTTV\n"
- "SvwZeOObTjWPafELbsc/gI9Rh5Idwu7mZt3ZVntCGaQ=\n"
+ "OlhdHgl8dxV4+GRqjsE45qk8QlBYL4+hqSdf4biQGgVGpQv+kbUqzioS8jmiMC4e\n"
+ "VzeFBwEbHxD4OI6C/LWjgOk33uZ3Re7yWnlMqnnWKZOLAEX1/BD4SuTSwlTlzci8\n"
+ "48mzwzTnjh3I1j7ChMm5r/QIpgiC1iwrgw7oVK7mvE8=\n"
"-----END SIGNATURE-----\n"
- "\n"
;
-static const char EX_EI_ED_BAD_CERT1_FP[] =
- "F78D8A655607D32281D02144817A4F1D26AE520F";
+ATTR_UNUSED static const char EX_EI_ED_BAD_CERT1_FP[] = "82D64A389FBADE8BB38C8F7027EE15B34BBA0CB3";
+ATTR_UNUSED
static const char EX_EI_ED_BAD_CERT1_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMlR46JhxsCmWYtmIB/JjTV2TUYIhJLmHy+X7FfkK3ZVQvvl9/3GSXFL\n"
- "3USfyf3j34XLh8An7pJBi9LAHkIXgnRbglCud7dXoexabmC+c2mSbw5RnuxDGEwz\n"
- "krXUph/r2b+2UY1CgEt28nFigaHrIQbCmF4szFX/2GPYCLi5SrRNAgMBAAE=\n"
+ "MIGJAoGBAMBDm5sHAbst7tvS5k9sCh6/7b3fEMW9cpARKuK5VR5PdcNJDkxWPTPr\n"
+ "J/Jy0xTqnWrUD0njXpsdE7PKIspn6a5dnk775GmpH8Z8KnRcCrx7AX1Rd0evg4+s\n"
+ "nCPASoD8RlfduLuJ2ZtdGZ8fWOYc2pQmLLYzy0BxoLKC0P9+/CwBAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
;
static const char EX_EI_ED_BAD_CERT2[] =
- "extra-info jaeger 7C2B42E783C4E0EB0CC3BDB37385D16737BACFBD\n"
+ "extra-info HomersRelay 590FDF3A7684E2F9FCC29CFC7941D73570AF5457\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
"AQoABf55Acpw27GZBdwGCgawCj2F/DPadt8F/9DnEWywEew1Yi3qAOtLpCB8KXL7\n"
"4w5deFW2RBg8qTondNSUvAmwYLbLjNXMmgA3+nkoJOP3fcmQMHz1jm5xzgs2lCVP\n"
"t5txApaBIA4=\n"
"-----END ED25519 CERT-----\n"
- "published 2014-10-05 20:07:00\n"
- "router-sig-ed25519 DRQ4MLOGosBbW8M+17klNu8uWVkPxErmmEYoSo6OuH2Tzrcs6sUY+8Xi2qLoV1SbOugJ214Htl0I+6ceag+vBA\n"
+ "published 2020-10-14 20:58:04\n"
+ "router-sig-ed25519 3vgrf5SH8v7s6BNlXH/+RckQExrLwkY9mCgxewnXqvefYzyORy3GAiUQ9Iu0TbldP/Vtf+UgqnaZVbTERCoRBA\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "DfdA+DbuN9nVJNujuSY5wNCDLk7Hfzkrde/sK0hVmZRvivtpF/Fy/dVQHHGNFY5i\n"
- "L1cESAgq9HLdbHU+hcc08XXxTIaGwvoklcJClcG3ENVBWkTXbJNT+ifr7chEagIi\n"
- "cVrtU6RVmzldSbyir8V/Z4S/Cm67gYAgjM5gfoFUqDs=\n"
+ "IKKNccP7/3owyYgAC0fnnsyx22Yc7yHqQFMVXwcqV9XH43yhN8KUrbzoZH2pkZzA\n"
+ "0Mn47I82FCd+yQyCmURmWFSAVRQGH8rmBzl+lG9TiRdlBdZfp7YaazQGOVpE6BcM\n"
+ "N4Rh1XY1zV1c82mdQW/JgJ9qDCvflILm597sADqdfyI=\n"
"-----END SIGNATURE-----\n"
;
-static const char EX_EI_ED_BAD_CERT2_FP[] =
- "7C2B42E783C4E0EB0CC3BDB37385D16737BACFBD";
+ATTR_UNUSED static const char EX_EI_ED_BAD_CERT2_FP[] = "590FDF3A7684E2F9FCC29CFC7941D73570AF5457";
+ATTR_UNUSED
static const char EX_EI_ED_BAD_CERT2_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBALAM1F/0XJEsbxIQqb3+ObX/yGVnq9of8Q9sLsmxffD6hwVpCqnV3lTg\n"
- "iC6+xZ/bSlTGLPi0k8QLCaTmYxgKwmlMPpbQZ4kpZUrsb9flKdChMN7w8hd48pY9\n"
- "lu8QiAEgErsl5rCCJIHHjrxxM/Cnd0TnedRnj/Z2YqpNx/ggsmsRAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- ;
-static const char EX_EI_ED_BAD_SIG1[] =
- "extra-info vary 5AC3A538FEEFC6F9FCC5FA0CE64704396C30D62A\n"
- "identity-ed25519\n"
- "-----BEGIN ED25519 CERT-----\n"
- "AQQABf55AbPp++GrRb6WphSu+PkMaYsqY/beiLBmtiV3YP5i2JkKAQAgBABKXjg1\n"
- "aiz2JfQpNOG308i2EojnUAZEk0C0x9g2BAAXGL63sv3eO/qrlytsG1x2hkcamxFn\n"
- "LmfZBb/prqe1Vy4wABuhqWHAUtM29vXR6lpiCJeddt9Pa8XVy/tgWLX6TAw=\n"
- "-----END ED25519 CERT-----\n"
- "published 2014-10-05 20:07:00\n"
- "router-sig-ed25519 a7K8nwfg+HrdlSGQwr9rnLBq0qozkyZZs6d6aiLEiXGdhV1r9KJncmlQ5SNoY/zMQlyQm8EV5rCyBiVliKQ1Bw\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "xhZX8Qmgft51NJ7eMd4vrESzf/VdxDrBz7hgn8K+5bLtZUksG0s6s7IyGRYWQtp4\n"
- "/7oc9sYe3lcQiUN2K7DkeBDlL8Pcsl8aIlKuujWomCE3j0TIu+8XK6oJeo7eYic+\n"
- "IA7EwVbdZsKsW5/eJVzbX2eO0a5zyJ5RIYotFNYNCSE=\n"
- "-----END SIGNATURE-----\n"
- "\n"
- ;
-static const char EX_EI_ED_BAD_SIG1_FP[] =
- "5AC3A538FEEFC6F9FCC5FA0CE64704396C30D62A";
-static const char EX_EI_ED_BAD_SIG1_KEY[] =
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMvb6SuoIkPfBkJgQuo5aQDepAs1kEETZ9VXotMlhB0JJikrqBrAAz+7\n"
- "rjIJ4JsBaeQuN0Z5ksXk2ebxtef7oMIUs37NfekLQHbNR0VsXkFXPEGmOAqpZjW0\n"
- "P524eHqybWYZTckvZtUvKI3xYGD6kEEkz4qmV6dcExU1OiAYO9jrAgMBAAE=\n"
+ "MIGJAoGBAK5yV8+I/GiI+Vz6ob7Oecf7TpuLoBPEppLzY3RLv9GqwrIyAhWR7oQk\n"
+ "qrImJE3U+QPdf/Sw/+LG6fIuZPQAyHx8E7FtUBrT6X9gmel+H/4bj40OQhs6nynV\n"
+ "XKnq0tsaNnQrb5ofdFrlCcG+a+ij7gqq1gd9JzITGK7tEdGIMKprAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
;
-static const char EX_EI_ED_BAD_SIG2[] =
- "extra-info coward 7F1D4DD477E340C6D6B389FAC26EDC746113082F\n"
- "identity-ed25519\n"
- "-----BEGIN ED25519 CERT-----\n"
- "AQQABf56AZkSDiFZ1QaiLJhcKdFDE5Kei/sPaPEIEoPMGP4BvOVXAQAgBAAlRLzx\n"
- "U029tgIL9BRe47MVgcPJGy48db6ntzhjil7iOnWKT70z2LorUD5CZoLJs72TjB6r\n"
- "8+HYNyFLEM6dvytWZf9NA5gLdhogbFcUk/R3gbNepmCF7XoZjbhPIp8zOwg=\n"
- "-----END ED25519 CERT-----\n"
- "published 2014-10-05 20:07:00\n"
- "router-sig-ed25519 yfV+GySMIP1fw1oVa1C1de4XOWBqT4pUtEmSHq1h+WrLBNCh3/HZWvNC/denf2YVntuQrMLCJEv5ZaFKU+AIDQ\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "g+BWq69i9CP19va2cYMAXCQ6jK3IG0VmNYspjjUFgmFpJKGG6bHeOkuy1GXp47fG\n"
- "LzZ3OPfJLptxU5AOQDUUYf25hu9uSl6gyknCzsszFs5n6ticuNejvcpzw6UfO1LP\n"
- "5u+mGJlgpcMtmSraImDZrRipmZ3oRWvEULltlvzGQcQ=\n"
- "-----END SIGNATURE-----\n"
- "\n"
- ;
-static const char EX_EI_ED_BAD_SIG2_FP[] =
- "7F1D4DD477E340C6D6B389FAC26EDC746113082F";
-static const char EX_EI_ED_BAD_SIG2_KEY[] =
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBALzOyfCEUZnvCyhlyMctPkdXg/XRE3Cr6QgyzdKf5kQbUiu2n0FgSHOX\n"
- "iP5gfq8sO9eVeTPZtjE7/+KiR8aQJECy+eoye+lpsfm3tXpLxnpOIgL4DlURxlo/\n"
- "rfCyv30SYBN9j62qgU9m6U2ydI0tH7/9Ep8yIY/QL8me8VAjLbf/AgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- ;
-
static const char EX_EI_ED_MISPLACED_CERT[] =
- "extra-info msselene 3B788BD0CE348BC5CED48313307C78175EB6D0F3\n"
- "published 2014-10-05 20:07:00\n"
+ "extra-info HomersRelay 8CEBCF8A15C8C1F0537C31C4286E56BDFD710235\n"
+ "published 2020-10-14 20:58:04\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf55AWBcqjzLESDuLNGsqQ/tHn32XueXwj2fDlgEy/kQNVf/AQAgBAAFOegg\n"
- "XY1LR82xE9ohAYJxYpwJJw0YfXsBhGHqfakEoBtSgFJ3cQAUXZQX4lX6G8IxAlQB\n"
- "7Rj7dPQuQRUmqD1yyKb/ScBgCa8esxlhNlATz47kRNR38A3TcoJ4c1Zv6AE=\n"
+ "AQQABstTAe3zhxsBmvrWABOzif60p/X+9bZrLiRVcYhAMELIWvSwAQAgBAAAyj9D\n"
+ "q/oQQN8BgmK0cUk1kNsnpNOvCNZ9BorUZY+EtFHiND/PYtDe0SNmODVcA4eBvdXy\n"
+ "v5/0QI2S8roW7h1X8V0QVRguZ/3WwJpFE/qLHJ7LWu7kDPqzCjXHE5hQgQw=\n"
"-----END ED25519 CERT-----\n"
- "router-sig-ed25519 Q52JKH9/iMsr1jIPlWHHxakSBvyqjT1gzL944vad4OhzCZuNuAYGWyWSGzTb1DVmBqqbAUq73TiZKAz77YLNCQ\n"
+ "router-sig-ed25519 beLJb1fZrhBz4t6pBCnJl1UGX6QWFoKzbwRwxLUTUHUDyGpPIIbIEdxxem/RPcaYiqXti45lW57v0CEgYktcBw\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "YplvAIwExGf5/L8AoroVQXtGm+26EffrxKBArMKn0zS1NOOie1p0oF/+qJg+rNWU\n"
- "6cv3Anf188EXGlkUOddavgVH8CQbvve2nHSfIAPxjgEX9QNXbM5CiaMwgpCewXnF\n"
- "UoNBVo5tydeLHVns15MBg/JNIxUQMd6svMoPp2WqmaE=\n"
+ "BfdqDEu4Qk0SxBTelpzTqjlj1B3Yd0rQO0dftyGLtQmp3gVhUQqiFrW5/R1nTJKc\n"
+ "uOn9o/Te93+OOBLn0joJZ7JpHQJHjcHgW4kCoc2cAYUBEwgCHAa+eV5+jAVQHIm9\n"
+ "YHGkwZNaQct0ZiYnzWtnWzDVLB8ZpJltvYecflLTq88=\n"
"-----END SIGNATURE-----\n"
- "\n"
;
-static const char EX_EI_ED_MISPLACED_CERT_FP[] =
- "3B788BD0CE348BC5CED48313307C78175EB6D0F3";
+ATTR_UNUSED static const char EX_EI_ED_MISPLACED_CERT_FP[] = "8CEBCF8A15C8C1F0537C31C4286E56BDFD710235";
+ATTR_UNUSED
static const char EX_EI_ED_MISPLACED_CERT_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBALTwNqhTprg1oC6bEbDqwIYBoER6prqUXQFbwbFDn+ekXhZj8vltgGwp\n"
- "aDGl9ceZWDKfi+reR6rZXjAJGctmv0VHkfe7maUX4FC/d2T8N8DvS+3IvJzFMpbT\n"
- "O0fFrDTrCSnPikqFfQWnlP8yoF5vO7wo0jRRY432fLRXg9WqVzdrAgMBAAE=\n"
+ "MIGJAoGBAK0gXKx7t/EMu82I7+XV+/D7zuaZdzInBi/ieys1iiKpYqfSsvIS3hBu\n"
+ "TEWeuCUds9O81RMOqgGRktHPGu+6D863BGlzL+Ib+iih5ceclmYAJ6WvZF7w9enc\n"
+ "JGjP+wwJGWQVKTltlt9y/S/KM7KEGnCf5Biy1ZqJb9V3Fjp8R8DtAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
;
static const char EX_EI_ED_MISPLACED_SIG[] =
- "extra-info grazie 384E40A5DEED4AB1D8A74F1FCBDB18B7C24A8284\n"
+ "extra-info HomersRelay 3D9E654300A20118E237361CBBBBCFC71CA34BAD\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf55AcGuIBoa6TBqD8Gg5atcwp/+r9ThxIBkULmPv9OSGhv+AQAgBACXH13y\n"
- "mUvdpcN6oRN1nX6mnH40LyfYR5um8xogJZk3oINse5cRNrfMgVWiBpDlJZAwlDDa\n"
- "lx99hzuZBong+CiOcnEvLMsBaVJmNTm5mpdetYclZpl0g8QEXznXXeRBMgM=\n"
+ "AQQABstTAfBKg56c9SNv+Hhf8VjMX2h9s7MS1jPh5WIbHfJ+JgLuAQAgBADdptx9\n"
+ "uqI1om7gmESf4MImZeK+wKjgv0gttLYUyFu39dcjvDoAWdzQXjJMtR5Q2WlEqqPC\n"
+ "Fe41S7M6zYz6O5dbLp4vdDtdr6ZM5gWZwfdxqAfxWKwIsu8IOFOpjAkgVAQ=\n"
"-----END ED25519 CERT-----\n"
- "router-sig-ed25519 TxuO86dQ3pUaIY2raQ3hoDBmh4TTPC0OVgY98T5cf6Y+sHyiELCkkKQ3lqqXCjqnbTLr1/4riH980JoWPpR+Dw\n"
- "published 2014-10-05 20:07:00\n"
+ "router-sig-ed25519 re8w0o9hmBdpenf9ifhETkcWriJG9sWXDpkogyA4lyQ9MDDrlT7C1IJyGI666ZctCS4lT/btn9/t2Omal4Y7AQ\n"
+ "published 2020-10-14 20:58:04\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "kV2CtArl1VF1nUSyHL00mO3nEdNxlQU5N7/hZNTd+45lej5Veb+6vb4ujelsFERJ\n"
- "YoxwIs6SuKAR4orQytCL0e+GgZsrg8zGTveEtMX/+u//OcCwQBYEevR5duBZjVw/\n"
- "yzpEHwdIdB2PPyDBLkf1VKnP7uDj059tXiQRWl7LXgE=\n"
+ "okoxxnCsf3+V7oKGbmIqiQf7uKDfHOFdamYFGXIFRysn8aZx+o0eMb3I7xlSQfyz\n"
+ "eXdw7m7zHMerCsMLPuWsPBzt9ZPzQ3yvOJWNezzSGtZm8CW/3vLbaxOfI88teIZT\n"
+ "GcqZzbrlvCspGvC2doxep6zQS3ApEdZWpF19/agq2kQ=\n"
"-----END SIGNATURE-----\n"
- "\n"
;
-static const char EX_EI_ED_MISPLACED_SIG_FP[] =
- "384E40A5DEED4AB1D8A74F1FCBDB18B7C24A8284";
+ATTR_UNUSED static const char EX_EI_ED_MISPLACED_SIG_FP[] = "3D9E654300A20118E237361CBBBBCFC71CA34BAD";
+ATTR_UNUSED
static const char EX_EI_ED_MISPLACED_SIG_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAK0HgOCG/6433VCrwz/vhk3cKmyOfenCp0GZ4DIUwPWt4DeyP4nTbN6T\n"
- "1HJ1H8+hXC9bMuI4m43IWrzgLycQ9UaskUn372ZjHP9InPqHMJU6GQ7vZUe9Tgza\n"
- "qnBdRPoxnrZzUOzlvatGrePt0hDiOZaMtDAkeEojFp9Wp2ZN7+tZAgMBAAE=\n"
+ "MIGJAoGBAMLLN1IOWTOw9I3FSQHW9YpDJu4Wdj51vZmXUS3bxxiPinMJo7caSMyy\n"
+ "fyRmgWhzkRKxDXAchBDcLqylvfYRFryIg/fh0zFC6IBvdkHezrJ07KSK4t4TU22I\n"
+ "6luR5LdfNvcAxs3bbHhajvpPeD2iQCcENWdRl5efgtJ8gOeGo0znAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
;
-
diff --git a/src/test/example_extrainfo.template b/src/test/example_extrainfo.template
new file mode 100644
index 0000000000..357bd30896
--- /dev/null
+++ b/src/test/example_extrainfo.template
@@ -0,0 +1,182 @@
+:::comment=this file is to be used with the makedescs.py utility
+:::name=minimal
+:::type=ei
+extra-info HomersRelay {d.RSA_FINGERPRINT_NOSPACE}
+identity-ed25519
+{d.ED_CERT}
+published 2020-10-14 20:58:04
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=maximal
+:::type=ei
+extra-info HomersRelay {d.RSA_FINGERPRINT_NOSPACE}
+identity-ed25519
+{d.ED_CERT}
+published 2020-10-14 20:58:04
+opt foobarbaz
+read-history 900 1,2,3
+write-history 900 1,2,3
+dirreq-v2-ips 1
+dirreq-v3-ips 100
+dirreq-v3-reqs blahblah
+dirreq-v2-share blahblah
+dirreq-v3-share blahblah
+dirreq-v2-resp djfkdj
+dirreq-v3-resp djfkdj
+dirreq-v2-direct-dl djfkdj
+dirreq-v3-direct-dl djfkdj
+dirreq-v2-tunneled-dl djfkdj
+dirreq-v3-tunneled-dl djfkdj
+dirreq-stats-end foobar
+entry-ips jfsdfds
+entry-stats-end ksdflkjfdkf
+cell-stats-end FOO
+cell-processed-cells FOO
+cell-queued-cells FOO
+cell-time-in-queue FOO
+cell-circuits-per-decile FOO
+exit-stats-end FOO
+exit-kibibytes-written FOO
+exit-kibibytes-read FOO
+exit-streams-opened FOO
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=bad_sig1
+:::type=ei
+extra-info HomersRelay {d.RSA_FINGERPRINT_NOSPACE}
+identity-ed25519
+{d.ED_CERT}
+published 2020-10-14 20:58:04
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+-----BEGIN SIGNATURE-----
+V3l9u1uUdGiUPOl8j+hXXw4z/ODeCj/24r2+L32MTjyfUhK49Ld2IlK9iZKlgKYi
+zyoatxdAjU8Xc5WPX692HO4/R9CGLsUfYcEEFU2R3EA=
+-----END SIGNATURE-----
+
+:::name=bad_sig2
+:::type=ei
+extra-info HomersRelay {d.RSA_FINGERPRINT_NOSPACE}
+identity-ed25519
+{d.ED_CERT}
+published 2020-10-14 20:58:04
+router-sig-ed25519 X{d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=bad_nickname
+:::type=ei
+extra-info bobhasaverylongnameandidontthinkweshouldlethim {d.RSA_FINGERPRINT_NOSPACE}
+identity-ed25519
+{d.ED_CERT}
+published 2020-10-14 20:58:04
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=bad_tokens
+:::type=ei
+extra-info HomersRelay {d.RSA_FINGERPRINT_NOSPACE}
+identity-ed25519
+{d.ED_CERT}
+published 2020-10-14 20:58:04
+published 2020-10-14 20:58:04
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=bad_start
+:::type=ei
+identity-ed25519
+{d.ED_CERT}
+published 2020-10-14 20:58:04
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=bad_published
+:::type=ei
+extra-info HomersRelay {d.RSA_FINGERPRINT_NOSPACE}
+identity-ed25519
+{d.ED_CERT}
+published 2020-99-14 20:58:04
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=ed_missing_sig
+:::type=ei
+extra-info HomersRelay {d.RSA_FINGERPRINT_NOSPACE}
+identity-ed25519
+{d.ED_CERT}
+published 2020-10-14 20:58:04
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=ed_missing_cert
+:::type=ei
+extra-info HomersRelay {d.RSA_FINGERPRINT_NOSPACE}
+published 2020-10-14 20:58:04
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+
+
+:::name=ed_bad_cert1
+:::type=ei
+extra-info HomersRelay {d.RSA_FINGERPRINT_NOSPACE}
+identity-ed25519
+-----BEGIN PLAGICAL SPELL-----
+aaaa
+-----END PLAGICAL SPELL-----
+published 2020-10-14 20:58:04
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=ed_bad_cert2
+:::type=ei
+extra-info HomersRelay {d.RSA_FINGERPRINT_NOSPACE}
+identity-ed25519
+-----BEGIN ED25519 CERT-----
+AQoABf55Acpw27GZBdwGCgawCj2F/DPadt8F/9DnEWywEew1Yi3qAOtLpCB8KXL7
+4w5deFW2RBg8qTondNSUvAmwYLbLjNXMmgA3+nkoJOP3fcmQMHz1jm5xzgs2lCVP
+t5txApaBIA4=
+-----END ED25519 CERT-----
+published 2020-10-14 20:58:04
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=ed_misplaced_cert
+:::type=ei
+extra-info HomersRelay {d.RSA_FINGERPRINT_NOSPACE}
+published 2020-10-14 20:58:04
+identity-ed25519
+{d.ED_CERT}
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=ed_misplaced_sig
+:::type=ei
+extra-info HomersRelay {d.RSA_FINGERPRINT_NOSPACE}
+identity-ed25519
+{d.ED_CERT}
+router-sig-ed25519 {d.ED_SIGNATURE}
+published 2020-10-14 20:58:04
+router-signature
+{d.RSA_SIGNATURE}
diff --git a/src/test/failing_routerdescs.inc b/src/test/failing_routerdescs.inc
index e2b72c58a0..a612bf8b96 100644
--- a/src/test/failing_routerdescs.inc
+++ b/src/test/failing_routerdescs.inc
@@ -1,56 +1,100 @@
-/* This one actually succeeds */
+/* These entries are automatically generated by makedesc.py to make sure
+ * that their keys and signatures are right except when otherwise
+ * specified. */
+
static const char EX_RI_MINIMAL[] =
"router fred 127.0.0.1 9001 0 9002\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstQAbeja00FtmqpWPIF6GPZtoI0uBiRk7InZ3EV/8U/e1KRAQAgBADZeEW7\n"
+ "LYPn7S5mD4DnQpTVdns8xJtRboTtfqTs6nTpOwWV8+WI94ZME6k6T2FEChi/3qs8\n"
+ "VeCQIM2wW6rEQyUcQzFwqk9bks20K/8x/2vxGopxeAPpJ3glHYqweNM1ZAQ=\n"
+ "-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAObzT4opT9uaThByupbb96tYxVpGxzL9CRPKUcU0beGpHyognD9USHWc\n"
- "SpSpKfBL5P3xr2i/XTs34M4UTbT9PE7bVyxv7RD/BZmI4gc8R3PMU77xxbpEU5bK\n"
- "LF3QUPpuB88m/2fXUGgMNVDc5MIq6pod2NRoDpeU7WA8T3ewXzK5AgMBAAE=\n"
+ "MIGJAoGBAL2WKwBXssq8ImAdp9VauVXKiKNPsW2ocRlEVsmTLc+R7KORI7ssMM33\n"
+ "1TV5fjKw9a7kSAVKWuthHlpYf8zVosEaECEon2K9zlKPzpGYTfIecKzMTZdjP4mR\n"
+ "Eo10yberjn0W9dRbqCM2Cq6ofJpz8du3o2hDCx4N880Fyr+G1or3AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 2XhFuy2D5+0uZg+A50KU1XZ7PMSbUW6E7X6k7Op06Ts=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAM1QKsQiup9DNMCgNeE2FkAhCWzpMZKCn1nNlZbDGfE3Z22ex6bdWWY6\n"
- "ocEZ3JZDsZsnaZrdYxrL3Mquq7MbHdfx90EdlOvDRP1SAIbZ55mLR77fZTu4BKd/\n"
- "h9BC6I26uZE0QavFq3+BhoVVhVn5Mqv05nR9CeUMSSZLxw/RJm4DAgMBAAE=\n"
+ "MIGJAoGBANfuddZ47R/rAqf1vgryApzX6k3Lp4kfY8dgortrpeIY2AMrPPBrDc+r\n"
+ "TVBeKRtnlOUstHtZ6ZV9BNUUg1zd0+RlkITWlSRrKXDI8SskNh5RhyB6cYNyKmld\n"
+ "tpyTl1BCvqDb+5QHzNtuQ6zGfo2U2WqZarGEwb5edfPy5iMRNyNtAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key 2kTFTRb+2MmTBjlS9o1bD/1YGQSqYez46+ROA777jGw=\n"
+ "ntor-onion-key-crosscert 0\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABstQAdl4Rbstg+ftLmYPgOdClNV2ezzEm1FuhO1+pOzqdOk7AGsEQYwHCV65\n"
+ "YCx4fS6zYcrq/nMtz0EfoVyVBbBsRemZ4eXH+a5tOZf6uQDHwE2na8s1sdLB0LcJ\n"
+ "k4lxJJAT6wE=\n"
+ "-----END ED25519 CERT-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "1xp9J+HTe7Xz9otke8bGVo0jeTICkbV372X0x4r2Nlex+U4pNMI+H7r2VEn0xCa4\n"
+ "0Mv6huE9/oYVZL0/XgDNJKiYlzDTQvaabvb5teLc31O5AnFS6LvIo0FFflNvaoLE\n"
+ "6h/siROaO9/n3Y56hGNbkg/omkuRsv0+UddLjLxxs8Y=\n"
+ "-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
+ "router-sig-ed25519 WGGVwF/5vU7kD4U3N26vuh5cie0AQc+xmVeV4ikdhGOgChNqqVG5fRN8pl2x0wPJipC1aJwJf9GOamMChSP4Ag\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "Ft/y3JXowjItgfTHwYcZzuUgXrskluoINW5sr+GQoNYE2F4sT8o0tBBJwqJ6FwKd\n"
- "fkIprv9UXqkv5iY+pXSYSI12mY1K5GMNkXiObk46NjuoNNP9l8oidhO6eNfcE+k3\n"
- "CRIYS4FbBaD0fWUSwgMuo0Bp83/Wzp3B9ytEBh0/624=\n"
- "-----END SIGNATURE-----\n";
-
-/* So does this, and it's bigger. */
+ "UQ4017wr2yQlu0wVBuLJlJLWudEGJ+9Z+ZiyJRCrsVauB1L2o+oCK5fsrQeKIWQM\n"
+ "PSJ2o1tXgHAxJixOoTu1tlWNdZeQGNYRh7N2IbRvtwZ1p7NwgM5cG7CCQ/JDiGGy\n"
+ "exMCOnyJpT2pD6KS2SEhbFe4nGxeUnmiJhSFsxAl9Q0=\n"
+ "-----END SIGNATURE-----\n"
+ ;
static const char EX_RI_MAXIMAL[] =
"router fred 127.0.0.1 9001 0 9002\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstQAcDfLx3m1n7Cd3ZUnm+i/fjYWdxZJ2OxffZTq+C5Qhh8AQAgBAD8rDLK\n"
+ "Vraijk0AAOo1CC2vJ+D+E5NwcwrOyKW9Q9wa17CXmHNUAw3LzqxT6RfoWtvKTNZ7\n"
+ "CtrLhi7vW4ypl9u0KC2DUofm2of/vmGDVeNqbe8EYWdvLnU284Xy6GCt6QQ=\n"
+ "-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANNI56H+b7SW5LMzvXyY5NJzXszsHZZ4O1CPm4CePhBsAz1r0s1JYJ1F\n"
- "Anrc0mEcLtmj0c5+HnhPBNrfpjO6G94Wp3NZMVykHDhfNVDBRyFZMroG8/GlysYB\n"
- "MQPGQYR0xBgiuclNHoyk/vygQhZekumamu2O86EIPcfg9LhGIgEbAgMBAAE=\n"
+ "MIGJAoGBAL0rYefTyz0UxOqvMHkcMN/Otd5PpHQeEOuEI0CwnIe1BaHP9Z3o2T7c\n"
+ "BoIkjYN4WWUss2ymcpFsikHO1/Qt7Jjeg0teLKeRk6kxoBeoXU3jH/XWIZQ72C0b\n"
+ "NDxIvm0ZO8hHXpXySbL7WdUE2FmPZA92+LI02PVh05FNdvPODnTBAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 /Kwyyla2oo5NAADqNQgtryfg/hOTcHMKzsilvUPcGtc=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBALvuNVSmg6R9USFbQcNbRjMCJAV0Rwdv0DlS6Rl02ibJgb01G7v391xE\n"
- "d9Njzgf93n8gOrE195bkUbvS6k/DM3HFGgArq6q9AZ2LTbu3KbAYy1YPsSIh07kB\n"
- "/8kkvRRGx37X9WGZU3j5VUEuzqI//xDE9lbanlnnFXpnb6ymehDJAgMBAAE=\n"
+ "MIGJAoGBANPEmrfTxh6KAokO33hjwdCG5VqwSRf8D85MF7as4WrqIvmq3l+yhX4N\n"
+ "rxBXU/oH2NHdkEJp+wDi3ec0U4RO3x5N3c+pkLJ7T3PzX2bqyhXw+M8KFH9OgV8R\n"
+ "uDjeZde+6/I78zf9c93N+44348otSnOIVJi7J2XcKc1nLEg+kaSVAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key XNNdSQl9M8leFmXQy8fR4LBWUpSMAq/5sVrm1gdBcUo=\n"
+ "ntor-onion-key-crosscert 0\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABstQAfysMspWtqKOTQAA6jUILa8n4P4Tk3BzCs7Ipb1D3BrXAHKPG/YoVIfa\n"
+ "3eEbf1Z5PTnWgUXAPjGnDsVwSRiO+L3cW55varIF4OzANq0YbBVk6DxuSKQRhitV\n"
+ "Em9uzK+n9gw=\n"
+ "-----END ED25519 CERT-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "pUhJD9GilzzJmZg7BKErxfjlqABZmV1/6U6MpquraNZy1q5/8Q/VMvVVyqkavLQd\n"
+ "ue3QrEr9bUCG7TcrNYkCS95D0+Pgigzwmrxd7Ry4eBZTwUbm+G2HYLVCFX6YMX2r\n"
+ "kkmsX8KYlVZxgkUPVsbTmjVjWxK9nRN9A7+8shNYzAQ=\n"
+ "-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject 127.0.0.1:*\n"
"accept *:80\n"
"reject *:*\n"
"ipv6-policy accept 80,100,101\n"
- "ntor-onion-key s7rSohmz9SXn8WWh1EefTHIsWePthsEntQi0WL+ScVw\n"
"uptime 1000\n"
"hibernating 0\n"
"unrecognized-keywords are just dandy in this format\n"
"platform Tor 0.2.4.23 on a Banana PC Jr 6000 Series\n"
"contact O.W.Jones\n"
- "fingerprint CC43 DC8E 8C9E 3E6D 59CD 0399 2491 0C8C E1E4 50D2\n"
+ "fingerprint E9D3 2FC2 7674 5958 C315 803D BAF0 9EE5 C29C 3A0B\n"
"read-history 900 1,2,3,4\n"
"write-history 900 1,2,3,4\n"
"extra-info-digest AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
@@ -61,1509 +105,1431 @@ static const char EX_RI_MAXIMAL[] =
"or-address [::1:2:3:4]:9999\n"
"or-address 127.0.0.99:10000\n"
"opt fred is a fine router\n"
+ "router-sig-ed25519 uBj+IWQchmSBwFO9m2wyaGL2jQ6mz7vx9bUxavKAWovIBtB8b3XCyxOfs7bYP5yXM5MYGcAb2FG0S7BS344pCw\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "x5cxL2h2UsEKk2OVnCTxOF8a89HAe/HwQnSlrBy8+l0YdVCcePDJhm1WyWU7ToHZ\n"
- "K8auwreuw+u/n14sQHPYrM9NQE689hP4LC9AYOnrCnMHysfVqKuou+DSKYYRgs0D\n"
- "ySCmJ9p+xekfmms+JBmS5o5DVo48VGlG0VksegoB264=\n"
+ "Y/kIU3v/wA0Uq2mwGyELOMiBqhU2ydgqJVtgH/0oXWvl3YTX3JJCP0lSCWTYFX8N\n"
+ "QZ6zlk9SCPcQ7etUFOZz7XNkDXChZCjRwK921+ko18b+6AK+OCZ1rTi8EepsgTGS\n"
+ "DicGNpmReRVQc9wGWyXsRYS0KBeRBB42gweZ6vlG+6w=\n"
"-----END SIGNATURE-----\n"
;
-
-/* I've messed with 12 bits of the signature on this one */
static const char EX_RI_BAD_SIG1[] =
"router fred 127.0.0.1 9001 0 9002\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstQAYXI0XoJPqR80XqwEbqmiOLL5CwG71dv+66mseJUGu+gAQAgBADAWmwm\n"
+ "dp+JZnolhz8FLdL6abtj+MRbcbhTTg5gDRdcSsc39Bf3UPkhUEhOtTn7tbyNXEtO\n"
+ "iPDCvdR8t4xBgOqDLnNygoqMdCsf2eNYR8hzxXF4zn/La20L4g3hRwX5OgA=\n"
+ "-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAObzT4opT9uaThByupbb96tYxVpGxzL9CRPKUcU0beGpHyognD9USHWc\n"
- "SpSpKfBL5P3xr2i/XTs34M4UTbT9PE7bVyxv7RD/BZmI4gc8R3PMU77xxbpEU5bK\n"
- "LF3QUPpuB88m/2fXUGgMNVDc5MIq6pod2NRoDpeU7WA8T3ewXzK5AgMBAAE=\n"
+ "MIGJAoGBANhXTGXVE78ronMXn5Im4nML51N69oYpEjh3QqLCq7V19vNCnCbQjcRT\n"
+ "1zHEpL2+HIBHGW7r4phYtq6jRrPOkRk+9A43KMbyYUX8I6Zx/DrryYWKOyZi5Gh0\n"
+ "9VmIp8uwL3oD2icNTIkvAZQ2N2EkMeqkHeqLvHhotDgNvWmOW2+lAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 wFpsJnafiWZ6JYc/BS3S+mm7Y/jEW3G4U04OYA0XXEo=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAM1QKsQiup9DNMCgNeE2FkAhCWzpMZKCn1nNlZbDGfE3Z22ex6bdWWY6\n"
- "ocEZ3JZDsZsnaZrdYxrL3Mquq7MbHdfx90EdlOvDRP1SAIbZ55mLR77fZTu4BKd/\n"
- "h9BC6I26uZE0QavFq3+BhoVVhVn5Mqv05nR9CeUMSSZLxw/RJm4DAgMBAAE=\n"
+ "MIGJAoGBAMAXX3EzjnH+PyThsoj9klX/WZRWSOzzCEKWu4+galdvzex4BRLnFjQd\n"
+ "RWRPcu6jd4eT+niaf0xacmDZuUlObhH0KdMx85JV1DfIO+LicGXwf+A8capCMsdT\n"
+ "E+ZRv+myozxvtYF5dXWWfBtb/HGyLBGP7LbiFM1a9Fy/opdCPI+/AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key LzriIs6B1YnUXISLCa0Ncgol4tt9coK0TlsyH9L8oyg=\n"
+ "ntor-onion-key-crosscert 1\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABstQAcBabCZ2n4lmeiWHPwUt0vppu2P4xFtxuFNODmANF1xKABvGX+C/nEsG\n"
+ "zqV/hrnqlfA/+3Pslp9+uPNs7nuq/gfsVlIjcOMcH1wpun1LxJ4CfaHbRoV9Azjm\n"
+ "AbJ4+sLFxgk=\n"
+ "-----END ED25519 CERT-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "CLhxMDL3CG8PG1UADvY604uoSwWZ5qDmlHLBc2FkJvdpP/wzovI615W+ew/DA/Jp\n"
+ "i5eHenjefH7LSfzGV1ZbjMZpRASqyHBsyl5nhOUEijRYlRi/LCsJutnOve6rJGfh\n"
+ "dedKLdeCqplto7xhROxvZcqhpwJTC+iJ4ghM4Xcg8Sk=\n"
+ "-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
+ "router-sig-ed25519 stCTjuw9egedA5hdDe1PQoljcLW3Fsg2ZYR3mre1moOd3mxTDI1Hz4uN+ZEDjedG4BNjDNcFY3qDS71Bs5cqDA\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "Ft/y3JXowjItgfTHwYcZzuUgXrskluoINW5sr+GQoNYE2F4sT8o0tBBJwqJ6FwKd\n"
- "fkIprv9UXqkv5iY+pXSYXX12mY1K5GMNkXiObk46NjuoNNP9l8oidhO6eNfcE+k3\n"
- "CRIYS4FbBaD0fWUSwgMuo0Bp83/Wzp3B9ytEBh0/624=\n"
- "-----END SIGNATURE-----\n";
-
-/* This is a good signature of the wrong data: I changed 'published' */
-static const char EX_RI_BAD_SIG2[] =
- "router fred 127.0.0.1 9001 0 9002\n"
- "signing-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAObzT4opT9uaThByupbb96tYxVpGxzL9CRPKUcU0beGpHyognD9USHWc\n"
- "SpSpKfBL5P3xr2i/XTs34M4UTbT9PE7bVyxv7RD/BZmI4gc8R3PMU77xxbpEU5bK\n"
- "LF3QUPpuB88m/2fXUGgMNVDc5MIq6pod2NRoDpeU7WA8T3ewXzK5AgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAM1QKsQiup9DNMCgNeE2FkAhCWzpMZKCn1nNlZbDGfE3Z22ex6bdWWY6\n"
- "ocEZ3JZDsZsnaZrdYxrL3Mquq7MbHdfx90EdlOvDRP1SAIbZ55mLR77fZTu4BKd/\n"
- "h9BC6I26uZE0QavFq3+BhoVVhVn5Mqv05nR9CeUMSSZLxw/RJm4DAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "published 2014-10-05 12:00:01\n"
- "bandwidth 1000 1000 1000\n"
- "reject *:*\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "Ft/y3JXowjItgfTHwYcZzuUgXrskluoINW5sr+GQoNYE2F4sT8o0tBBJwqJ6FwKd\n"
- "fkIprv9UXqkv5iY+pXSYSI12mY1K5GMNkXiObk46NjuoNNP9l8oidhO6eNfcE+k3\n"
- "CRIYS4FbBaD0fWUSwgMuo0Bp83/Wzp3B9ytEBh0/624=\n"
- "-----END SIGNATURE-----\n";
-
-/* This one will fail while tokenizing the first line. */
+ "aV5gqy5fTtsrdntTPRPGdeN376lXK+blHJuqbAL0WQ7XaMB4r+F8/whFu0cObOqD\n"
+ "AqAhxkcMu721iYCkUNQvhc3FDou2i1mBJFDrhZEtux/2aXODIMG+OPdDUCyBqeQR\n"
+ "oYLLfLR4ZZic1tlBFRRNdtXGF2SHeIM052F7PbeJz2A=\n"
+ "-----END SIGNATURE-----\n"
+ ;
static const char EX_RI_BAD_TOKENS[] =
"router bob\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstQAY1Po0v0V6qx88GtnuvL+A1OgBABUAjtKSNXR3ZZbB7BAQAgBADilhyL\n"
+ "8kQhWtuPIYxVEQNYAqH/zZCGy7Dj84NEHauI7RaK3GtpbxrIKsMV6oIjyabSSwck\n"
+ "lTBMZ21/EQERwvzyJC6XhSbPIWjI2MpZa5zez+RueZuGhOfqPDidE3sJUA8=\n"
+ "-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANGCgvZc+JRtAzuzk3gBD2rH9SHrXzjJ1wqdU3tLKr7FamKCMI2pLwSA\n"
- "FZUpTuSqB9wJ/iVcYws+/kA3FjLqgPtzJFI0SVLvQcz5oIC1rEWpuP6t88duMlO9\n"
- "flOUzmYu29sBffrXkQr8pesYvakyXArOJVeRR7fSvouneV5aDYWrAgMBAAE=\n"
+ "MIGJAoGBAOMS5ORipGxb7cm0JEUMxbTh6Jj8t2fMSC4sSAEWtScFVSa5Lc9duuPO\n"
+ "QFRBMFSN7JPp7yv4MiQ/7UWQbm8KeSHwTdLJAaU9IaK8We0oQYPrW5qjHZGexYBu\n"
+ "xy27uSSerxMnk9tulG/AGLQUwTaVVzMZKswvvx4Rerk1QBVQKAzhAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 4pYci/JEIVrbjyGMVREDWAKh/82Qhsuw4/ODRB2riO0=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAML+pYZoYc+whKLijupd63xn0gzlEQqe7k07x/lWMqWFT37FfG6YeNr5\n"
- "fpFoo77FDfuFaL+VfPfI8i88g157hcPKBVX6OyRH54+l5By0tN91S0H+abXjXQpv\n"
- "U/Bvmul+5QpUeVJa1nPg71HRIauoDnBNexUQ7Xf/Bwb2xCt+IJ6DAgMBAAE=\n"
+ "MIGJAoGBANEtuNrjt+lqyvpAOhb1KgoZrtHOVsgvxbQxntUFWxNFWDu0pQ1oeD2Z\n"
+ "sKK1LchHdDAZMo5Hx6Kph8zYtrOW5lP1uo8Q2UfZfkUvmMFWFzPE60Sw7OHW0emI\n"
+ "53qvAsaKcGkqjH7/BqkNhoz+Z7kPrp1hj3bzPJL2WRwl5Oc5v0EDAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key /O0T65ZXDCLznQB8kW5e24GfH5Ep1Hp8Wn72d7MLKHc=\n"
+ "ntor-onion-key-crosscert 1\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABstQAeKWHIvyRCFa248hjFURA1gCof/NkIbLsOPzg0Qdq4jtALHBaxDDFa82\n"
+ "TnVkxKLU/OQ+b8w1OFtaphO6OUPnF9TCuxcL1Q7uEyD8aVpgSHs6+vAsGEA/iYjV\n"
+ "qNRsst8dAwQ=\n"
+ "-----END ED25519 CERT-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "ILLtKDOLTh4o9trasbxFq0mXfZylPyo3CBjYwZlrSONma9vLmjVob6uU4hugoL9V\n"
+ "Ti5+GgkfNszCiyDJfTkZtL57HtnbHEF6xrMcVDF4j3/ChJR4leaE9IiT2i2Qqe/k\n"
+ "pQVThYaTVooBjuuenqqduGdkQD0sWR0Nd9sormczWbg=\n"
+ "-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
+ "router-sig-ed25519 B/2mFc4gjSmcRguwheihVNruRrqjWWULorDNIIbF2eIER8ZG5DMiG9x57dKf68ga1MeL2Jx6BLhvIHpBxdloBA\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "tbxtYYzyVqi6w6jz1k8NPjFvZaSNR0WzixVTTvKKGoMPx/6+Z8QAFK1ILzRUVucB\n"
- "nRhmZMFaPr3vREMErLRE47ODAzwoBCE9C+vYFvROhgfzuQ3cYXla+4sMaRXYZzjH\n"
- "PQ82bTwvSbHsR8fTTgePD/Ac082WxXTGpx6HOLBfNsQ=\n"
+ "ymrdXf4aSaFDb5Qy39rn8u97kKqzs5HZ62dCWLHDyfewUSyNilg7Wt11v4cs7l/7\n"
+ "zizuBHz0Y4E8d6rdoO4PP9KBWFnpcIblaPC5f/SLnNyP93Z6H55gzm1fvTU9cTZM\n"
+ "zKSyCKiUSYpHba5jO70pyR0uOHeu6QhnuphxEN7/KOc=\n"
"-----END SIGNATURE-----\n"
;
-
static const char EX_RI_BAD_PUBLISHED[] =
"router fred 127.0.0.1 9001 0 9002\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstQAdYwLWzkkORAf4oCu7/DXxkHqpAuz/6kHURFX99fxos7AQAgBACvXQAY\n"
+ "eQLaT3/Y512bMp/QFMwqhb3LZJrdQaamSfIkpeQgxtDmcMb2pzU4Qvq34qyBON0z\n"
+ "3yqEUA8PkjK8F/tCayXzftZIMn88qna4OWtytpnRI+qhfkZ2qeCcsXKCTAE=\n"
+ "-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMoipSwZgTG6SpSOm6ENbyALS1Ljqqa1LSGmtHSRfGYgUQGWZXERXKQj\n"
- "P5ql6o7EbGr1wnispGW/KB8Age09jGDvd/oGhQ9TDFluhLZon3obkZSFw7f9iA7Q\n"
- "s29rNxoeXXLZVyS7+sux70b8x2Dt4CeG8GA8nQLljy1euwU+qYYJAgMBAAE=\n"
+ "MIGJAoGBALoFN+2xSVUeUDh9zMC5O3MRa3T3hS1Uiw0KMgai6TXM4vYvIva5Hsmf\n"
+ "jkD5eERRn9NvYF+dVM6mZqUsra93Q0P93WJjSS0V9Hi4KERAZEJYXpdOq6xwF2A0\n"
+ "fy7AfcxrARjk6Scjqq4WRdWJ80F7fmtRC2aJQx9hrsoYJUylkzc9AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 r10AGHkC2k9/2OddmzKf0BTMKoW9y2Sa3UGmpknyJKU=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAPzfzQ+2WFMUvnB3z0xD+zwczWcFyYYNW8Lj7/aRGSNN2DICp5uzSjKq\n"
- "qkYQ+C8jG21+MR2PE+ZBmq6CL5mvlFKlWKouXUlN7BejwWf2gw0UYag0SYctae1b\n"
- "bu8NuUEvdeGWg5Odgs+abH7U9S0hEtjKrmE5vvJS5L841IcaPLCFAgMBAAE=\n"
+ "MIGJAoGBALKTuo70dMO6xF89bE/ke4IkN2V9t49UtSI+X607oul59J32YEjCdhOh\n"
+ "mGDw9c/IpUg/fC6yyhNxrVJttKHju3bcHqMTMbkjvyQcEqRRR3f8i5YNmLj3bNxc\n"
+ "vyom0RpyUopuVUx3IFhd1R3MkBVLjMVYOu9zpre8PnDeEtjFNpZlAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key v6c+IGW5pPiYjt/7EUjzO5VAEYETPAAr/qGw3H/N6AE=\n"
+ "ntor-onion-key-crosscert 1\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABstQAa9dABh5AtpPf9jnXZsyn9AUzCqFvctkmt1BpqZJ8iSlAEzibhI3GhEl\n"
+ "AuLAGw9oa+6KcgVuJb77xBj/9uezeCXCkiPDA6HPjhLsBGlZTchRSZ2CNnRkMB5I\n"
+ "phz7u5XhWgE=\n"
+ "-----END ED25519 CERT-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "lyaSCIaSAW5R09tUtkwRvJBDYgCGq2zbgO3hkG8L0XoUAjBU+VyGdqUeWwt3mMeH\n"
+ "nzOTa+oiO4uGbCic8nMXSQMeSD8X1uLTDn5w1QgJlGbJP0nfJyHPzFafIMKPYe9u\n"
+ "bUWThv2WwfygfZLpm9Vtg+wOuCf6CEPUekBtV/mzDkw=\n"
+ "-----END CROSSCERT-----\n"
"published 2014-10-05 99:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
+ "router-sig-ed25519 4VtXGU7x0OmWCijvK6CGTrKEtEqmbfwau2oIWfmX2anU7rWKrHp29HlBljK62cso22ODdfjDA9xOIUF3/Rx2BA\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "G92pnwCIXGJ9Q0fI9y4m/fHpWCsD0Hnk81/6T4TmRH3jt77fc0uRdomUOC5id4kz\n"
- "J2M4vqXwRs5OK+eaPbtxf8Yv6FPmB3OBNCIhwNHIIqzKQStHUhPxD3P6j8uJFwot\n"
- "/CNGciDN+owZ2DzwrXpszDfzcyp/nmwhApbi3W601vY=\n"
+ "CLIS6weTFUdRmbZQXuu6084omWxMbVmbbEvVZcgxNJdFA1Kjj5XLLw4xU9710FHH\n"
+ "FHqftfs5e483aw3ge/A44L03JL6aUeeQiRU7+A4daLq2h+pw7sTM5CzB9nQYMaQQ\n"
+ "1PyCDtVGLPXlFcNyVsJV135RplESfC/SMOJCdqqErew=\n"
"-----END SIGNATURE-----\n"
;
-
-/* Bandwidth field isn't an integer. */
static const char EX_RI_BAD_BANDWIDTH[] =
"router fred 127.0.0.1 9001 0 9002\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstQAaUhoYyIeOU1shTEDUP1aHQqyxQrwwVfEQgqR30hmhxgAQAgBAD/v+wN\n"
+ "v7f62EeJZlcfrx3ar1tVPwbYg+tr8nI6vAsfZ5CnHu+tFZwH/z8wYr99xeLNE1WM\n"
+ "PSS5gecVO5O/dmX2prMLZC+3+wTUNPMPhUeZEalQQmqtm1Lf132P7jQIpQY=\n"
+ "-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAN32LAvXQaq0p554FcL4LVwnxyiZvscfuFnfpXwWTDRJJHd2+JCttWIx\n"
- "v+eW7dNq+rq/tzSzaZwnp8b4V2skLRojSt6UUHD234eZcsPwUNhSr0y1eMuoZbnV\n"
- "UBBPevpuXea85aSFEXXRlIpQfvFc43y3/UFoRzo5iMPqReo2uQ4BAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMBuF1GvOyVcRDNjzlEmGHJkTA7qkaWgTp33NSY/DPEJoahg0Qswuh2w\n"
- "1YCBqem6Txp+/Vl9hoUoUGwb7Vwq0+YDMSyr0z3Ih2NcNjOMZPVtjJuv+3wXrQC8\n"
- "LPpCpfU9m9QvhQ7f9zprEqUHOQTT0v5j2a5bpfd++6LFxrMUNwbfAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "published 2014-10-05 12:00:00\n"
- "bandwidth hello world today\n"
- "reject *:*\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "svABTGDNJOgaiPLqDlkRU6ldYJcoEe2qHlr4O30lVM2hS3Gg6o4QARL7QRt7VepT\n"
- "SruR6pE83xOr7/5Ijq5PlamS4WtODMJSH3DXT2hM5dYYrEX5jsJNZTQ+cYwPQI3y\n"
- "ykuvQIutH6ipz5MYc9n0GWAzDjLq1G8wlcEfFXQLD10=\n"
- "-----END SIGNATURE-----\n"
- ;
-
-/* Onion key is actually a signature. */
-static const char EX_RI_BAD_ONIONKEY1[] =
- "router fred 127.0.0.1 9001 0 9002\n"
- "signing-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANByIdFOKA3r2nnWyLjdZE8oGHqJE62T1zjW/nsCzCJQ8/kBMRYeGDu4\n"
- "SeUJJ2rsh2t3PNzkqJM14f4DKmc2q76STsOW0Zcj70Bjhxb9r/OfyELVsi+x3CsE\n"
- "Zo/W4JtdlVFjqevhODJdyFNLKOvqwG7sZo/K++Hx01Iu0zXLeg8nAgMBAAE=\n"
+ "MIGJAoGBAMJ1zsaN0EPSavqoy/FCS/fbm4MYJFcawEbMmB6mh0cQSR5koddyHeFO\n"
+ "eQZAs9kAPgSOU7Ka1eMTJEZxYqOY3vsqUojdwqV4KGsSaWhPck74D0pZBEK6iaXP\n"
+ "5R7dfo4Z/msPV0w7lWRkgn1WXCEq9Z6RXeW+82kZlq4tgQtwh3xvAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 /7/sDb+3+thHiWZXH68d2q9bVT8G2IPra/JyOrwLH2c=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "svABTGDNJOgaiPLqDlkRU6ldYJcoEe2qHlr4O30lVM2hS3Gg6o4QARL7QRt7VepT\n"
- "SruR6pE83xOr7/5Ijq5PlamS4WtODMJSH3DXT2hM5dYYrEX5jsJNZTQ+cYwPQI3y\n"
- "ykuvQIutH6ipz5MYc9n0GWAzDjLq1G8wlcEfFXQLD10=\n"
+ "MIGJAoGBAKmq+DEg6AMhSUN7MFblSU3TcDg6fpmHANdELEKKIfSTu0uzjqpctZ8J\n"
+ "GY0BHAFx/ckd3Sz6MFYo6UYgsKw93349DFG8KNTwxZH6ZvD1MhLQf1YcT2GRxGIZ\n"
+ "lnisR0FRM8sw1d6gWd69wet9McE0+2BwsD2HgZDmHG5IZfNBq02tAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key 5VBTNKFPXQyw/SIdNg7zgW/pXqTh+VKIo8kObZQU5Go=\n"
+ "ntor-onion-key-crosscert 0\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABstQAf+/7A2/t/rYR4lmVx+vHdqvW1U/BtiD62vycjq8Cx9nAASWPz85p2Es\n"
+ "QOD8JH26Zc5NWVauFqaTtoOrUnddgpfabhbugZ8jugBc47D9SJhkIMp3EfC6GlPw\n"
+ "W3vOM1ovpA0=\n"
+ "-----END ED25519 CERT-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "HY3nfEgabs7A4X1xrKk+4aIZGhrXycSXVaS7Xth0WogrNhK342+OfFkl9VdhYDpF\n"
+ "SLAw54Vu4M9t18fQtDPaVANujrsvdItkm9YEnOATgXR4vFqBDWXO6NJjMpnmkpYR\n"
+ "6OdOu2FpKi5K+WYuUUrkabeXdykPP11rmLx8QGfXKng=\n"
+ "-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
- "bandwidth 1000 1000 1000\n"
+ "bandwidth why hello there\n"
+ "proto Link=5\n"
"reject *:*\n"
+ "router-sig-ed25519 W6O58DzFB5fa36RszIIcRUgLD5M/7CeVEXPjgfn/SVn2EXz2TMzTqZvJpEMSDWx++ZDvQ4x9VCZB35Rvu2SZBw\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "Cc/Y22KFvxXPXZtjvGIyQdjm4EMhXVXJEBwt8PvK7qlO1AgiVjEBPkUrTQQ/paLQ\n"
- "lmeCN6jEVcZ8lNiVZgzRQ/2mTO3xLBPj26UNSDuouUwZ01tZ4wPENylNYnLKv5hg\n"
- "gYARg/nXEJiTVe9LHl99Hr9EWWruRG2wFQjjTILaWzI=\n"
+ "tDz9zY+0EzMa7m33Bu6D1GApdsSh06uoVGKpbXT2FqQEa/Pl3xdkNURNIlqMqupi\n"
+ "riyUaVud31+fQtkqV+KpAHBYCfKN6eT6KGloocCx8eK/w22+O/vAnF9wviDJLcg5\n"
+ "q5LyGgs6ZGO6x9VfOScemj8BRjBQ5ro4MRyzSekm3ew=\n"
"-----END SIGNATURE-----\n"
;
-
-/* Onion key has exponent 3 */
-static const char EX_RI_BAD_ONIONKEY2[] =
+static const char EX_RI_BAD_ONIONKEY[] =
"router fred 127.0.0.1 9001 0 9002\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstQAW1xClFKHwnXFI+597t7/uU2mng7CGM9sc7FRKee3UlfAQAgBACPfVQl\n"
+ "9cApxwShdfQ9+w4Akbp+zzrxQjJLwq0Qe7qvKgyl7u1hWyJH/aguIbkCQDPhDUsj\n"
+ "Mc5xVdNamPsWuPRIyxKJLQ9+bhJtUeI3SYc0BwMCUzP4a4EkqeGvvbOEvw0=\n"
+ "-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAKP1kWHsH/BZhNSZmn0FyzIrAHtMl1IVPzc7ABbx+kK+IIEMD9k1fy2h\n"
- "AP2JTm2UmJDUwutVxPsxmndI+9QsRDpu33E5Ai4U1Rb6Qu+2BRj43YAyg414caIu\n"
- "J5LLn6bOzt7gtz0+q69WHbnwgI4zUgUbwYpwoB7k0dRY97xip9fHAgMBAAE=\n"
+ "MIGJAoGBALiWTCyh2ZwplM4DQDwQ1DKVmTInxsuILLmv8DATTZXyMhsBnHf7UPTf\n"
+ "qYZz78V/bW5JSluXYPaLvt1ZteZelLAabbaTl9ezmH0unaXQ7K4lE+Ige/rA0Vfj\n"
+ "YKF/MLdSsEeFj8pAomQvaqUoBgByGHz+eLLVcSAGTvl8hiEXTBSjAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 j31UJfXAKccEoXX0PfsOAJG6fs868UIyS8KtEHu6ryo=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGHAoGBANBKlyoqApWzG7UzmXcxhXM4T370FbN1edPbw4WAczBDXJslXCU9Xk1r\n"
"fKfoi/+WiTGvH7RcZWPm7wnThq2u2EAO/IPPcLE9cshLBkK28EvDg5K/WsYedbY9\n"
- "1Gou+7ZSwMEPv2b13c7eWnSW1YvFa64pVDKu2sKnIjX6Bm0HZGbXAgED\n"
+ "1Gou+7ZSwMEPv2b13c7eWnSW1YvFa64pVDKu2sKnIjX6Bm0HZGbXAgED=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key wIOhItdhRuyT0Feij9xNXTEPuV9mE6fXU8Y6l1Mjjx4=\n"
+ "ntor-onion-key-crosscert 1\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABstQAY99VCX1wCnHBKF19D37DgCRun7POvFCMkvCrRB7uq8qAEYfc9irhCYM\n"
+ "WseTLWwjMSClI277sp1lzy1Y7PN/tlQqZkG1mRcGELYARY1cWkj4b2G09oKY41TF\n"
+ "1+EG5BTCSA4=\n"
+ "-----END ED25519 CERT-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "E/Sq3MBmp6wnl6QQXI9pt+B2cGzepUMuOvb+v9tN0+YHE81VRHzXORq6kEVRvc5e\n"
+ "t/7qpynQ9QcsPMfPHr/6hFJMHvBKJAKl4ulbdy+dIkKSiwhgp1bXqUV9GoUjDAHy\n"
+ "fw1CA6oKififqoMVqZN6infAVIo7yl6OPAhY1yZLIMI=\n"
+ "-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
+ "router-sig-ed25519 Iw6AuWlz9lT69zV9UjBWiPrenfnuTITlv0YxJlJ00k2kzQTKOTcbEBYrqbm1uDWzgcLqtw2BI48V/VpE9JzFAA\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "cYcBOlapA+R4xq3nn5CjpnzNXdDArMlHuXv4MairjleF1n755ecH8A/R8YIc2ioV\n"
- "n/C1TACzFVQ12Q9P3iikVOjIXNxYzaz4Lm/L/Lq4sEOPRJC38QEXeIHEaeM51lE6\n"
- "p6kCqXcGu/51p5vAFCSiXI1ciucmx93N+TH1yGKRLV0=\n"
+ "U15TJrcDOWr7qwtZH46wpAfSZlN/oinnf0a1wPEYQvHditLj6WgH9p4/r0BT8dI1\n"
+ "hi1Y6KWZhMx7/Qwq/MyigMeQelHV2caiWEySKqqfxfa7yore5+ismj0quBTCJaWv\n"
+ "3sM4zWkwaVPvTNtz1btsJYkEKWG3NvPNcZHpxZr2dj4=\n"
"-----END SIGNATURE-----\n"
;
-
static const char EX_RI_BAD_PORTS[] =
"router fred 127.0.0.1 900001 0 9002\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstQAfb3eBF1wYkkPlk5AHyDmRwtEQDfd7pzfAYRcInfzwnvAQAgBABFNYwJ\n"
+ "gZyXCSt9SbuYCDYXpKt4cPuAW9BCmRHABo7BUcRuOWtfVn0zH5qs4V3490Anu8p6\n"
+ "KHYDAiAS2gfcnTc2OCz1iw1rY1egGjH5+uUIjckdftghs4QOghLVmyUSHQM=\n"
+ "-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANVi/MVWhzT5uo3Jxw4ElS7UGmA24dnckdkCLetMhZOcE9e9mg4WcImL\n"
- "NuBe2L/9YaL4PFVchCGlq73phKG6yFdqJdjDV8Qh9MJdAYWW2ORrjRvCrspPaYPN\n"
- "BGJrkD2Gd4u3sq7f26TIkzmBx0Acd/FD4PQf8+XOt9YYd36ooS4vAgMBAAE=\n"
+ "MIGJAoGBANKi30IsA+x93+fyVJjP8IC3iF8TWe4lJsYbTCvfcJa0+j/GSPLdxClT\n"
+ "AT4QJkNCNgZcJmo1QqiFAUZHeWs7kKhlSyQT7YLrpSlnjRIBwPBn8ddAY/X67tpS\n"
+ "eXAiWzhpEuzHgle3nCQMlYNUQJp0Yyj6UvK9SiD9B/WCs/ICmWzDAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 RTWMCYGclwkrfUm7mAg2F6SreHD7gFvQQpkRwAaOwVE=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBALtP4cIpAYp9nqo1ak4SxALcndFw4o51U36R4oa+uJS/lYQPHkMMOj6K\n"
- "+AVnj9sxkDJ1POaU5lsCQ5JPG1t+Tkh7vDlJb6RCUy25vJOuaQCb9GVVY7KQTJqA\n"
- "E0fU73JdKACNjMlbF36aliQhrG4Fq2Uv+y7yp8qsRxQ8jvzEMES/AgMBAAE=\n"
+ "MIGJAoGBALpZKULTdehX4/NbsioiJ6i3m5YiUe0iKpRnx51VkFOd0HaRdfY1AEyo\n"
+ "FSQtRBYgzugvd6RnWknzcl5r3f38irYS1aAidS4fkTBq1Ce58Yx5iiaHIjylrFlH\n"
+ "3f9N9m/mny5l0QgGvqI+dl94/zr80hDDSxrlH7eIvcIa+BuoTfdNAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key qR1PUvc7ky3rgJ6mWwjNo1aAQZsFZDsJHVy8akTgHls=\n"
+ "ntor-onion-key-crosscert 0\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABstQAUU1jAmBnJcJK31Ju5gINhekq3hw+4Bb0EKZEcAGjsFRABHNkPpYhab0\n"
+ "ehvtfFPDt90wzDnWsebaqe6EZe+bPSrZCGGDMjgs/1VajEK09zH0FV/F3d5B+XYw\n"
+ "YegiFba6mwE=\n"
+ "-----END ED25519 CERT-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "QJCikM5x69I4ErNhwwLTGZ8utGy9P5NjAK+T1BgPOkJJJTzLWz/t5AhLUorAmvC3\n"
+ "fa4byUrVFX8wO6bmnMINaBDVPVlVVcWp2fclI7f9l8q/oCp1GKdmYnyky2RxoXoK\n"
+ "qJBi5CnLCRjpaO36Y4OeUld5jr3gzezDmkD7YQLtzAc=\n"
+ "-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
+ "router-sig-ed25519 9tBjrFWWzCXx3ZUUgDHXykKsi+9sOoSYBneo+QZMtgWPJnYH16sT4eAQ0Y0PYd7OlXOZvOB5u3JX/yCujJpnCA\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "xzu2T+pMZtdsS5q1cwXM2hMIH2c8mpAV31G2hKIuiQRwtPD1ne4iJsnoVCXhFakd\n"
- "QTq7eTXM174fGWyIT93wvQx/Uqnp29dGZp/VaNOsxHFdYVB4VIVqkBh757h+PSJ+\n"
- "VNV5JUm4XQ1QbmniJGdTQp4PLBM++fOXMR3ZNd6rt4o=\n"
+ "AKtLxm4FGx5TawJi8kKQL5X8SyQTcDoyHXM+MH8SGjsx3tq560HCK+SGSeoWayGa\n"
+ "s69aHl0nUmH5UMnDOdiWPZqzTi+K5kmO3ik3zkSZQ7/XsUMl+o6In3OkxQrqL7ka\n"
+ "Xdqh3Zz3MT5DE6LBvTSRjnET1Bocfx2+bqkYpUEpxyo=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_NEG_BANDWIDTH[] =
- "router fred 100.127.0.0.1 9001 0 9002\n"
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstQAbfU59VhOWlweNlw/DQgCRjBh7EtF0hewpRHsuiVKUnTAQAgBABEV12f\n"
+ "2PB6QzHgt/bGosT8rLoBpR16XSi8aqCdurCvr4niKEyudgp+d1h3J8UyB7stQ6T7\n"
+ "qaKCyhXg4v96Rctc8nbi/2HMWvPj+wUqc8ArTrVSH8b3XPijrBU1RLTeFgU=\n"
+ "-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMCG/ZCXNCF02uXRSCP7qWBN75jDMQZ363ubnQWhF9KDDNWWiwj3UiZR\n"
- "zqsM4zKRgjtarWZvp2qxKABFAODd+j9iq5DvUGRbbXv+aR8TT/ifMtwwxHZQBk1F\n"
- "1hbsLdwWzGIiyz5k2MVhXnt6JTlklH2hgT++gt9YTHYKxkssaq5TAgMBAAE=\n"
+ "MIGJAoGBAMTLuiE+qY3Msi3rgMQ6/jLJu3JyunkZ1MqMTgdqwLi7kPTQHUKg15v+\n"
+ "6xUpEJG9lgdn55OKx4EWda0nntm+TvmPg32ijgX9+hfmQ/euy/kgfrFkN23JAa3k\n"
+ "myqNj9p/LcUML3QFHi7V0mQkcNvXPKOQ001JqW78EGxBccuFQcP7AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 RFddn9jwekMx4Lf2xqLE/Ky6AaUdel0ovGqgnbqwr68=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAM3vk/4kOTB1VXrve29JeHOzNUsPwKruBcjxJf+aatxjf6KO2/RW41bM\n"
- "gRYq9V7VAYeZTsbS727fy03F5rk3QIBhMJxm9FHatQ6rT/iEDD4Q1UZQsNtm+OLf\n"
- "/TkZZhgfB3MiDQ4ld/+GKd7qww8HXTE+m/g1rXNyZPKozn8K7YUHAgMBAAE=\n"
+ "MIGJAoGBANKNi9dzOok4QWBoT//XU/ok0UySUyZH41gNH5AM1kCMC34DNvfcTnHb\n"
+ "KG57vyi9fUBQPpg6dOTav0feit8v6Mm18v0P1dMUzeFiiu3HjEeoEhpfCRyUGbtd\n"
+ "LSaLLyLrFbM0Ejhh/DJXOdtSKBdPCgdRGceq3z1zihVvqOypm5eDAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key cGIQnSfgCDYXatS8Iiu7MN8iLAoFVageRdeDYd6Y4SM=\n"
+ "ntor-onion-key-crosscert 1\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABstQAURXXZ/Y8HpDMeC39saixPysugGlHXpdKLxqoJ26sK+vAC2ouHrvGEya\n"
+ "blACfJBgviThszToS+i4ohSdWOXVEvXflIQPjttaduf6+B6YwLTcXnmCVDEq8Z0o\n"
+ "Qc1FSGXkLgw=\n"
+ "-----END ED25519 CERT-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "CN6jEFhWkQ3j46kbqRgfH5ngz6exkJj000887E7oinmWITJyVA2oX75NeU4uNdt+\n"
+ "Qrv7bjQIvKyJ+ThzW+E6lNoDbd2Nb+9TkK25tOO7QEzWMOeG2ASvI9NOVlzOktIh\n"
+ "w80DXx5kYgYQ3diDC136rkU4BBdnQDX5aryIqvhESEs=\n"
+ "-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 -1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
+ "router-sig-ed25519 GN+uBj6dVw//1wQfItXo//CCQxgse+Ch45REa7XrJaJJHlThviicTmYL6gH4Ft76n6QElNppbys7MJpL/KuNDQ\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "bUBBZYZWqCbsH4/7fNXtC/HgIZNGOfDF9v4d9YfKaDs5xDYf2o67hRcwx5imhrgC\n"
- "IU7n9AI4AGxkFoN6g3Y/t4pqebxdkF678rRDCtrlwwreAiUktgrwnetp9Tpo16xj\n"
- "V7Uf6LcqQdvu78lRh1dsrY78sf7sb90vusFMPLXGUKM=\n"
+ "h0ksY36ssG9o8ypJM9gedjDsw816vTOKhiJfaiC/jDdj95aflz3C/WfVviwVPrru\n"
+ "2ThlVuJqESbBykEsW7zBQxJzR3m+1xo3aGpyK37pHx2M7Ys1NkxravfvTw2MVe2C\n"
+ "ZSORjIQZirKTNq9OAPF6h/xxiRvI1tlvMBN6bfeyVe8=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_IP[] =
"router fred 100.127.0.0.1 9001 0 9002\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstQAXBpI4NGHpiYtqH9QSueuPqjGjV+NwTGv1Wr7AAEr/lAAQAgBABzxwnC\n"
+ "88ko/02rKCpajAup4icjbr7R2Yzj4i3/d36G8LmUMVTI8TRIwjV9CMQehqfNWMq7\n"
+ "Cmm5b79vpKgjk7ahT/UajbwPxdmec5C72pUiszuTkAdh7OLFeA89BUPkYQQ=\n"
+ "-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMtMrM24AJpJCevxnseIpRlSuAIMksfkfky2+noe7Rok8xn6AMQzMrwx\n"
- "AiCJ8Jy4DBzIKUiJK4/y1FimyM08qZGR0xeqblCxZ1lbSiXv6OYxoaD2xmWw8zEP\n"
- "Zgu4jKReHh+gan1D+XpAbFNY0KrANhjRo96ZZ3AQsZQcWBiPKCynAgMBAAE=\n"
+ "MIGJAoGBAPG7HhynsWUO4hRHZ9yljs1/DFba8wuw56k//JLHDaM7GXwvfOjzTznZ\n"
+ "Iz8GjT7a0s+XvIqIwBxxUfsffAdRpoUVoJGTvcuLrbYTjVvhZ2rKBgXk1Dy+HOSZ\n"
+ "rF7/3X7n73Jw27g07yB4Ymz7pCrqFTEdHUSEe998IE5yWRwPcJKhAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 c8cJwvPJKP9NqygqWowLqeInI26+0dmM4+It/3d+hvA=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAOPclmBO/amw1RWTSI1y80qY/EPjc0I+sk9HKr0BQOovxqJ0lmy9Gaue\n"
- "y+MOejQ9H2hNev0nd7z1fPxEogt7SCe22qJHHX3xDf+D9RpKsvVzDYZsk7hVL7T1\n"
- "mwHzuiV/dtRa7yAMp7+q0vTUGesU2PYFYMOyPvz5skNLSWrXOm05AgMBAAE=\n"
+ "MIGJAoGBAMWXC95x/pQF+LVa7Z2LKjuL1Zow6+I/2pK5pxqwTv0LiZHEjrCq5Yyn\n"
+ "cXobbDuQqMIQs9MiZl9mceXNz9gORncgN9MGae7mAcQFJIH+Hv5Bp2h1QVpjllcl\n"
+ "yhGFtDVfGjOmr1AUAP2gR7GsmLMzjH6bUtD0o8JujF683x6VRGTDAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key Ue8UgMdiy+jJN+u+N304hAjGzli0ckutdhwTwpJj5Bs=\n"
+ "ntor-onion-key-crosscert 1\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABstQAXPHCcLzySj/TasoKlqMC6niJyNuvtHZjOPiLf93fobwALDJghOhBUQ6\n"
+ "PvjUF4HdnKk94mFUnVEuXhbDQkqVpUSwqaDgs8pvMps+kysskBrQT9m8UdtvFg+b\n"
+ "7hC2d+i5iwg=\n"
+ "-----END ED25519 CERT-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "fmwhrHV1jQWhrQ3GnQZoY1l2LPcw0kRMEobEyIcDiy3hCTQDQcaChlTVM+fzmcoL\n"
+ "3aF5FFn7UICK8NAJ9P2HyyC185+KEoLKF6haXCMiTWye0tVN/pZgxvwY49WBEkfs\n"
+ "yUcQa9Ixq6BxBjyxaDvsp7zXcdhFKYU3ukI3IAFVlqs=\n"
+ "-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
+ "router-sig-ed25519 +GEY9H7Q+FV5nimwaLadRy4etG7TgGCKal0LqFhHc4L0dXv8EtcplaKUDxivN2u7bm05enwRWr/z/YxvAiR4DQ\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "g6besL/zxOp0N6Q5/7QZgai2kmCU5EAWJlvZrf5jyrjKhsv2a4LDkap07m9QRFqW\n"
- "GGe7g5iiABIqnl0kzv7NLX7ah+d/xxv+IILXyZfVTxSw0e+zFb3uPlQ7f9JsGJ8i\n"
- "a+w8wyyDBpOAmi8Ny866Cnp9ojVzCyIErUYHFaPvKao=\n"
+ "0fO8rKE3VjyjmF506pxkOH8tIHaN+VBVQViRPE/JmCzBPnaNPIj3FnSaQ3lowlzz\n"
+ "Gy4JE8+/6TS5t2C+MGHUsfTlTZOudtnd09fF/FGERljzzGNx4ABEhGIxf79TG3rj\n"
+ "H0bMCfO3Q1x7X01WZ7f7kreVWC5z6fbrcCgvR7PIxuw=\n"
"-----END SIGNATURE-----\n"
;
-
static const char EX_RI_BAD_DIRPORT[] =
"router fred 127.0.0.1 9001 0 bob\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstQAeSXj4cWNVaGVBdAZZDkDAdmQFTUpxHYo0ux4eoc7bytAQAgBAC4EaEq\n"
+ "+La3x6f1fJqlT8YhqxetiSdlhLPcFkeWLTOTf3BRXHAQ1EVdiSu76J9il/gn6u4h\n"
+ "j7jaUEIf3v6WovHJ2qAy7wiJRDuXO3aExat3RLJCvqvkaQjgrKFYAmlpDAc=\n"
+ "-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANKcD6DJ16X3yvdq05jatdwgjO+hyoIpckW9sV/OkdfIZwf+S6Q4pZGC\n"
- "doMw5XeOM52gjpx42kUp6M2WlTGDFEpaNU0VyeZYG/M1CM1xvfj3+1PoebioAGdf\n"
- "GuhNBCHZdaYNiOGnh9t2GgUomgpE6njdS/lovSrDeTL469hfcUghAgMBAAE=\n"
+ "MIGJAoGBALJUtCdVl3BTyy761sZAnKa8N6VOT4QNBLSXxbmVOExMbyr7AVTvOeNk\n"
+ "rrcDbKj35e6fcEFaJbPWHBuHCcRqH54BI2nD4CzR+t0RFSXYK7ZbyM1mhRR4Kshg\n"
+ "WlEAaawZiXte09FAaSNZNrkzdQwXy86JXdZjwjyegfDRj9aaxS3xAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 uBGhKvi2t8en9XyapU/GIasXrYknZYSz3BZHli0zk38=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANWeGHig5wE9UijaNnEW5au3B3hZKSlzCi+T6MYDPbbYhm8qJaVoXUXF\n"
- "EP1EUgzDcX3dPEo9upUA1+91GkjGQCo9eOYlqGib8kHIwKnHZK+hernBc/DnOeUp\n"
- "Wyk9SW5s+fi12OQhr3NGjbSn76FMY9XU3Qt7m3EviTwWpI3Jr5eRAgMBAAE=\n"
+ "MIGJAoGBAL5TunHoAxAC+j3w9P9KmspLn/xl8EZZUfovx9gJ95S/R7uPZYMY1Cdf\n"
+ "d0sObKeV/bdO+7EUT2dpu6ngMj+sS6xam1/VhI0DZemTVHVGh/NOr4P/5Gtgd5+L\n"
+ "g21nRpc77sPtFibJSHhA8M3LGbwZEhbtje4N6r+HlOitX6u69z0JAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key XHq9XhW9b+fh+ZTAUiZw835EI5QzC0t353VeYWUrQFU=\n"
+ "ntor-onion-key-crosscert 1\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABstQAbgRoSr4trfHp/V8mqVPxiGrF62JJ2WEs9wWR5YtM5N/AD84uDUsUs8x\n"
+ "FOOzaneZZrA38hU/7ocJJ0c8uyAHyJ2FKGsRrLvtK3dbrb1WEyZMTF4U0Ht5tF9h\n"
+ "FYNzHcqFBA4=\n"
+ "-----END ED25519 CERT-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "plpu9CjEVOV598popgY9KpeKyXYdhgV4e4cn8xq4ulQOAmqodjw5cd8iEkXYQF6z\n"
+ "g6LT87XHdyLbVOa6Diz8ed7lX6gV0bNLId+mfu+wowTCKp9NxF/+/oZGF6gHrT9z\n"
+ "XsoRUk89LO5JhHMhHH/WdHNe+d6EQGdqMC8oDzrZlTg=\n"
+ "-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
+ "router-sig-ed25519 iIG3Qv7UShaMwFLJRnoplp6iS/Y+oz60D5hLbE41zpH3CzHNz/5dkbDrss5yMWPyWyBC9bZzUytNusyjBWjaDA\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "t77wEoLjyfMf9LKgBfjveosgwvJ8Go0nb27Ae3Ng9tGtR4qaJQfmwZ5fOOuVU9QC\n"
- "3s8ww3aY91KD3NTcN3v3FKngxWtRM8AIfwh4pqT3zW6OSP4+nO3xml7ql0Zf6wfj\n"
- "TPFV2941O3yplAsmBJ41sRSWizF04wTtZAIgzY7dMLA=\n"
+ "eK0fcXaG9ZE5PseMnntHv2PQwEiSZZ3T+wrpQb97MwgIrU0zgBPc8fZZemMpiJ6O\n"
+ "f+0SziFXrYWPOOji3fATBHm1w132bE/0lDbUYf17tHMq9/Uvy9cA03f7Vt2+A9tW\n"
+ "xG0iqGpeqoJqg9DcYXbzB58tGkTGwVwSba6MXBRJSnU=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_NAME2[] =
"router verylongnamethatnevereverendsandgoesontoolong 127.0.0.1 9001 0 9002\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstQAXPRPZ2/Fwcf6Y7r0OZ/DsY50YcgEUsDcYU9SNPRJRolAQAgBAA0NkVW\n"
+ "i3wAeoIg9BeSaD11/nqc5+lOqxsRW5KgrUF5F9EaBcn1mK8QMpZmStY2pyk4PHtE\n"
+ "dAHvytGNgzllNG8ZqCYWQbB38OcYIVp6snV5P6O5FVDzoLHKxB2RZq9CKA8=\n"
+ "-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAL0mcUxg7GJ6oxgciLiBCbo+NuZ/OVKRrERCSM6j6iHERcB9+ciSRgQ5\n"
- "H6o6FUX2LoRmHYzBk1x7kIjHa9kx9g6CAbBamdZrQbdVnc1y2NrdHB/jvwLj3C48\n"
- "PgzFIrLg9OlkuoWck/E+YpPllONfF65e0+ualgVjPgpQpXwmz+ktAgMBAAE=\n"
+ "MIGJAoGBAK1B43OIRWXV0MifW6xipNWJbezgje3v81ks04dgu4nNi/4opPzV5wJU\n"
+ "3d244I4/KlRgzY4L7D/mxBYtoNtpC2Dae53TkgnLAwHdx77XkoEGuQMjFUtRxejj\n"
+ "KtVUZW5N5kDCG6bItzpmULvRmYoJa0kSGn5nROo4CCiyJSX1tK6xAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 NDZFVot8AHqCIPQXkmg9df56nOfpTqsbEVuSoK1BeRc=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAOgHvvTAxyjJtHx9W2X7aOI05H9sYDDY+sxhovT/8EpAHrioex54tsMT\n"
- "ifgtoXTjGIBEOTDi/1ry39nEW5WPbowqvyzRfR2M43pc96WV7e1nhmD/JrnTYgtR\n"
- "5/15KxcMJxoDhod7WZ/wlXBnHc2VevX8JTaeOe9KYORCj5iNbtVZAgMBAAE=\n"
+ "MIGJAoGBAMWiMIxbssLwJpiCvHvZrg3sbXPMLu/EN3naP1PI0+R2NrlU5AAIEw2X\n"
+ "NeK4LJyBdO4XXBFL+R3HBlUcXjzphHWxeRgYgg85AfF1xhqIgXpzA0AgGRaQ8GcZ\n"
+ "5BZm8fBg8CRiS/DLIgwloQmvOJcUDqYLWqvz91zxeGHK+92msp0jAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key J7+npqmFouE4EuXuQAbhc8d6lGGab27mFTQLeXCnAzU=\n"
+ "ntor-onion-key-crosscert 1\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABstQATQ2RVaLfAB6giD0F5JoPXX+epzn6U6rGxFbkqCtQXkXALDsSLNkQF1E\n"
+ "8OpEiD4TyefBcLptg136A7UXqXbC1nWC+xUHYBCgkI5ymEtMHOn9bpl01ULisRH/\n"
+ "29OEIlRPwQQ=\n"
+ "-----END ED25519 CERT-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "tVZrb1HMx1OCvD61ulJgLwwRZz5mLv/qmIXym5JaWApvKPFwUkTeqlMKVD6HwmQq\n"
+ "FWAVIvqZNSA5jkq5PJ+LpM7QBuUrA1tuDVnieCQKpC+iP3Gs9c1aad7jrpciDB9A\n"
+ "MqaJkfketFTtOEa858NWMO/bHAIjcfnGHxRVf3vwIQk=\n"
+ "-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
+ "router-sig-ed25519 +ZJ6ovLWqUfLCwpGqge14MwQfPiWhQYopxbzQQKPtgHnRO5qaMb4K7oIKmMkmKaDchTrz0WyIGFZez6u40qQCA\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "j/nFT5gyj20cLHWv94O1jmnqy3n6qkO8Av0OdvvfNeXsMK2UHxk84vzFvEwpUF/Y\n"
- "i+VR3LXY4CjTpuliMtjt7BQGtmJSvB8W0CeIUenIGzfwDxW9dG2o7spDldKDB/OU\n"
- "C1wyHvKaA6Yss/02RIDa4AxyjsfbgdJ91qK+aAnYAtA=\n"
+ "PRiWQYy6k2mmwHHkP0AvQN/r318tQXWGzkNBlwoNwewVTRbq0J6Ds9aIWHAijd4b\n"
+ "vW8E+AHWt3so1ucjq2ix5NwYInhiGHcTSRUqGOKo1WtgcrmGP00g5axZCVxsRDRf\n"
+ "Ev4TNKSLXDRvblNSpYTccuTc/ExvKREplVrajjxN0X8=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_BANDWIDTH2[] =
"router fred 127.0.0.1 9001 0 9002\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstQAYnSPlxnc+nZZZIokyW+85uwJkjxUDEqTweLYVXCtdekAQAgBAD9bAif\n"
+ "9zqaYAZfgnkiER+TADvD001LseJa0fQEPA8EN+zx+GpjHP2yBU1ZHPo4rtIDoaCl\n"
+ "AioFwzs546cZoZGJsp7U6NDvncqIcu1rGEeOk2MK9Tw7Bfxvi5vkgEO6wAw=\n"
+ "-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBALQDCm9VEopiYILmt4X9kP6DQazfgKnLXv+6rHbc4qtmvQQD3TVYbxMP\n"
- "F4sEUaz+YHAPnomfDVW3a0YFRYXwDzUm1n47YYCyhUzEaD2f69Mcl/gLpKdg+QOy\n"
- "boGB1oD4CStWL3y05KhxxTNiTrg+veMzXTqNwryCYm+GoihIAM9fAgMBAAE=\n"
+ "MIGJAoGBAMWlPXGRLRI5kHuR7pMHD977D0XkwSJ5QwrFnbi0FVG5tN79nRRfmZcJ\n"
+ "5DRQAJu35CFo8wgHTJDec9/gXu1gjjDq6SfIcEVjIF1JX/pKC9+CpYbqhGBxTJLg\n"
+ "ysPqgQDq4PdkqSU1FMzcW08FOXmVZCkPTm0J7CwKIefubo/IghjZAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 /WwIn/c6mmAGX4J5IhEfkwA7w9NNS7HiWtH0BDwPBDc=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBALYHwdx6bmYy09AW5ElN/DWh0fHh3mBK97ryiIMi8FImYfzbw2BR6xuT\n"
- "aQT5omqS3PNJJcNWZt5gOyDtA9kLh03cch7t1PenXSYJshbME2bDrZDJKVJMN6vV\n"
- "B1v/9HjXsVF50jBzZsJo3j26XCPT5s6u9wqUFWW09QR3E/1HInHVAgMBAAE=\n"
+ "MIGJAoGBAK80UOCQiPEWjOB8yPslBNOEPFcK5AKeA+hIIh6FFceGYxeiIWF5LBIC\n"
+ "5g4dn1GBlUcPX3P/d5m0DXGnGPskwHFyQLpFO0ga4F5HdirTnEUMiko0Nonbrseu\n"
+ "F44Dk+x/KGa1B+8Xr68HZbJGf3kHSlGVDFwVnSBwmRsMjTkW8qyDAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key wrcJB+L6TYel2UOh6d2/11nrQI5TePnxJUZZ54NUShs=\n"
+ "ntor-onion-key-crosscert 0\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABstQAf1sCJ/3OppgBl+CeSIRH5MAO8PTTUux4lrR9AQ8DwQ3AK0mat83aPjn\n"
+ "XxaHRYZ0M6qHd5NhM0z6RGtw1SmT4AtK1g0ZkcVdDhgzjdu62Y5tU0pzBlK0A9Pr\n"
+ "BW+haJUp4Qc=\n"
+ "-----END ED25519 CERT-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "JDqs9wmPisHZOZ0s2Dj6E0jFvFhy6KcXuH0De6Ssud5TJqqY8RNOruJA+OIc5/mV\n"
+ "7rAGsedOETg8d37D09q35RPCPNDC7Ja/Xud0BLeB2VBn3AwxDimHLtp6KyU93CzC\n"
+ "nsUu8iblk6M/hPiinoo8s2qRWj3CvtX9xgkWxrfmI4o=\n"
+ "-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
- "bandwidth 1000 -1000 1000\n"
+ "bandwidth 1000 hello 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
+ "router-sig-ed25519 c5WgGlFiqkcoxrblfnz6S14En3b3F6TkHEqYDg3p9BHA0doDNntOiOJZr6y1hxuZZVxHkGyqz26wqHl1OXWrAA\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "p09ijyuvcW+WKRj4mJA/nkLCvZkRcMzykAWheJi1IHCoqhXFdkFLiIRqjaeDVHRr\n"
- "zBtD+YCQiGvFcaQJ9IUhh7IleHcyyljmDYlvuBAxWiKvVZstJac0kclCU4W+g8yK\n"
- "0Qug3PmGKk115x2TllHaCZqMo5OkK4I/WAsKp+DnJ1A=\n"
+ "Vkqau37qjImmyVIa1+w8f8JdXAFiQ1js7gTmkHBxNJrNpNuwAIogOt8KVDwYL3yV\n"
+ "fR3I+kRNjbWn5PfKY8fENtmwj25IpOeJB1UcC3bBpfaUHnUYj4nNLoOxfKO+cOoN\n"
+ "uUhb2jyxJzbSFLuPmIlD5ZiDK9cT/J+Q/o36Ll9TLXE=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_UPTIME[] =
"router fred 127.0.0.1 9001 0 9002\n"
- "signing-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMM0Nubr1VXQ/FcgIQTFxZpZDlAEh2XN8FoJ8d+X5S46VDGijmMoYmyN\n"
- "oLXqMTGmOaR0RGZOeGLgDzeY8tLrfF821IjfkXeAANZibUjdsHwqHO3wlWD2v+GN\n"
- "0GBocWXEdAp/os229mQQKgYAATJ0Ib3jKhBdtgm5R444u8VX5XnbAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMpyOr4kEtSTZw4H9eSkH2+WmwIlO4VBpY2HkPS00l6L5fM2REjt50Xi\n"
- "lsNOz8Q6mAn5cMYmsGlv61kg01mCvYc7Z715jGh+1hhVAxMaNS3ED/nSPnslyjhq\n"
- "BUm51LhYNHD4ktISIqPMurx6aC8B68UYgKzLgCYNzkathFXSBpjRAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "uptime forever-and-a-day\n"
- "published 2014-10-05 12:00:00\n"
- "bandwidth 1000 1000 1000\n"
- "reject *:*\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "NHYeiQOu0nZdrhSy31Xz4F0T6OTU23hPQDzoLax1/zq6iTVrz9xi3HGm7HhOMW1j\n"
- "YgFGK3+Xm4iJL+DwriunsAIuL5axr3z2hlmFDQHYItP//KyPpOqSrfEOhwcuj/PE\n"
- "VbWsiVYwz9VJLO8SfHoBeHI6PsjQRQFt2REBKZhYdxA=\n"
- "-----END SIGNATURE-----\n"
- ;
-
-static const char EX_RI_BAD_BANDWIDTH3[] =
- "router lucy 127.0.0.1 9001 0 9002\n"
- "signing-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAO6HrITQTEjV/v/rInQ2REmCFZa4dZg8zIh6+B51U/I6hDiZaKGwpNey\n"
- "9OfjoRqT2DwyLEe3ORm9A2RAz2twLBixrpt5IvC0sbGustmW964BHW7k9VvRupwl\n"
- "ovujHpLIj5dkLxD15jGXHoTp1yHUVk9NkMGN+ahg6y+QhTbIrWbRAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAOEpciJFXauEqs31GMTUTzu6edBj9WtV+sIflhGKvU1KKRfwCgOcuKMx\n"
- "QiLHHD9AjhMAFGT/qtNbPFkzfYxHKLHw+NLJsxmNtdkYM26FX3ButPiX+69sq9fI\n"
- "PCHqQy6z/A7hHwtEk6niWgK2PLhAZCg9duAv+mqFVXe2QEBjax/lAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "published 2014-10-05 12:00:00\n"
- "bandwidth 1000 1000 electric\n"
- "reject *:*\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "Jk0Xk1RMJSjEflNRcp4qznaHKcfe2r0kOc7TdLAnM8zyNDVj6+Bn8HWmyp/oFmf6\n"
- "xtWKKgkKxriAVIJgqZMchPbr9RuZS+i+cad++FCwpTVkyBP920XWC47jA3ZXSBee\n"
- "HK6FaoK5LfmUm8XEU9BVhiwISXaUfTdkR8HfzugFbWk=\n"
- "-----END SIGNATURE-----\n"
- ;
-static const char EX_RI_BAD_NTOR_KEY[] =
- "router fred 127.0.0.1 9001 0 9002\n"
- "signing-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAKYDCSr0Jh9d/mJKjnGYAHKNBcxR3EJk6GGLwKUrRpN8z/aHRxdWlZF2\n"
- "lBml6yQNK/VPftcvOekxrKq3/dISrIFBzFYj6XHNtg31d09UgitVkk0VfRarZiGu\n"
- "O6Yv55GSJ9a3AZDE4YmIp5eBjVuChyVkeDFYKVn0ed4sj9gg35rjAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBALXdUQuq1pYHyYP0qU6Ik+oOmwl0eOsuwiLWf9Vd+dsgEszICX4DRWPx\n"
- "syDxfxyA/g9FEPvlI7Nglx6cKe2MT0AutSRLbbML4smfuRZNIF35Cnfu5qTGVVzL\n"
- "GWVSA2Ip7p+9S9xLhLBdc6qmrxEXCPL6anEhCR4f8AeybXAsz2JLAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "published 2014-10-05 12:00:00\n"
- "ntor-onion-key s7rSohmz9SXn8WWh1EefTHIsWePthsEntQi0WL+ScVfjdklsdfjkf\n"
- "bandwidth 1000 1000 1000\n"
- "reject *:*\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "Yf9axWyzPudnRvQstNdbtBYo7pGpUEIdECMGcJtFb6v/00pxk4Tt3RiOKa84cOBV\n"
- "7V9NjOLdqlx88pGz0DNCJKqToIrwjZDeQ8Q1yi9XClLDkC32fQRX4y6vNBZ3LXLe\n"
- "ayVrdRrb41/DP+E7FP4RNPA5czujTfs8xLBMbGew8AA=\n"
- "-----END SIGNATURE-----\n"
- ;
-static const char EX_RI_BAD_FINGERPRINT[] =
- "router fred 127.0.0.1 9001 0 9002\n"
- "signing-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAM0wDWF2dBLzsmoIDHRugzosCSR9TSvEE0TkvKu6+agfogGtkQJwQ5zO\n"
- "sGzZbRR+okO7d+QCED2i3rUs1iikoMUT+pwgvOm8Bxg9R64GK7fl9K5WuAiG11Uj\n"
- "DQAfSx5Fo30+rhOhe16c9CT7xJhj//ZKDbXUW7BrJI8zpuOnvgD5AgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAKACg1nWM/WjpUiGwlLQsY3Tq1h0RTz/HmOMx/6rTRxS5HLz0KnLg5zV\n"
- "dvmfhxqQVKBkt1N2+y+qO7x71oFzIsFMfHYWSxOCEo8Nkff1BqAPqxxUHvM0HwJo\n"
- "d7lswJ/UT1j4+WZNZ4sFIujsIW2/zZqKlxG9xaw0GXJ082Cj9XkPAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "published 2014-10-05 12:00:00\n"
- "fingerprint 5555\n"
- "bandwidth 1000 1000 1000\n"
- "reject *:*\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "mlqyJ/ZGBINKwSNEi7GpNBCMqIVbL0pGAOBYHJF1GbRlU28uRyNyeELIxIK5ZIet\n"
- "ZzKr7KPvlBxlyolScPhTJfP98TFSubrwYz7NnQv0vLI0bD0OyoBf/9/1GYlzgTso\n"
- "3mKfnV7THUalpxe9EjQ/x61Yqf26Co0+jYpt8/Ck6tg=\n"
- "-----END SIGNATURE-----\n"
- ;
-static const char EX_RI_MISMATCHED_FINGERPRINT[] =
- "router fred 127.0.0.1 9001 0 9002\n"
- "signing-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANUAvwbpGbsAyA+mBwjFkvurtRzdw9btDqNKtPImufIE+q+AFTaCnwPr\n"
- "kA7vm/O6h6OhgfdYEC2GfYJfwPGM7MDuz+NnuKxUb3qb2DQN2laqow6qWs9La/if\n"
- "oHKUjC5mNeAgHcbWapx9CygwaFeVW6FBPl6Db6GIRAlywPSX+XMJAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANlSGd+Vm9nLiUk6zgu8dPnSFfw4F0R2GYfmzncIGJWtRFTF9ThW/0av\n"
- "/9vZAWyVBjjtnpAP5R1BzdJYV2RwimC/6tqoHtkSbCBhdq5Cb/EHG7Xgb8KwNWVJ\n"
- "NV1EESDwvWnRfSPGTreRw9+2LkdXri17FhDo2GjRxAq/N7YkLK5hAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "published 2014-10-05 12:00:00\n"
- "fingerprint CC43 DC8E 8C9E 3E6D 59CD 0399 2491 0C8C E1E4 50D2\n"
- "bandwidth 1000 1000 1000\n"
- "reject *:*\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "Y8MwYBeEfMhoAABK/FgpVRYolZ7jQ2BJL+8Lb6i4yAuk+HeVmPKTX7MqQoekUuin\n"
- "/HdPKP+g/9HPMS5pCiW4FMwnXAF0ZocPXF0ndmsTuh0/7VWVOUGgvBpPbIW6guvt\n"
- "sLLQ3Cq9a4Kwmd+koatfLB6xSZjhXmOn7nRy7gOdwJ8=\n"
- "-----END SIGNATURE-----\n"
- ;
-static const char EX_RI_BAD_HAS_ACCEPT6[] =
- "router fred 127.0.0.1 9001 0 9002\n"
- "signing-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAJfPJNA3zZ77v2nlX2j5dXImcB/NhRtkG8XQgF7z+3H17sqoXgBgZ1dq\n"
- "IbyJmAy2Lrvk/8VkXNFrT5/ErThn1B98V/PsJOOW1x7jGcix6X4zDYn/MvwC+AxA\n"
- "zNP0ozNcVZ6BzVYq8w4I1V4O3Cd6VJesxRVX6mUeSeNawOb7fBY7AgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAKBzfB4mDEJjFTnmtqZxDG8G1yAiccVgAtq9ECEREL/BOQyukixUBeBe\n"
- "j/FgXzbMJ7DZAuopuJZU2ma6h14G63fZs7eNFceDtmdLpuCOsFuvJ5Mlkf3hDZ1u\n"
- "1KK5q+tiG7MKxgnGrqjPBUO2uubs2Cpx0HmsqBNUalXd/KAkFJbXAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "published 2014-10-05 12:00:00\n"
- "bandwidth 1000 1000 1000\n"
- "reject *:*\n"
- "accept6 *:80\n"
- "reject6 *:*\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "Dp9dLgs9s5beMPxfD0m96as9gNBvlmKhH1RQ/kcOKscia4R8Q42CnUtIqLkCdjOu\n"
- "zErc2Vj9QzjKOvlqUqHxP+J+l+ZJez6F+E1tcmK/Ydz3exL8cg9f4sAOCSXcpBey\n"
- "llTFDibz6GkQ2j3/Uc4bN/uLzoyZKunpJbSKZP5nt8Q=\n"
- "-----END SIGNATURE-----\n"
- ;
-static const char EX_RI_BAD_NO_EXIT_POLICY[] =
- "router fred 127.0.0.1 9001 0 9002\n"
- "signing-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAK4fbjTKYqv2fygfjzY53sVTdtbNMjq293/uffKKxFYnOVvPzrHlP6Go\n"
- "2S19ZcyDxOuH1unbBChPnV0GpxXX6+bgfDkaFh7+jef0RQ3fpJl84hSvdM8J8SCt\n"
- "Q/F4Oqk3NeKKs+zAHDjhAU1G4LkF9/SZ9WZVXlH4a4pf7xgQtaShAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAKahvyDkmh33ob/bLVO1icgz2ntOZN6ZQUfgpMU4Cd6DQtOEwFUGhbVt\n"
- "gvtMHv2+VbxM31ZfUsyBqJ1rJBLpOqlPvSoYwSac2+twa+w/qjfGqcJYhBjP9TV9\n"
- "n9y8DzBX85p6vRcCzcuZ4qUJ2nRzdLHwjdgzeLmmCHuPO2dQxQhXAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "published 2014-10-05 12:00:00\n"
- "bandwidth 1000 1000 1000\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "ntgCtMC0VrsY42dKts8igGQ2Nu1BpuzUltisIsJz75dDx2LCqTn7p4VpWbTrj1sH\n"
- "MRNOvEPFxVMs0Lu50ZUGRzeV6GrHmzIRnOIWanb3I/jyrJLM0jTIjCOLwdMRA298\n"
- "tw8Y9Hnwj4K7K6VvgU8LP4l7MAJNfR6UT46AJ6vkgL0=\n"
- "-----END SIGNATURE-----\n"
- ;
-static const char EX_RI_BAD_IPV6_EXIT_POLICY[] =
- "router fred 127.0.0.1 9001 0 9002\n"
- "signing-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAKHJKLHqjYoW9M+1q0CGHJRT5u2CnZWb8Qr1DpLkkusQ6ru+cDAG12so\n"
- "IpDQh7IyB2JosVJi9ogekYxJ3O1p5WlFUi0X19DMoer9FJ9J7/3s4enGJ/yMBeuu\n"
- "jLVRkjMJhsfhj3Cykon+8Rrf520wSmBg1dpJQCXTwtb7DARgYRpZAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAPJH61Ir6XSu9/Q9tXGaINbXO1GWQQUXtwh6TX9lxnaCNDLGnxiY+ZZw\n"
- "+Vqj3LAQoMrz1PpPsF5e0VIxok10Vc8y4cWC+kIitcecut4vWC5FYTtVVP9wtlyg\n"
- "YCcVOVhtFQxtLiGqprl84+EVxrR7RQVCMLNDUXIgxAfdnS24eBPDAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "published 2014-10-05 12:00:00\n"
- "bandwidth 1000 1000 1000\n"
- "reject *:*\n"
- "ipv6-policy kfdslfdfj sdjfk sdfjsdf\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "XWorzVT5Owg+QcsBtksiUNtpQQ5+IdvbsN+0O9FbFtGZeaeBAbPJ3Poz+KFCUjZY\n"
- "DeDAiu1cVgODx2St+99LpwEuIBx78HaD8RYU8tHx8LoA+mGC43ogQQS9lmfxzvP5\n"
- "eT5WXhkOS5AZ8LZOCOmT+tj/LkSXev2x/NC9+Vc1HPo=\n"
- "-----END SIGNATURE-----\n"
- ;
-static const char EX_RI_BAD_FAMILY[] =
- "router fred 127.0.0.1 9001 0 9002\n"
- "signing-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAM62QoRxSPnm+ZM4fv9p03Qqbz5SzhXYSNjKWqylBruaofTw6oIM8DtX\n"
- "7QnrEe/ou/WtfB+swV/2rt/r0EzmeWBWuDmuSUrN5TC2AdOi9brSJMgXVW6VW77X\n"
- "fuIlLd5DVSId2zs3cKLDqp36CUsooA9sS6I5HrvW9QDf3VS3pGBtAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANg1trpnRzkCi4t4Z4qnBKF612H5A3Zrjg7Jo2b3ajUnON/KEuLPTc3t\n"
- "PPN0W4qqeCMmVQEuxf3DRbTPS20ycy4B/JDWYfxCNwuj5YAx04REf7T0Hlx7Aee/\n"
- "sHEQBhIBfasA2idhTh3cAm4DMYn+00BqjxF6jmyRA0hyntEABabrAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "published 2014-10-05 12:00:00\n"
- "bandwidth 1000 1000 1000\n"
- "family aaaa,bbbb\n"
- "reject *:*\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "xOgP3liKF/WEvwbbGzUUVRZ5WPrOI7jex8pZU/02UEnHjit7vCf9fsUcvkeo0xjz\n"
- "n3FQHIO1iAJS7dEaEM4nz6wtPUb2iXSU9QajkGBkJ9/V7NHMFIU3FGfP47PIJJkd\n"
- "nz5INoS+AsE7PmnDjUMm1H45TCCl8N8y4FO6TtN7p8I=\n"
- "-----END SIGNATURE-----\n"
- ;
-static const char EX_RI_BAD_EI_DIGEST[] =
- "router fred 127.0.0.1 9001 0 9002\n"
- "signing-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAJ8Sn8AxBRbeIAHUvaKjqmcYOvXz7YFlpYFiVHp/cn+l+KUkIYTOFQXf\n"
- "K8AtwjmJ4R2qJIbNlY/6oZGFbizt/B+WPuWsTj+8ACEEDlxx0ibg3EJRB8AZYiWv\n"
- "0zC/loiUvHm6fXF5ghvDr9BQzEUo9kBk5haoHwROtGawr1+vOEiNAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMzok3ZJtLjXOC8RKltXI8xulwn/ctCvQFHImR0+ccA1uBxaZNYgiIcc\n"
- "q8XngROfV8xEgDbYPiWiLXJOMSwOd7hfs3YzRWF+LKftYs8PuRyMJcCoBjOPZ4QX\n"
- "HRfTetEvu2SijZMby+lkqpZg2nuF/ipsXUjrabRZdNiIGhC451vdAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "extra-info-digest not-a-digest\n"
- "published 2014-10-05 12:00:00\n"
- "bandwidth 1000 1000 1000\n"
- "reject *:*\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "c/6zAxO04izQvqdM4bZVGE+ak0nna5pz9XZizFkieZEDWGzWQuVMhXyL5sbsFbsx\n"
- "6Hn7DvNRYR/2nA0teDeRyIHMoMHi76te5X9OFDgaeUVCbyJ8h/KZYfPnN86IDbsR\n"
- "dCSmj9kX55keu64ccCAH1CqwcN/UsbplXiJJVG5pTfI=\n"
- "-----END SIGNATURE-----\n"
- ;
-static const char EX_RI_ZERO_ORPORT[] =
- "router fred 127.0.0.1 0 0 9002\n"
- "signing-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMc4MOhLG3PKPgc+xYVf4eScWzeOf8wq7Cb/JxZm50G0LuvVbhHtHEZX\n"
- "VOSHI7mLE1ifakJvCFJRLobMU7lU0yhn18/nKl2Cu5NfFHHeF/NieUBSxBGb2wD6\n"
- "aM1azheXrRqvDVVfbI0DLc/XfQC/YNiohOsQ/c9C6wuffA4+Sg85AgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBALBWdl9/Vft+NQKQlg5kgvZo+krnhNTRVQojWtUEzom4TFIT+NNKJyMG\n"
- "reQXcNdzNptTB0aOBGGwqAesqzsZ2Hje699NsDe7hdl7Sb5yhKDqtdQY6yDXJUFt\n"
- "zqpAUkmYMLe2p3kPiWefNso56KYXrZrlNAiIS/FhQ5cmuMC2jPydAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "published 2014-10-05 12:00:00\n"
- "bandwidth 1000 1000 1000\n"
- "reject *:*\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "gFg08P9A6QNQjURlebfdhU3DSV0BeM0j2SFza1jF9JcBOWDRmT8FvYFK1B3js6jK\n"
- "8LNV8JOUssv14z5CnUY9CO1BD0xSl+vGlSS4VOXD7rxui8IoWgnqnZsitq+Qzs95\n"
- "wgFKhHI/49NHyWHX5IMQpeicg0T7Qa6qwnUvspH62p8=\n"
- "-----END SIGNATURE-----\n"
- ;
-
-static const char EX_RI_MINIMAL_ED[] =
- "router fred 127.0.0.1 9001 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf5iAa+2yD5ryD5kXaWbpmzaTyuTjRfjMTFleDuFGkHe26wrAQAgBABFTAHm\n"
- "hdZriC+6BRCCMYu48cYc9tUN1adfEROqSHZN3HHP4k/fYgncoxrS3OYDX1x8Ysm/\n"
- "sqxAXBY4NhCMswWvuDYgtQpro9YaFohiorJkHjyLQXjUeZikCfDrlxyR8AM=\n"
+ "AQQABstQAQvNaHu5qx4lh0J5u39pwIR+4bHrHty+wSqMbmR4i5mGAQAgBAAm5VPl\n"
+ "ChSd6wSrmDX50ZZmvkr3EZwt+R3JtUiYZ77yqVlAGBws0BGvUIbYOUHcS4pWuDSX\n"
+ "KwVT5wktWdgm/VKqZv75Ekbt1HqVAtJVrTXWramFH1JfX+di4xIaYmYRZA4=\n"
"-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAOsjlHgM/lPQgjJyfrq0y+cR+iipcAeS2HAU8CK9SATETOTZYrxoL5vH\n"
- "1BNteT+JxAxpjva+j7r7XZV41xPDx7alVr8G3zQsjqkAt5NnleTfUREUbg0+OSMV\n"
- "10gU+DgcZJTMehfGYJnuJsF4eQHio/ZTdJLaZML7qwq0iWg3sZfBAgMBAAE=\n"
+ "MIGJAoGBAMn6qgw7XEvpr8+99/6trahXGW2laXSQGZzrgLdOAIeCK85uqhOmE15V\n"
+ "4J+fvueDykuU5KpgIjvqC8GdzWWZ8THDMOfi2L4kfnF+KZLAxE2b/M67+8dYlIJY\n"
+ "Xip1Wy9LRmJvlnLpwJtm4R6eYFSANEX1sSkQQKS3mgsJbAx9sOtPAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 JuVT5QoUnesEq5g1+dGWZr5K9xGcLfkdybVImGe+8qk=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAK9NjRY7GtAZnlxrAZlImChXmGzml0uk2KlCugvju+eIsjSA/zW3LuqW\n"
- "wqp7Kh488Ak5nUFSlCaV9GjAexT134pynst8P0m/ofrejwlzl5DHd6sFbR33Fkzl\n"
- "H48zic0QDY+8tKXI732dA4GveEwZDlxxy8sPcvUDaVyTsuZLHR4zAgMBAAE=\n"
+ "MIGJAoGBAKjYRj75Sv9HEGOb+MTtlOkBUHubxF6inexiMOOIeypOTU4tGbxz5CBx\n"
+ "IPMR9HGSxR0maExkaBXjA35zIy9mjAMoclTc/cXdMiD/hJfcPACGBFyeKlblYNKd\n"
+ "clR72dRskggOXPo8wSQMX+4ngB6wOfi6HWH+tT4ZW+VoO8DmraHBAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key 71DgscFrk4i58O5GuTerI9g3JL0kz+6QaCstAllz9xw=\n"
- "ntor-onion-key-crosscert 1\n"
+ "ntor-onion-key eQjy89b9KtHPSi5/+lxGB2L2l98lbxP4wqOwVRbJPzc=\n"
+ "ntor-onion-key-crosscert 0\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf5iAUVMAeaF1muIL7oFEIIxi7jxxhz21Q3Vp18RE6pIdk3cAH5ijeKqa+LM\n"
- "T5Nb0I42Io4Z7BVjXG7sYVSxrospCOI4dqkl2ln3BKNuEFFT42xJwt+XGz3aMyK2\n"
- "Cpp8w8I8nwU=\n"
+ "AQoABstQASblU+UKFJ3rBKuYNfnRlma+SvcRnC35Hcm1SJhnvvKpAHV+58GHOOCu\n"
+ "AdKmVPv2VitBQgdgYhgITdTEo4gHSWSnJ7NSf59IZQmleYAQDFC2ZJUJy0n5zTQj\n"
+ "R4u9ikE2XQk=\n"
"-----END ED25519 CERT-----\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "lAZwD6YVic61NvJ0Iy62cSPuzJl5hJOFYNh9iSG/vn4/lVfnnCik+Gqi2v9pwItC\n"
- "acwmutCSrMprmmFAW1dgzoU7GzUtdbxaGaOJdg8WwtO4JjFSzScTDB8R6sp0SCAI\n"
- "PdbzAzJyiMqYcynyyCTiL77iwhUOBPzs2fXlivMtW2E=\n"
+ "mrgyJtcOK97/nva7eGZLk1slPCGmRUm6CvfC/cVrbAiiJF7OxkPEb0SOO8291wKQ\n"
+ "qCxQVXp1Ox/gcILrgRuOTMDDCEAKlYtofKaw+ya3XNqImLtxLNS4MzzNR4kNvuD5\n"
+ "cd9wxTdUZMcbNnWxrwAtp3knuUbv5s+fPB/C9dPK+u8=\n"
"-----END CROSSCERT-----\n"
+ "uptime forever-and-a-day\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
- "router-sig-ed25519 Oyo/eES+/wsgse1f+YSiJDGatBDaiB4fASf7vJ7GxFeD4OfLbB7OYa4hYNEo5NBssNt/PA55AQVSL8hvzBE3Cg\n"
+ "router-sig-ed25519 YZgLS52VJa/LEUkgPEoWAuv6fpmD7BnTIYlxa/gF6OsQiriCTtZp1rg351eoMDt4lxaHFXdiE+uVj+97/thWDw\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "wdk26ZtS1H81IxcUThyirANLoszrnYYhOMP57YRAUDEzUr88X6yNDZ5S0tLl+FoT\n"
- "9XlEVrpN7Z3k4N9WloWb0o/zVVidPMRVwt8YQakSgR8axzMQg6QhQ6zXTiYhiXa4\n"
- "mawlwYFXsaVDSIIqYA2CudIyF3UBRZuTbw0CFZElMWc=\n"
+ "O4zO6U4LPp/eEzhLMA1fCdkHW2GxlkvQx4x+v5v/DDf22r3YqQpazRoScAMXgqPd\n"
+ "m6SWYs13ipqs1/9WDLbwv3dPqOAIgGvOeQobQ06Yxqi4nqg7WW+asbM5K7iNIFYZ\n"
+ "SL51DpGbMKDwgRCaobua9LjxzOtrBROKgwpudn4drkM=\n"
"-----END SIGNATURE-----\n"
- "\n"
;
-
-static const char EX_RI_ED_MISSING_CROSSCERT[] =
+static const char EX_RI_BAD_BANDWIDTH3[] =
"router fred 127.0.0.1 9001 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf54AfsyyHhGluzfESzL4LP8AhFEm83+GkFoHbe1KnssVngHAQAgBABNzJRw\n"
- "BLXT3QMlic0QZ4eG612wkfSRS4yzONIbATKLHIgyzgGiGl4gaSX0JTeHeGfIlu7P\n"
- "5SKocZVNxm1mp55PG+tgBqHObDRJRSgbOyUbUgfOtcbQGUeVgUlFKWZ9FAY=\n"
+ "AQQABstQAZGXxVfBig1quo5wNr6AAbHSuTo8wQga3b0wyrhm49IrAQAgBAD8KBVe\n"
+ "paDp9WBD9Yk6CbO7dqW2bGBYDYHxhMVrAP/xDV2Z7HOjXFjZa5dgz+kcqdxV9BQK\n"
+ "Fvd6c3ZhRpb2jqTKSyoiwwnYOJ0qpbLbHjNC6kIiwzpMKF5/eBIRnL4vugY=\n"
"-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMqT7K8cEzWIaPNXbNgvoZ5ejavoszI2OjW9XXetPD/S2f+N7TfQXHBW\n"
- "bnjpgj87gmk59w0OXTMCv+XofZ0xOy2YR/jG5l1VJIvqgJhhFJ8oSEGVzy+97Ekn\n"
- "Lb1FEYuVfVxSxnU2jhHW6KPtee/gvuyRI/TvZuwmYWxLRpikVn4pAgMBAAE=\n"
+ "MIGJAoGBAMQHT7ehq+M8EKdXLpxc244S7bFsV99WL9B38RS6uWp+Zw5iMhMqBQDU\n"
+ "gLyTzojkB6/MhCQRlai5xmOdexpT9Il9H+C3d2L8A7tHj/58SMH5fUK9Pk91p1xV\n"
+ "pTSkelUNNTTivrkhWYKkZ83N1X9QHEiyM9UOBrx+yQh/ANVOF90lAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 /CgVXqWg6fVgQ/WJOgmzu3altmxgWA2B8YTFawD/8Q0=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAM4nITNe8UykgsIuo5czSSSl3Okr1K+UVWTzDGLznDg77MkLy7mydmk9\n"
- "vf51OB+ogQhozYKIh9uHvecOzY4EhSIuKhui4hNyQklD9juGoW7RVTSpGdYT1ymp\n"
- "dDYS30JBPwCZ7KjdMtXiU8ch2WgbzYBuI+JfjwOhfcsuNC9QPfbfAgMBAAE=\n"
+ "MIGJAoGBAKpe3Vz5SPLedYcIun0NxBb9WHU+PF52CNtyfFSX7ydLk1fEq7ug2Kc3\n"
+ "iT0kZYnYUqIM9tlp94JwOiFLaOfiYdqi1NF8eCHaljf0Fkl+LI4i7+TAxIvSWF9E\n"
+ "00vfFN5vRmH2vnR/tGyM1kbrVJiaBKZLu2FkN7wS5gqXhQl40s3hAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key lx8o212IYw5Ly2KbH2ua1+fr4YvDq5nKd7LHMdPzTGo=\n"
- "ntor-onion-key-crosscert 1\n"
+ "ntor-onion-key VxoUHpKVDO1CwJrUaszxPFyPFBYJpXscprJARNOUFCw=\n"
+ "ntor-onion-key-crosscert 0\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf54AU3MlHAEtdPdAyWJzRBnh4brXbCR9JFLjLM40hsBMoscAJ8cHMIc71+p\n"
- "Qa+lg5JiYb551mLgtPWLy12xdhog7SXiJl3NvnMgbMZXHDqkU2YZCidnVz+xqMdh\n"
- "mjQFK4AtRwg=\n"
+ "AQoABstQAfwoFV6loOn1YEP1iToJs7t2pbZsYFgNgfGExWsA//ENAHxn+CYVO2ow\n"
+ "HY22+Iab30Z52szYAWonI/ivMFc1JXDwhZEYw6p2S9tg5VhPc0EZyFdF1i/HrVwZ\n"
+ "rLdd9n0apg0=\n"
"-----END ED25519 CERT-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "qAE8PqbI12yeyLWaGyW8TtGv+LNXddZF7hTalGr/Hrd9JD3SrT0sPdn//qQZZbMe\n"
+ "fFAiGR42w8P5XlLXp2O8hbpn24dr0MLAPsxL6YwRBWFCUknPtgnHDau5ycXctUlS\n"
+ "zjLi32GfA3FQKnMUp5tJs5hjbeNAUld7Hi3Lu2z6MRc=\n"
+ "-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
- "bandwidth 1000 1000 1000\n"
+ "bandwidth 1000 -1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
- "router-sig-ed25519 4DSdPePrToNx3WQ+4GfFelB8IyHu5Z9vTbbLZ02vfYEsCF9QeaeHbYagY/yjdt+9e71jmfM+W5MfRQd8FJ1+Dg\n"
+ "router-sig-ed25519 AO4AMaoDJC3BCSY9WGz/MuOx9IO1jZwEuTM/PTacIB3Q2+6MR+mnuaWDh7fB+IgyGeBgo1s4ScccosxHDBH3Bw\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "cv1yL8HhQzQfjzkSosziu2kMecNUQGle4d103h6tVMoZS1ua1xiDpVKeuWPl9Z0+\n"
- "wpFwRkOmK0HpNeOXCNHJwfJaWBGQXunB3WQ6Oi1BLilwLtWQixGTYG0hZ6xYLTnX\n"
- "PdSQIbsohSgCzo9HLTAgTnkyBgklIO1PHJBJsaNOwfI=\n"
+ "LkLZaaP2n1OwlzJZ93jWCO1qegtUqLCh1TyHhpb/PzREJsfsqWATfl14TK+Bhytu\n"
+ "H2xDuGFCejTWH1+g+rh7Fkd33W3SirppNpr9Q7s5Sj8fA51HAWk7nYArSiWYmwBR\n"
+ "ITqgfNVhi192LE2mkgFJeP7SDBcs3dYXTu/nbpwXtXM=\n"
"-----END SIGNATURE-----\n"
- "\n"
;
-
-static const char EX_RI_ED_MISSING_CROSSCERT2[] =
+static const char EX_RI_BAD_NTOR_KEY[] =
"router fred 127.0.0.1 9001 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf54AXXgm0CUWQr+rxvgdIslqaFdBiwosT+9PaC8zOxYGIsZAQAgBAA6yeH7\n"
- "3AfGIGuDpVihVUUo0QwguWDPwk2dBJan7B0qgPWF5Y4YL5XDh2nMatskUrtUGCr1\n"
- "abLYlJPozmYd6QBSv6eyBfITS/oNOMyZpjDiIjcLQD08tVQ2Jho+WmN64wc=\n"
+ "AQQABstQAeHEwGvEQ6Q0Q4feihyajToFJ/tJdYb7X0U6LJX83+x4AQAgBABfIsFo\n"
+ "zK+xiF5YqrRX9jIluwrJqUXcnRBc6jzzEnMIXCFIlaXAHlR7FtlVjhoUy+pClNul\n"
+ "WcT+JjHbzUwXwAtqhV/tDhLAHk+Ay1vwH1pVlqDBC6UYE1WnAfzUGdGz9AE=\n"
"-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMdyTK/VPZloLUaLsvj1+NOFs33/E9HmA0VgvZ1nNUrR+PxSR71QF7Tw\n"
- "DKz+/p2rJE+MPfQ/Na3dH0vH4CDZ+FH2m4A8SB9emF8aKxdc/7KCjQNDQCNlEQYn\n"
- "O9WvZJhbNPHUmX0z4OotI+Sk3qBzVHu0BGDsPYC9gwszIumDUILxAgMBAAE=\n"
+ "MIGJAoGBAKScAJYuwEgWW/u1K9zpBmTcM2/iwH1yfdQ3MgAcLEGTukHyMb0FJ8GI\n"
+ "zetrQJn0mBY+W/Hb4xylMMz2GL9pgsmGjKxDLcW9at9rA5FXunCEvRkfCvJhhSzS\n"
+ "KDbtTM0030k6uvSo1MQKt1zrntdUXkCDZYl8+yDewb3MfNgOCNZNAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 XyLBaMyvsYheWKq0V/YyJbsKyalF3J0QXOo88xJzCFw=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAL8o6CJiLfW4vdRFvJ2nFt/H/ei0ov83rilOuwSmNORmL9lvnHY++HrD\n"
- "dmEEvBv74xqWJxGbJ6OQ3VOwRpf2X/cb4gAvsQDqDmNwpJsrPYRQVXp/KY/8z7bJ\n"
- "dM4CjcsuJHHmj3yc3iCzgqt/Xr6vR24X4bee12/bP7R8IETvWoiHAgMBAAE=\n"
+ "MIGJAoGBAMpVLmZCeEHM7aRPjxGrcYYTlm2YmFVYkQCMealSBwoP/zMEPnLXODPx\n"
+ "vNx0syUAKg9WraLRoVoTNgHQvPWJCIHULthD61O+S966zItMUoWjD3lfrwZRkA2S\n"
+ "NDvzxUAuxhqS01zfoXGw9jq058b4yhGxdkeloz/6ctIf78dCbfC3AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key qpNEGrLMVn28Odonk/nDtZq1ljy0fBshwgoAm4X1yzQ=\n"
+ "ntor-onion-key xjiodE8eCJMDycIoosVW5OnhmvEDSn3zQ9uFSpVnI7RI=\n"
+ "ntor-onion-key-crosscert 0\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABstQAV8iwWjMr7GIXliqtFf2MiW7CsmpRdydEFzqPPMScwhcANqd8l+sKSqF\n"
+ "jfzw43nwQ24k+ktkImehYV443lPygB45J9hfk1Frtf73sdnb3r/Oq3nFfkqTHiZA\n"
+ "vfpkxWg3qgM=\n"
+ "-----END ED25519 CERT-----\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "i4RKGIeaUrO6nzfdtb6j+ijYJh1Vgc9bsHMpW9cVCOjoJKFW9xljgl9xp6LytviN\n"
- "ppKYCt9/JflbZUZjny34ESltPGrdquvHe8TtdQazjiZBWQok/kKnx2i+PioRF/xI\n"
- "P8D0512kbJjXSuuq9tGl94RKPM/ySGjkTJPevN4TaJE=\n"
+ "t3ByKPtpGpveOkZI5ArpxDsdjmRbo+vdmqGmDOdUzGEQ7xLZ4tfsul/yvkKNX9WT\n"
+ "f40zkn1kOpEkiNRhpJT1z33yUeGO4Sps8oezTf9mQJCccsTyZ8Jj49V1VSZ2jrAw\n"
+ "J3GJNoqr1lO68HvCA5avXKb8M+uUlB1zoimkTyq14Tg=\n"
"-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
- "router-sig-ed25519 pMAOpepn5Q9MxcV9+Yiftu50oBzBsItQcBV9qdZCIt3lvSFqFY9+wJjaShvW3N9ICHkunrC0h/w5VEfx4SQdDA\n"
+ "router-sig-ed25519 r73EDnNHPxOwmwTR4mcoeM0/P51/WmFnvW/oLzgaR+Cjx1QObZEKO45xqB+QatM0IQ+7H23R2m6cD0iTi6GzDQ\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "Du5fJYDzvEeGqKTJwgaQsJJgz39K/J4qEM2TZ3Mh0XuDM1ZWDtjyzP03PaPQqbJ1\n"
- "FsN5IStjOqN3O1IWuLzGaZGpGVuqcyYOxjs7REkGQn2LfqCjpzjaAdcsL0fI4ain\n"
- "o/in8GQ6S/qhsx8enKlN0tffTmWmH9bmmVz0+yYmBSo=\n"
+ "SpSRg72z5U5RUIVQymJNyufSYH3RZPdlGweBzUypnaU4+iBum7IB69M2VPE4bchK\n"
+ "EObhVkqTisg6utm6h9HyDUgpgtAIS25IfeRhb713RNdJYeD1KW5KBcmdI5g/eoCB\n"
+ "4N8XrU4+xI6B6chj8I2GiYCMCT7gWFOqAIoJlOJN/UY=\n"
"-----END SIGNATURE-----\n"
- "\n"
;
-static const char EX_RI_ED_MISSING_CROSSCERT_SIGN[] =
+static const char EX_RI_BAD_FINGERPRINT[] =
"router fred 127.0.0.1 9001 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf54AfoVFYuJnDNBWbjbTqfXACUtXWPipmqEYC++Ok/+4VoFAQAgBADH7JzI\n"
- "fjSMV158AMiftgNY+KyHYIECuL9SnV3CSO+8+I7+r9n+A3DQQmGLULo/uZnkbteJ\n"
- "+uy6uRG4kW0fnuBlKhseJQm9hjNGWzC8hmebp1M+bxwG41EGI7BZvnTrRgM=\n"
+ "AQQABstQARuzNoxmRJWC5XJHiZrz6JnjmLqWZdGCf7gxcyDanXhqAQAgBAC96/co\n"
+ "YtwP7WOha/PdIPmAj9uCv7vl/GtDI7SYowz/i0AqWXGk1T/GIGeSJZ3uSWq9u3tP\n"
+ "ytPSnJvmqj6wMkGLQ7oZsi3G1DTuh/gU4fY3aIAQcm6LEestgnI6RkQF1gY=\n"
"-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBALEqlijoFIDX1y1i5zfei8DuDIsFtSw56PGgnMRGcybwD1PRQCheCUZM\n"
- "erQgFCWjgLgvGJERBK/oILW1dFXp4MAR5RgnrPGTfWTinCj32obMLN1gIczpq6a9\n"
- "P9uv6Cz0ApSxpA/AuvjyAZwQKbUXuMvIY4aTprAKSqqVohk6E+E1AgMBAAE=\n"
+ "MIGJAoGBAOhMzS1rZAYB2AZpV9VvAF3twjoMaKuwscP0Z2eFih5/WhUWBSlq0ik7\n"
+ "4XgTYXS1EtV2GjgCE3aIdElr1eBar4+cz58jKssZH5FFWDzPmEN4g6qzifIbsvXk\n"
+ "MeAF1u6wCr/TDJ7srCSp4EL/f6V2y0uC951Z24wKGnRZadBQlmo/AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 vev3KGLcD+1joWvz3SD5gI/bgr+75fxrQyO0mKMM/4s=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMZbbBjGV7xPri4XNmejq4add93p+XsWlsfbM930bcC2JZiwg4g4cq6W\n"
- "idl8VDmCXeaWg5y3kb82Ch/Q9vPG0QYQbXxUA3JxQKKbcEK3QsEvqQh8Nb7krILK\n"
- "YnSGAnLG2Nc3PnKb7Wpb8M3rAysC5O99Gq1mSfm8ntj3zlIM7NSHAgMBAAE=\n"
+ "MIGJAoGBALdUFqqQlTglmEhthhBDk4ZYeG6NA08jemECh1Eusl+cgiQzvD9nMwdC\n"
+ "euE8OTZkDa2CxlhCdUNV0D67X4hp5C77uJzLGL1LHUeQQaNIkJeMP9A1iZpHcpki\n"
+ "Q9iN/XEMiDK5z42IGc40cimSU1SDCgKquDg+mLyUmQzpo/9GzRvVAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key CYcpfIF4T9PJcfROfVJTUYl0zNd4Ia5u0L9eng/EBSo=\n"
- "ntor-onion-key-crosscert\n"
+ "ntor-onion-key e7xFX5txUS4DxZsux+D2Pz7YGIy60IfBCsxqgSbcCTg=\n"
+ "ntor-onion-key-crosscert 1\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf54AcfsnMh+NIxXXnwAyJ+2A1j4rIdggQK4v1KdXcJI77z4AMRc2LxiKbyr\n"
- "fqRVynHuB031C4TN/HAlNPBjVoRvQRgzpiyyoyCqMDxLZdM8KtzdLLeqZJOXtWod\n"
- "UXbYG3L70go=\n"
+ "AQoABstQAb3r9yhi3A/tY6Fr890g+YCP24K/u+X8a0MjtJijDP+LAH5UAsebB7YK\n"
+ "McQQD2Kt1QtPfkIClLENUG410z6SwWNU1A1p7nJQ0AcCUrsM/5gZfwPzaoEfFZWJ\n"
+ "dmRHtqF/4As=\n"
"-----END ED25519 CERT-----\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "BRwRAK2lWxWGS49k8gXFHLEQ/h4k8gOQxM0WgCaN4LjAOilLHFjsjXkmKgttVpHl\n"
- "f0V9ebSf+HgkpQnDSD8ittnr/0QaohUbD4lzslW4e/tQYEiM46soSoFft85J6U3G\n"
- "D3D63+GmaOfIaa4nv7CD0Rw/Jz0zTuyEuARsdJIr1IY=\n"
+ "DO+sLD0Q6Ls39UplbwmIP1kqrYPdUTO1ydHtdEl22+nXbzQ+vIEaMprv77fbOkJS\n"
+ "adq3HQ7WDJ+ESxYyvnOn0rxCv/P4zENgbWE4s10uMWQ5Oqirwlk6peNou9MZ8Re1\n"
+ "1VChxzgerdCJcOOvTW7CCR/7A4QKnn8zu38cT51ncO4=\n"
"-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
+ "fingerprint 5555\n"
"reject *:*\n"
- "router-sig-ed25519 7XfV5r7FXbXPEvrxlecWmAJxat/6VT+/4tE5cHrQnvLM4zslysstWH6/AfIfcmUuDlQ0watmfg1MvVnjavcfDA\n"
+ "router-sig-ed25519 lF577k8aob8csasyKZnvyyfbBze3dgO5QhHRrUCDEoE5bFLRLs50RLwWSn9wNiuOc8tFOFvXqT9o/Y0rziEWCg\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "eigLL3S/oMGL2tJULt9bl3S0iY+YIxdKeGFCcKZci59zD786m+n+BpGM3yPpvrXr\n"
- "bGvl4IBqCa1I+TqPP1rM9lIEcUWaBT7Zo5uMcL1o+zZl1ZWPWVVKP5hC5ehDueu8\n"
- "/blzNhTEFAp23ftDK9PnFf+bXxqbgKkEoZsxnd3e9Ns=\n"
+ "S4yw7hIs9NHODCiTFcSh4YpYHbG4XP3rq9YyJgUG+uWen18N904p+4iQwGh+Ye3T\n"
+ "cHl++4ZkXajAuSm4ZT784/SserPJmxxZroeSMVcdBgGdngOq62kVtfqBRyFDUtBU\n"
+ "CvCb6eHRB+BoKHWcSSyr/abEqO+AfjjWRVEsd7B4PT8=\n"
"-----END SIGNATURE-----\n"
- "\n"
;
-
-static const char EX_RI_ED_BAD_SIG1[] =
+static const char EX_RI_MISMATCHED_FINGERPRINT[] =
"router fred 127.0.0.1 9001 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf54AR8QC+SNBpPOTVY198IQBANNwZjy+SBqQNxfzjEmo204AQAgBABjz4FP\n"
- "zW/G+fu7YirvANvvqJeb7S1YYJnf6IrPaPsPRzDqJcO3/sTzFC5OSb9iJmzQAWnn\n"
- "ADPOl+nOJC58XJnJ7CUJdPtyoVdMvUiUT/Jtg4RuCN1iDaDYaTh2VavImAY=\n"
+ "AQQABstQAblHLIIIJbgQ7K3DMC/bztGu14OqVAr9A/sTA3/eethrAQAgBACvXlt6\n"
+ "ONBSjN/eXPqM26//TBLhJ880ueBSi2sw+UBpUXqJJsJcW/nChhopJvXkM2LAMF2Q\n"
+ "fnXee5XVoAO50gMaDU7vvh9GVnuAiV4coKDzmDyKVYnGN5CdCk0zj9LlegI=\n"
"-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAKuLC0kzCBTV6+WPZcAOQPKjqbjvMIyaehIQS1o90dYM+Tosrhtk3bw8\n"
- "QBLMaiWL3kfIWPZuWi2ai40dmqAXMrXH3yBgKRNZ6zZSbUUuJ1IknqmrQ2PKjC/p\n"
- "sIW2awC6Tq+zrZ7vntDb02zY857vP59j8eolTDg1Vvn6l2ieL+WhAgMBAAE=\n"
+ "MIGJAoGBAKNE/KxjoKl5AIVfvGBm2o863+0/NS3DZsEo0nKaO2n4ZDeAjwezHYl2\n"
+ "HVCod3XUGRrYs4pAz0x7QYcWrI+v1RSy9JqouZeZsCI06lB/4tedve7hUN6nh+9r\n"
+ "AmxK/9RF7O2dosFWTss8ZdK7zYiNTOVcu9nrzpZCsx62TJl48l4VAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 r15bejjQUozf3lz6jNuv/0wS4SfPNLngUotrMPlAaVE=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMnBQPOJBQLZ3NAa70n6lGZGvS3DYZFNOZ2QnHVeVvOSFIFsuvHtnUdX\n"
- "svDafznYAuRFRVqJS2xtKKGu0cmy6ulEbBF+4uAEMwQY7dGRPMgVF1Z33U0CSd08\n"
- "ChCJGPTE7tGGuoeSIGN3mfC4z2v9SP3McBdAiLHisPzaUjfRTcwRAgMBAAE=\n"
+ "MIGJAoGBAJbj7YfrDjilYtStM+ujxajNuayX+IUE2ZXBn4ZD37BAVXSdnoDBnV2q\n"
+ "TMyelhaQlPHHlJKhDnU6l9IJhMYS81rHcavShnbq6xRk/MyIYT5m9a8e9zGjpFOu\n"
+ "++tnFR3CO9QM3PL2gKln9Ta+yRbFJ1Dut6Nx5BOsKQsQwU9Hekl9AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key W8fUvBpKBoePmqb70rdJUcRT0NhELDWH7/BSXJtkXS0=\n"
- "ntor-onion-key-crosscert 1\n"
+ "ntor-onion-key z3SSwtgbp0wv2AUpqmoRh+r0Ebc4DNy8s0nO9v/IDRQ=\n"
+ "ntor-onion-key-crosscert 0\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf54AWPPgU/Nb8b5+7tiKu8A2++ol5vtLVhgmd/ois9o+w9HAAPwWqmL0HXa\n"
- "bYKrKPWQYnpQHQ3Ty0MmCgj3ABF940JURnV161RlN8CRAOJaeQ0Z8wBRLFC1NqLT\n"
- "+GVdtewGeQA=\n"
+ "AQoABstQAa9eW3o40FKM395c+ozbr/9MEuEnzzS54FKLazD5QGlRAImd//fC+Kly\n"
+ "EP8g9NhXLgNwyYMPv4AVK/IHBodacLoBibzr3tjOEryYVjp5GMjdV31FM48yUMEP\n"
+ "684oirlXMwo=\n"
"-----END ED25519 CERT-----\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "x0vT5Wv7Guc0/Vu2BqomWwenh8oda9+8K/7ILi5GQL/WC29Tj51i0EE7PVSnSMJ7\n"
- "33I/V+N5neauqWnbg7TxYaLsPfr6SpPTpBL1Xt0OiwT1//PvPYZ1gCcF3ig3KcfI\n"
- "mreQd5C5Vri6ukWkMtz/zNDaDpDanzaNXTdaUXmFHF4=\n"
+ "iPAp07r37ZfIGSVkunV7GbD4wUg9YTzkfZqqK6v/k+PktFD3ymFMm17xSWB+iDBZ\n"
+ "kPHuPL7n00fARbs7hZxmxB+Z8VV8aIU2o4Tnh91NHVxd1WIfrqNIwKUIXt821Qc/\n"
+ "fhotsrR6u1NGcqHiUZLOq7DFCtX4xvTMXDnQA2Y3F1Q=\n"
"-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "fingerprint CC43 DC8E 8C9E 3E6D 59CD 0399 2491 0C8C E1E4 50D2\n"
+ "proto Link=5\n"
"reject *:*\n"
- "router-sig-ed25519 4DSdPePrToNx3WQ+4GfFelB8IyHu5Z9vTbbLZ02vfYEsCF9QeaeHbYagY/yjdt+9e71jmfM+W5MfRQd8FJ1+Dg\n"
+ "router-sig-ed25519 I1vjiJ3q04pz1mO5zxsoy3ng4y3Ix6YxNEUaO7O83kOiU+VvGmaO+fzlXkTMuAz30BFm75Yckpeiqodak+F7Dg\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "Hci/Br1+NNymDZBmQy1QWMlCeLe8Z1vtZ2ZTj42jDhWg1OC/v72ptI072x4x5cmi\n"
- "X3EONy8wQUvTNowkfG6/V/B768C7FYJYBId1GAFZZymXnON9zUYnE3z1J20eu6l6\n"
- "QepmmdvRmteIHMQ7HLSrBuDuXZUDJD0yXm6g8bMT+Ek=\n"
+ "NRlkV2yLpVDu9fppAPrOyw6rcNvcDjATuZbiwL13KR9NOKFZtF9KQ+qSme4Y8Hcg\n"
+ "hjlVuRiShZPmjq3n6iktNRryn1+ziVrjr6WQQBZyd0HuJ86PAUW8LOC7bI18AzT7\n"
+ "fibS1unSsKBzcFjuP5Uz/ZGABG6lhbgvoleRbAFbd4s=\n"
"-----END SIGNATURE-----\n"
- "\n"
- "\n"
- "\n"
;
-static const char EX_RI_ED_BAD_SIG2[] =
+static const char EX_RI_BAD_HAS_ACCEPT6[] =
"router fred 127.0.0.1 9001 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf54AW8fyx54c7vQQA/AmShAitFP7XI1CLdifEVPSrFKwYq6AQAgBAChqjVA\n"
- "/wKKJZ30BIQoXe5+QMiPR6meNxF1lBttQ2t5AhauZbH5XzRhZkdGo114wuyPNEM9\n"
- "PrBwp5akTtari9doVy6gs3McqdoIbRdWevpaGj5g5oOEOtA9b5UNWQSwUAs=\n"
+ "AQQABstQATlCWYR3MJXT0ttJyn6HikvWxiw1QlFMUv6P9aVNxSeoAQAgBADrOgV7\n"
+ "plvP37tRpQENPGYV8J0+hJAK5YcnEtfnPFSIf2TimQb9VZZ4Zcn/7WLIsAkWP7lu\n"
+ "BPY5GC8YPPz5kaHDkrsX7LExapYw0KrrLrHHOf3DWuNayjzRfkPFOIitIAI=\n"
"-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBALp0Croi9zhpGxi9sUj54jr/flZdzxVVS+8VNldJG2c1soSx8kwlwotu\n"
- "7mGGudJDAzDHGo5F5CCPEfQov2OmDehpefYUz/AaMLly6PrLRJlcUcpLogGf1+KU\n"
- "1lLwE8kanXUkgvDhVQiFvNjy2Dxxuv3AHH4WdZZfbMbm8FJRGoHzAgMBAAE=\n"
+ "MIGJAoGBANEcIzy+Sq/G43SLJDO9cVZWUC9aPR6VX+C3A7nToJgl7eqRuI9EWdLc\n"
+ "ORZTRoLWfEeu9ciJpjfOdIt45Sz23lZ1ZULRQEOrgZ4rXMolSdVYMKPKuldvj6fz\n"
+ "t4QRUdkVGISNn7lVmdF6Dti6NNMdS0H+vFM4C6OK7qc1WY2qD3NlAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 6zoFe6Zbz9+7UaUBDTxmFfCdPoSQCuWHJxLX5zxUiH8=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMoI9vQT4g2sV2dViGOWOzxckk367T9sMjVwcYfJCmnixGxjWeKScQFB\n"
- "K9v1uK73cfZR8AxiUGK4/iOX/9en14mJOGF7fftAqypFLAt1TBvb07IgXljOBoHc\n"
- "Paw4oZoJQzEoazt0Oa181LyNnNIoaZpHVZd1+a1Gs1gKoM4xDBv1AgMBAAE=\n"
+ "MIGJAoGBAOChxY+BMY6iajCYdjz3My8oqJw++gvhnH3aQk+a+pmXO5dFnSeWnnxU\n"
+ "7kue4Kc/F9C5ZLdArObXegUYE7nge3Sss0gxlNj8E1eItCkh5mDXKxj4wGoYFxqi\n"
+ "tMuJIcMSkz6mt9iOIC/33AcFLHCH2fEPL9lNqKZw324+2B/HwBkZAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key KjyvXYkMcpke5ZsUYf2gZAUNeEoz8NAwYoQvvbcDGiw=\n"
- "ntor-onion-key-crosscert 0\n"
+ "ntor-onion-key oOTk28yuw1rfN9ieyNcjsR41nmWZ3sMl7WAq/8rIyWU=\n"
+ "ntor-onion-key-crosscert 1\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf54AaGqNUD/AoolnfQEhChd7n5AyI9HqZ43EXWUG21Da3kCAI6MRHm7GpCF\n"
- "/3zDGR/6jKe625uFZX9HpLt6FgAdGSJeMQ9W4Np9VkrFXAB3gvh7xxRzSgZ1rXgR\n"
- "lUomgi7N1gc=\n"
+ "AQoABstQAes6BXumW8/fu1GlAQ08ZhXwnT6EkArlhycS1+c8VIh/AFfG1jFn0GEz\n"
+ "Izr4UdQrqbSIW4GnGZt/cWF+5GgrFqVLKjLQn0qL59+RcI5uL8t4HYMeX7DDW05D\n"
+ "kFEyCR0K3QM=\n"
"-----END ED25519 CERT-----\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "xJXvCCpP4ExBuT3OTsdn2HJB0HidupmQq5zBh8fx/ox6+047ZBOM7+hVxxWapcMg\n"
- "PMXbcLD4L/FCBpA/rjnFUE/9kztdq7FH/rOdi0nB6FZWhwDcsZuyfvbnDTxz5iHJ\n"
- "87gd5nXA5PE649SRCxW5LX0OtSiPFPazu4KyyBgnTIM=\n"
+ "WiHEajyWxVHtfGW2zk1P/oiayJ71SooJ5h8VTJvt3Ll6EwTk0OLKrT+WHfnKyIsx\n"
+ "Zc0ocAD/fB89k8aD9doEbyGhtxYOnbHzm+Bu/HBpHcsom3sJ8V5dAG7T0SsA2e7j\n"
+ "/nUR/px6AhyLRVTPCwHJffU7BgCBpZR5qpxwE6iFJec=\n"
"-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
- "router-sig-ed25519 4DSdPePrToNx3WQ+4GfFelB8IyHu5Z9vTbbLZ02vfYEsCF9QeaeHbYagY/yjdt+9e71jmfM+W5MfRQd8FJ1+Dgxx\n"
+ "accept6 *:80\n"
+ "reject6 *:*\n"
+ "router-sig-ed25519 UPASGxdHFoEI9MK012Ip83qfdYAAAaaDpr/2xn4dDozCGisojWJ1Cdv5HDLpXRsdcjkvOjg48XQHMiFQHLWEDg\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "tk4kBNYqB8utOmX30HrV8YfnwBXYODIiL3M/juRS6nPn0uvbW7pjoZ3ck/ahgW+6\n"
- "FNQsgTJnEADCWS1r6v7PcvzQjtrOUUpNxGJxYw1r8yZkvmIxSQD6GMzuTxq7o1VA\n"
- "/wZYDLonLhCWRdPjxnrl12+z92NdyISJCHMLRVqs2QY=\n"
+ "m+JqBjl516GHFnz/BMCX2Fc3vJkZxcstqa1+QScfj+hagYlW97SyUSTlGrNJcP0R\n"
+ "F6ZP5p8DFRoyMPLUsHv3cXodSCmmlGYZLctIAlAwNPyvjx8K4viE4/ImEemoKWzd\n"
+ "D1ylziMbpPYQ//9w3a5zNrOuigFGKyQJdtc4eKbMkQM=\n"
"-----END SIGNATURE-----\n"
- "\n"
- "\n"
;
-static const char EX_RI_ED_BAD_SIG3[] =
+static const char EX_RI_BAD_NO_EXIT_POLICY[] =
"router fred 127.0.0.1 9001 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf54AYYiKZrFWZ/Cj5mZbfK11MZHYbwchllsUl4qPqY9gfi6AQAgBAB4irxT\n"
- "86FYA0NbZssSTmfyG6Edcf0ge61OwB4QD35kHCrvuZk2HnmL+63Tj4QoFqIVnwVC\n"
- "3wRGJGcmS7y+vS64GUXbuyTgqgpl/KuoHo5Aqe6IxJlVWYtU6W0M6FV9tAM=\n"
+ "AQQABstQATYAnLUERikTHIW5W60T/eDjs/+G8GViekaCOpm7O5oAAQAgBADvnTrF\n"
+ "bsB6EXhry4mELlXb0xIK+zDsMniuXXOs3dZhondVXKfc/6XyytBWFt3V2323aYwg\n"
+ "W1uRiwqrqdbGGCelO6Vfp02HtSKOUELhzb3XRfJjrTTOf/ov0TFKqZq4oAo=\n"
"-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMUEvXTVTl5xkQ2MTEsB4sXQ3MQkz8sQrU63rlqglpi1yUv24fotjzvE\n"
- "oJpeKJBwwg5WBW/fW0bUDJF2cOHRHkj/R4Is3m+2PR1Kn3UbYfxNkFkTE11l099V\n"
- "H6xlsi0TJOJKlgrcbSuB7se2QctZVhwsdsJvFRptC9Qd+klAPb7tAgMBAAE=\n"
+ "MIGJAoGBAKKGX1tx5+kYDoBULSeIl8Yj+bfOwoQACHT/S/W9Mt3OKcfrjjaUxxoY\n"
+ "TYu9W4m0CbVOmTcNnB/StDwub+fhFgg/jf8dUywFuzl8Dv0+Elvd6rhr8sQO6UWm\n"
+ "nUpZL4yvOVehl5pcY9lIUYX8SE6akUCLo6S1mJ1/aUnNK6i9TxSrAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 7506xW7AehF4a8uJhC5V29MSCvsw7DJ4rl1zrN3WYaI=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMooTeSUX7GPoyklSd1/6cF1u8e2LbjOLIpZrMon0Xt7c/aNwlrG9rVo\n"
- "TSokHs3AQ2H2XIceySVRRWR4AdX9KApO4CX0gGTuVUmq6hFJWMnHdAs2mKL0kt1w\n"
- "I+YWzjUqn4jIVa2nMbyHVQWzIysWwWiO4yduIjAYpBbWd9Biew4BAgMBAAE=\n"
+ "MIGJAoGBANM184uIu8XUgWZBARcAOJSZ9UxN2aecqJ0QcicJ/OSt1GDrxrmIuvCh\n"
+ "+lGA2dT1uqGVJrrSKMQoBYsvJXK1gMFwvhl9pjg4LGkXLS3CUJffjwSxRJ2wF8Ga\n"
+ "yVC8SLWJqFPE7/ReWLES5Qx8/LqpJwIORwQbJc9r2g325U07HYGLAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key BN0I+pLmFkDQD5iRsdkcped4eZwGIuXnLiX2K0Zoi2I=\n"
+ "ntor-onion-key jQrLewVdDUe3MvTdLNB9H2Is2mhQx+TCOlbIdDyxTlQ=\n"
"ntor-onion-key-crosscert 1\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf54AXiKvFPzoVgDQ1tmyxJOZ/IboR1x/SB7rU7AHhAPfmQcAOrIvaG/xJqe\n"
- "adM6mai+FlV8Dbt6QrXTcNHJU1m+CUDthA9TPTAYz9D8W0mTEQ6KEAKGfQrNLy2r\n"
- "G1B+9wWSpA4=\n"
+ "AQoABstQAe+dOsVuwHoReGvLiYQuVdvTEgr7MOwyeK5dc6zd1mGiALA5bpkro0Qh\n"
+ "9tV7U1Ym6Pngmgs/Tx8yUzwGIoefT4A1L14yYokNBBe9DQ207rA5y9u9WnuT5mZH\n"
+ "2mcZOMGzywM=\n"
"-----END ED25519 CERT-----\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "BpLBsl6Yo64QzczJn0TjdcXC1Jv9IhUG2m/Re3v0voCELOP+t5vkZXXLoVL23oKv\n"
- "JheSkWiuAIEPsatb4afXZ8wZxPcQjwy3zTOBM7p9CG5fA+KYpqKTxAi+dhVYlcDo\n"
- "M7S5nMV63FclkZIT70FFTHwWed1sAKwEO3/Ny24eppc=\n"
+ "WC79UXdGUGKTPFfB7Oz4qtk5uytmNA5XoCH4w9cpKOUBxG5Fc9Dol58STLr/AWoS\n"
+ "A9Gfx2zN5MoOyv34z2UlUV5Kp75zT8emxun47SqKv+lqRqRTtHrFavOkO0LbSRH3\n"
+ "bxYDdx/HmQnz48vQyK+VLm8lowsxCjgIBVmTKs93t3c=\n"
"-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
- "reject *:*\n"
- "router-sig-ed25519 abcdvEzGFYMcJ/Ea7sbessW1qRJmnNNo2Khkkl0rEEgtLX0b4L4MMhK/ktS52Y6jX3PRQWK5PZc6gjV7Jaldh+g0Aw\n"
+ "proto Link=5\n"
+ "router-sig-ed25519 DA5Fd5XeIyZWetlWbLRKUPBZ6MLW16/C3/m42sSMV5ya4MRMIql9keH/m7apzd6F8UqHztuHnFpgfOXwyN3OCQ\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "Vyj7g3eQ3K4+tm49fJkAtsAYnYHcEiMnlucYCEPeKojzYStNfZwQO2SG5gsoBIif\n"
- "urgQZ/heaF4uiGFg64UFw08doXqQkd5SHO3B4astslITvmq0jyaqzSXhdB5uUzvp\n"
- "QCR0fqGLVS1acUiqGbRr4PiZ9G7OJkm230N3rGdet+0=\n"
+ "aGvBliAHSDUmrFcHMLuEKQVFY+zr6oYKgJjBe2G0j3Xcw9VpwSpZkgmZa5jJI0br\n"
+ "HJwA0sd8NhzGuP9oCLbRI6pdT5l8TDCM+zM/G93Sz3cgxATj2bxDTg9/B4HNObCn\n"
+ "1VufCazt1ild43svRJa2bLsqWKTRHKA8LGKmwYsvlWI=\n"
"-----END SIGNATURE-----\n"
- "\n"
;
-static const char EX_RI_ED_BAD_SIG4[] =
+static const char EX_RI_BAD_IPV6_EXIT_POLICY[] =
"router fred 127.0.0.1 9001 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf55AaEnncX/t0cbLm1xrtlUpkXghaA8fVuV7g1VF3YNfCaIAQAgBAC7Ki3S\n"
- "zzH9Aezz5X4fbwHeF+BQEDfVasfyTxTI4fhRi7t3RxHzBJd60uEMXy2FchD8VO5d\n"
- "j4Dl7R4btrohPVSVBQZuemBQSW6g3ufNl0txpFWu0R7vBPTFH6oyXYfY9gQ=\n"
+ "AQQABstQAUGR5G6d4pKIbn8TsRPUlzF3aG+bGlSRq5CmgY3FHvXCAQAgBADHVYAg\n"
+ "VsnLCsUgF4yKxR8mDyeVRASJ6Lan1xwA49u0MrcvHJDohop1C2fRi6npUKM+G80J\n"
+ "vebsEbexWjnaWURBrwx6YvvF22lw5TEc6dm8KxhGNOWSBFukr3tWJpn6ogA=\n"
"-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBALGKwzhOui2/jJPjU1ngW5IZRPcoDk7RAfGDO4xaef4VfAFHCV9CQO1c\n"
- "/wQ09CcRdggTvUcv9hJTGJhSObUUooCkxw4/35f/A6/NoW1Gi0JqF9EsQWHpuAfr\n"
- "n/ATlJQ9oGdTCNDq/BXSPWXhoI6UhUe0wiD4P4x4QwaYHcZh+lE5AgMBAAE=\n"
+ "MIGJAoGBAMebdGK2Ac/1eewX+boQNlZA+msq7kCqqS3FM8GRBrCZGm4MFCx6bDZT\n"
+ "sMWjOqN3FGPjN49I4GYlgkqlcvgaKFB/DGbXOn7X1W8fa0qzKK7okK9qtHMAjINg\n"
+ "RjZ4aHWmeGhsVpGD1ifEEofWWjx7/T8dx7XIvNdu2zgKVjuySdGrAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 x1WAIFbJywrFIBeMisUfJg8nlUQEiei2p9ccAOPbtDI=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAOKrizVm2h5/jE/HqqLCBLWJZVVoGspasCtDDqHhSqsPzyjpqa52iMKi\n"
- "q/deJ92le3J2NJRGKxPmPQqWxwhIjnMS5kUMoW182iLpO/G9qyPZ0dh6jXB0NBLF\n"
- "ySfW6V2s3h4G4D2P+fqnsnzQnAX7YufkvgDau/qTWi2CqD0CjavDAgMBAAE=\n"
+ "MIGJAoGBAOFfyR3mbBZMu85gSrw/VBofkCmp8CwKU68pEWc3SL29c6LjV9LCXrDZ\n"
+ "08jUZ1RRHR8hYeLaz3ZxLhOQ50JYw55w6YhLbfzZS5+xt7gay6M2iFjj6vH8QPqc\n"
+ "T1zFNy0DAYID6u2AcvTGrRdRPv9NBs64wf2fJAGWUXNPQMlCIjKtAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key A9h8jY9dPbhHTDbIc/NYWXmRP65wwSMrkY1MN8dV3BM=\n"
- "ntor-onion-key-crosscert 1\n"
+ "ntor-onion-key 43r7FnWu5hrjSRXEIEGIOsja18U1+5/zMUDWqOlKSRc=\n"
+ "ntor-onion-key-crosscert 0\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf55AbsqLdLPMf0B7PPlfh9vAd4X4FAQN9Vqx/JPFMjh+FGLAN8xr/w3KFVi\n"
- "yXoP/az6hIbJh0HYCwH8D1rPoQLcdpe8XVwFSrHGarZesdslIwc9dZa/D1dx3OGO\n"
- "UhJOrdv51QY=\n"
+ "AQoABstQAcdVgCBWycsKxSAXjIrFHyYPJ5VEBInotqfXHADj27QyAFEDwHRfJikw\n"
+ "3q2nD4w+XXQg5kk4g+pKuFaVSIbO1Xem9F2Hd+0JgiLlDSuAgLeUKiZIqGAm2Cil\n"
+ "vDw1Z+8kHAA=\n"
"-----END ED25519 CERT-----\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "bLmdO7ME5vq+c9y/Hd8EyBviMBTeo85sHZF/z6Pehc3Wg3i1BJ8DHSd1cK24Pg48\n"
- "4WUrGTfonewuzJBDd3MLkKe6epXmvUgvuQN5wQszq1+u9ap/mRf6b3nEG0MHxMlO\n"
- "FLx5MBsScuo+Q+pwXZa8vPuKTtEjqbVZivdKExJuIX0=\n"
+ "LVjbq3IyLJSQ09ywgtPZ11ddpq6Mbldd7CsX7VAE66ihd5LMJmEVuugilHZqIvQW\n"
+ "JeXJylZWvqbwFEy4DDZCTZBh9aXUouZEIm3jNxyWDu5LKs9M/cKZTXcleWiipDue\n"
+ "yS72i2K2l9zPY+YoNMElc9TlC+lrOlpaT+fwR+93cWo=\n"
"-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
- " router-sig-ed25519 4DSdPePrToNx3WQ+4GfFelB8IyHu5Z9vTbbLZ02vfYEsCF9QeaeHbYagY/yjdt+9e71jmfM+W5MfRQd8FJ1+Dgxx\n"
+ "ipv6-policy kfdslfdfj sdjfk sdfjsdf\n"
+ "router-sig-ed25519 T9pQHeYGU9voVeSoywCtL62Ep2EyYSO7DWjwVOkLxQccAyBa3NS1sBaEVEPXyDtnXeZQUL2hCDy4kEulLimnDQ\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "LqNGEa10zwSPeomBXTfgvBnnWAdWyiR7KYZq9T++jK4ctR6hUaWngH8qSteUrkMx\n"
- "gyWb6UMmlxdfOG0sdcU463HsqV7zObaKya8/WwQ9elj3FfsToswUCeOaLR/Rg7wC\n"
- "zcUjI5VsneQoXT2WVZbZBLsLB3+7QfezVHRMB377GAY=\n"
+ "HDzaU7OdsTuFtjmHwqXkJ/+DCkTyz1vzd39F5L1x2dDZHqk0DJNHy5E6jWpN4yqF\n"
+ "m3nvoKS2II8r06NX7gloF67lfwTtEVc11HZWqyuzAQPZZj2VlPGH/vbTA1NL8MjM\n"
+ "Qn7yzykq8Ry+mLVJ4b1vtZOHm67K4q3V3pSBG5AKO68=\n"
"-----END SIGNATURE-----\n"
;
-
-static const char EX_RI_ED_BAD_CROSSCERT1[] =
+static const char EX_RI_BAD_FAMILY[] =
"router fred 127.0.0.1 9001 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf55AV1AfOvQWKlWsbzoBdJc5m72ShIJuA8eNV15basjhXYdAQAgBABy+KQK\n"
- "3oLDGtqL5kwRmjAsls/+C6SAoAALll7U7wNSH7en5RVBal4RUzCf57ea/KG0c9V8\n"
- "2DmZ3PdOt2aY/M2bWGmmH/tyyapOoV98dhDwFU7zcx/pMfRnJTDRSDwl8QE=\n"
+ "AQQABstQAURbCqkJspCMD7ju6hc5A5b+nTEaKJ+Pay1TpF7nYZXhAQAgBADzX5sn\n"
+ "pjOeXa3eX/C9pVLjwtq5VRddbd7lf0JNlZ1ad3wtO0l5ETftHyU6QoA4g1ZU6itY\n"
+ "IQVLmIdvHo4nXMvUDPWvzEMZiD1epyNnVHglyJXMzC5dzUteE/Jdb0wx8gU=\n"
"-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMP6xbqbj+x1mq5XImjeT0rUzqKZTgBd5zvK4Xcy9IifJuFC9+mMzrY4\n"
- "WhYbdClxKUkDMkit9MVhek+P/w5TSHKl6AuqGaO09ID+hZpoUSdoBUYktynxfGsx\n"
- "kIDu0XvgtAeSyJaVvoV1SKVChY0IBbzUqbHt4O2Q1BhzFCKEJTEzAgMBAAE=\n"
+ "MIGJAoGBAMIwbAgXUtGKe8W2wsaJPqFz2cCaRZy+1ZHEpyMWSN69UDdl+QTEI5qI\n"
+ "W52+bXLXOCQOPLaFtSmfv6i09pPlb9XcyZCfI3W/01KgpKDWFji4QACK7BQCCxaZ\n"
+ "avKwo8eN0XSL5ihcPSZvSMFjX3AdAMLdtYdQVNpCg80NjmfHK1FfAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 81+bJ6Yznl2t3l/wvaVS48LauVUXXW3e5X9CTZWdWnc=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANwWlBh7e/eSLlhto5YUdj1iGYOq+yAmlosDItVfYrSPJuUfM2ocMBAn\n"
- "udbRbWiADoqsbKn/gwwHCC/f1HX2FkRXxxnOlJKLo+NEi8tGmOlcQXSQol1pCpvK\n"
- "sA9TxtYr+Ft4LRpxNrexF+pIBxqzwetqQrZbKYr0CFJi8q1qlMynAgMBAAE=\n"
+ "MIGJAoGBALNX/+fYN5lj6v7UqrK+URDxRBPnrMGCv79WZ7lfSc1yaxFPWqAG/OD1\n"
+ "X7Voqb5xhr5bsszliBe2m0DfOTOPTQ91SyjUoPEXznfHYkbwGVRhNKNa2eN7E1Sl\n"
+ "xw2iSoCnZEpKSaQsLvHvIaYiWnhvHtRl7QCuAym1I1hPPw+BTnkrAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key cs1AP+xF5cXTLuKeOeItdoDAzfALTJkwk9lB4mtC4QI=\n"
- "ntor-onion-key-crosscert 3\n"
+ "ntor-onion-key XjO8+6SaRrPblN+i3FftAlAR1SAij1e/Tlj6x2L6T3U=\n"
+ "ntor-onion-key-crosscert 1\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf55AXL4pAregsMa2ovmTBGaMCyWz/4LpICgAAuWXtTvA1IfAKo6ANUq+hi+\n"
- "xb3J4aYafnszlj87oi/DR+SDf29wzwNw8gmaqGzJ5GbfISfABuTUCzlilZyVnLxi\n"
- "BHcCH6PWiAQ=\n"
+ "AQoABstQAfNfmyemM55drd5f8L2lUuPC2rlVF11t3uV/Qk2VnVp3AFoeOhW877qn\n"
+ "nmT9epNCicfIcyEynHC2865A0htIKT1CCRA6MFNnCMPIs9TpYU0G1zyrvdObtPsm\n"
+ "w+QHaRhFuwg=\n"
"-----END ED25519 CERT-----\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "qC9Kph/kGtONR2DxZDoIFFgnDFC+/7H07EgCiYQdIFIROc+gGK9qBOgeFEptrkXF\n"
- "XdE35xxox5xSASQvp7hjFwxUtJRGOtf2O98regqeeaz6O9VPXHkLf51uqX3bVgq8\n"
- "KvFAsFFS66GxhtbrVjpyRgIwHAYvse1WVESfLuZZTn0=\n"
+ "q0Pp+duh37vyrIjY1gW+16ueGRoXOmFwILm9Eq/6zQedtnUrReTS4CqtkRvMTJp6\n"
+ "JeOOHWD4mcYdoC31NxaYhr/E7aafE/rzRZk0b5H5RgtixVdsrUUcFyWXLsYP+koC\n"
+ "pTk9g3nsOfQCF3u/p0nspsogkZd8qq4fLqyJDK4qh2s=\n"
"-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
+ "family aaaa,bbbb\n"
"reject *:*\n"
- "router-sig-ed25519 3uW8Q1aetIQLOsqSco128ZUaHlhqdYiBvrxV7x75BGNS5RzIMTEwYDNtEX1LNPFJ5N0YOV0HEEOLhrJUV9QCBA\n"
+ "router-sig-ed25519 h4sKEoqV2V/jvbP+AM8dEW7gyXWzMi5u680qa0k4VvgDwj8mkQG7NYguy2O5ovZX5wTE81b9pjNmR7Fx4Wm+Bw\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "WuD7S/saTYBxKvItITbHRi8n+e6g/oVbosicfbRbafYPzPp4Prb+RK03UTafzXrV\n"
- "QEQIzDNhfePcIMH8qX+qrogLMXFqiXx6TVQ0GqNvqirokk8ar3AgtRtewhChAuAj\n"
- "8pmQTj2JpZn/iB3PCE2l/93O9LHZfp44hc8QOWKs6BE=\n"
+ "qEFvYELbbiKjTnXxmbYZDHdeEDIAJrIhxbgLfTFKI6LlOQ+sy5XGd+fCU365U6Mu\n"
+ "0jOej6XL1XQaHE1tFhviGj1pNLlaKL3xK/VDLNhjJSR20adtOQo7UX5NutWhQdSv\n"
+ "L8k5Kqc43XXhqQrMC2nKdFAF43mcp3MesBAnkJVFBqw=\n"
"-----END SIGNATURE-----\n"
- "\n"
- "\n"
- "\n"
;
-static const char EX_RI_ED_BAD_CROSSCERT4[] =
- "router fred 127.0.0.1 9001 0 9002\n"
+static const char EX_RI_ZERO_ORPORT[] =
+ "router fred 127.0.0.1 0 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf55AW5TTGF9jCMl7aALZzqypD9Bj8WYnAPIrKCoIJdgMbY0AQAgBAB7eCn8\n"
- "rukx7t/egZUdqU7+FYqsnO4wdmOkLZkp0+gpF3jjk6N1Q0037NNVNZBjONB0Nm2F\n"
- "CpB3nWSJliSSKr5tOYsuBPFy5VVGYeKPakpOoxanQ1UcqevMBAQy0zf9hwA=\n"
+ "AQQABstQAUmwuikZ7vHosMBCYuyHaTxtFLZstIlPgiR7CYZNyfC6AQAgBABYaoui\n"
+ "ahSEC4liv03C91ZzmpKPUy09X9nOUYgRtb+rsJ6/GklBLyC1pX7YGiCbUfnRcIXE\n"
+ "PRaFkYvku9qdIvj8Zxf+dxPLOQbuNbR7Ky2oLVgLJnC65N5tzoqcN7axWgY=\n"
"-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBALeS5YbeDuKQ5iiuUvh3REoyJ47/YU9lslWmTrVBf9b66pMnYJv/awPu\n"
- "m2HredUAJ3VzwQ38VJA39w3fQXUhQDnQ0OPpKzeAmIiuG+6WdW/mBSK7uKcezC23\n"
- "LA1d6Afyl79LjZz/n+ENXqNMlJk4QPcPHuRnAvwBl3t8YVRPJmxhAgMBAAE=\n"
+ "MIGJAoGBALbQl2VvUsDYFiqLWZdJI5w44z8mmtrDyYC2in84CI7NmBqrqODyVDDV\n"
+ "xU7ZJtIfzmBFiN+oxl3Xja+p2UeZ2qhaPxNwBvpkj3uLoyqjrzxRvzrXOILxrJq0\n"
+ "zsVU6F9J4PD8khEK472XsnEwmY5wK1cVNm/n6eodGppqQbjMal6XAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 WGqLomoUhAuJYr9NwvdWc5qSj1MtPV/ZzlGIEbW/q7A=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAPprokY7utWuO/0252dBB5MCxmVD/dROaIBDyFtpdH+YVv04rkOlDzYD\n"
- "W4mgHVBMxEm/cspTgQmJ4exRHJPpcSe1RYHt1ONZdLYr6D7OOWf0y1IUrVSzF6K4\n"
- "lqlmNuH1H4+TKGbkvixYc5GU/2ZmAy6gFEuphYnBbsN2Ywc38mnfAgMBAAE=\n"
+ "MIGJAoGBAJ71N74R9kO7XgyH0CH2Z4qtr2YKwu+U4FCgBZozMoBe+vcynzNNXRMR\n"
+ "UOKl+hD5nl6CjDO+1Q36iUJPu873CzZv6SXsICnMIkFx/nrMD8JGEiqupjj8H4SS\n"
+ "t3hRhlU6pStjwhqqJozUVinJ+CKCwHG9UnUBGiPNRAwAPU+2VVcHAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key Cgo6xniGfEiuYoLSPUdE4Vb2D4zj2NQzC1lRjysRRXs=\n"
+ "ntor-onion-key 6qko2boqKfkcENCGbCSZ1RbZN3TY2AFqo5WMFnwioC8=\n"
"ntor-onion-key-crosscert 1\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf54AU3MlHAEtdPdAyWJzRBnh4brXbCR9JFLjLM40hsBMoscAJ8cHMIc71+p\n"
- "Qa+lg5JiYb551mLgtPWLy12xdhog7SXiJl3NvnMgbMZXHDqkU2YZCidnVz+xqMdh\n"
- "mjQFK4AtRwg=\n"
+ "AQoABstQAVhqi6JqFIQLiWK/TcL3VnOako9TLT1f2c5RiBG1v6uwAIB8Iig7LEAU\n"
+ "CcznIarqADUWZK/MjxQZHoCdVmb3DlVZ86BWnulrjUnFPINqBRsM1m7a92AHJI28\n"
+ "SdQ+PEw5VAs=\n"
"-----END ED25519 CERT-----\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "bi4M/AJLZF7/vSNmOj4uhrgKBQA/KfcZy5e58mhGL4owxd9vaWfl3aelvb9jf9zN\n"
- "Q7FMv8f9aXzeVIoXIpRJxSKIJgBtG2wnMumIc80pqBvTyGInharszb6njfm0bg1u\n"
- "PfJkbQYyf/dA5l5UwCrjFs06ImDmjFTAdsSWf6DfZ/k=\n"
+ "VAzikUKMdtT0ejXQ9XjA0IFKYyJK3LUpwYRx5jHupvpM9pMww1UpVORwEySOuu/l\n"
+ "iWy+YT2BJ1T1gybHO/BUbMUOCJs746wKaRu1TNoa0iB5hBS08eZHsLcuMPWNj4HZ\n"
+ "8ul4kp0JL6s3SwCyHPx+3ZiXWlAlyixIMwYMYp3iUwA=\n"
"-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
- "router-sig-ed25519 4DSdPePrToNx3WQ+4GfFelB8IyHu5Z9vTbbLZ02vfYEsCF9QeaeHbYagY/yjdt+9e71jmfM+W5MfRQd8FJ1+Dgxx\n"
+ "router-sig-ed25519 wYbZMmEuVaKbcQVwPDuNfqoowIUQB2AXmLhuZn7x7c7Le1K6GJvGxUP51xamZNJtPZpb3B2hY0Q8x+gk5JI9CA\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "io16v+e0pK3sbFzPGnkQrAjrRgIOJHrVZ1RXcxZ1+UNXagWM/MOLhQpkU/cw49Wd\n"
- "4rQeZD3JQh16330eXbxc97AyDgp0b30He846SI0MfW/DnmGI8ZNeYfLbMv2bmbs9\n"
- "QULzyIH8C+5mnMI1arcuiAua+Dpa34F79vgqPuvw5fU=\n"
+ "tiwHHQTe0A/QpY6oom3lG7CbFvTtd9KfAyHN8kZAxo/mctogQw3ZBZbUFZWhrQhl\n"
+ "L57BcL/UgaAAtl7eD3X/91uaoEZl/avxlmvgTEg59aQnBzhAkhj/ZYOjQqTTlfWS\n"
+ "fv8wOQgiuJSKTBBY2LZAJyMDj0oI7PK2JYBtnUvi27A=\n"
"-----END SIGNATURE-----\n"
- "\n"
- "\n"
;
-static const char EX_RI_ED_BAD_CROSSCERT3[] =
+static const char EX_RI_ED_MISSING_CROSSCERT[] =
"router fred 127.0.0.1 9001 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf55AVB+j+B2yPgGywvp7nvejyhMh9ejKmw7LCwufV83Zl9eAQAgBAConA3B\n"
- "jJ3X2tES40jd94rRUFS2/s/Yv7E4LEQ9z0+jz8horNivzK3O/t7IGxJggi+b41/9\n"
- "Uaqt+wqtVuKj0xJ9jwBlCXFt28G2P9s4ZyXYgGZqo7MlJlboybnOMvmoTQA=\n"
+ "AQQABstQAbLkl65prybuOHnQxRi+wVzjNlEsViHPH/T6RWQHtNaIAQAgBAAEVy+i\n"
+ "zeBNENBHHpiag6H+8XDe77msq4YHvxeycWRuJjjNnEcLLQMbtnNFmgzKWwGT2uPj\n"
+ "+U3Z9Rg0+PRkXHKnJKZJLYrglWHjQdiFELn8opGTNX3rkd/FdU9Ws/Fliws=\n"
"-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAPWuEWckT4aYAVNrZzLA8xVwfXp0wzfXeTWBztLS8VzssN6w/+cwXdeY\n"
- "N1YNc2DiD3u8f+7kmuZIqL1EFQUwTvRwEzQXm2dqGM7qkm5ZGNMb5FKu+QwO2ImI\n"
- "FLNiO5zO/LqP3cf/2L8/DuvruLenUrhRtecGFaHmhDYl+2brHIiPAgMBAAE=\n"
+ "MIGJAoGBANyNH7TLjpmgV1TTkT716iNp9tpZHwDHoYWduoiZntmDHpRN4rp0AdhD\n"
+ "LQ5/JEdW/XjAhcnynzINgvGw1nK2XiC/UdTv/Gx6/6Nt9Izn7oAT5YRUOOUaBDYm\n"
+ "9Q8uNo8d/4FrXDEsxaMJme88v2Z6LJd8FozBwlkfeTKdOJon6IabAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 BFcvos3gTRDQRx6YmoOh/vFw3u+5rKuGB78XsnFkbiY=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMtHTfk0gDvp9+PtIG8Ks7rgCiJZ2aihSvr6WaKHYuIprgspFuga98cg\n"
- "D//J80CrgH5Dw68YnkG+gU40IxP7YzhQ4glFlJGu3s2y7Qazcv5ww1XtHur+GDoA\n"
- "cY0zCLhltNQFxIsoVUepY97XA6Y2ejYJjyqNXQcAmoPNoVhnTdkhAgMBAAE=\n"
+ "MIGJAoGBAKT6X+Qm7moNEV7o0oAcrbzpOa0UyOkqWxQkfijqcMbreuMXvfLyBB9l\n"
+ "dgttee0cf0LmWWv9nBtwlbQNgFzkOwcvPRQZ2e1AiFsk/bFlQ5Ow9nxRJoUboL/r\n"
+ "9VCaflE+ETtV+fTl5R1sn3j3OsxK8SOhOl5s+6OAisp3wEaVhjVTAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key ibZf57LptdOK3WpVFXkYMatEEqPhuVWxsnkwF6638V4=\n"
+ "ntor-onion-key DqsbD32Vw56RVM6+gdrE3x0b3DqBsuMsbwOpzYPSB2k=\n"
"ntor-onion-key-crosscert 0\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf55AaicDcGMndfa0RLjSN33itFQVLb+z9i/sTgsRD3PT6PPAEbkxCdI/bH/\n"
- "B06DAjRuoDiv1HKsGuW+UN1iGEiWu2ieFzf3m0Z7BL9p2u2zIbHYkP50b3T3sebD\n"
- "1AksemmMdA0=\n"
+ "AQoABstQAQRXL6LN4E0Q0EcemJqDof7xcN7vuayrhge/F7JxZG4mAHlxXgoRkCMR\n"
+ "QRUsroTKgpVFI6FasFLpfbn1PNzhBwrA0x2Jf5VftmgraI40+oLxL9SiMGzakBfJ\n"
+ "FRXjeMEk2AU=\n"
"-----END ED25519 CERT-----\n"
- "onion-key-crosscert\n"
- "-----BEGIN CROSSCERT-----\n"
- "BpLBsl6Yo64QzczJn0TjdcXC1Jv9IhUG2m/Re3v0voCELOP+t5vkZXXLoVL23oKv\n"
- "JheSkWiuAIEPsatb4afXZ8wZxPcQjwy3zTOBM7p9CG5fA+KYpqKTxAi+dhVYlcDo\n"
- "M7S5nMV63FclkZIT70FFTHwWed1sAKwEO3/Ny24eppc=\n"
- "-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
- "router-sig-ed25519 XS4zVi46Xl3xKhuozPCDlW0QRFD4qUhJmkefonQNsRlMVsrPkALnP2tfnfdfTc69hbNa22pOjJNf6Gm505EnAw\n"
+ "router-sig-ed25519 Dxt546uUdpCxCbO21HaaA6JtW70Xsx5evw9l2eVlWpGDzCTfGO4cMlIUku4ABQdrT6wk3Er9qL5paNyhrYjfBQ\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "Q+R3OpO8VhfvFbXuE5qolhVbgosBHy2A5QS91TMzCbsxa8pBA6Li4QdPR37wvdLq\n"
- "KayfmmNCMKU5qiZMyXqJZm4fdpxiSi50Z0tYlXM3b2OVfza3+pSOEBl89fN6G4Qc\n"
- "pAmM14eEo1UzXrqZw76tMS2CwOYF5vR2xFGCYC0b5hM=\n"
+ "ik0LYc81zprhK5GN0SxE1ikzF+sAzCjo2vhFsihljOyg3d9XxhbriTpROJeUe8Ig\n"
+ "PpgLPeJxPFOvs5jC2XeTAOpxdYyMqC7d/RfupG2v9qBzcj9a84p+tOP1DZKg9snn\n"
+ "NZS6fGWijh+okwRlvbFPk9e4Z6gJUSLthTUhz6P8/LA=\n"
"-----END SIGNATURE-----\n"
- "\n"
- "\n"
- "\n"
;
-static const char EX_RI_ED_BAD_CROSSCERT5[] =
+static const char EX_RI_ED_MISSING_CROSSCERT2[] =
"router fred 127.0.0.1 9001 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf55AaCfOaispi7dJhK0c8HXJHIwoBkMgRpmmHu+3Zce/soMAQAgBAB5bAIo\n"
- "5i4TSY/bV2KQAyziRwvgJm+nEiECClflPbP9Um+zOzOgxtDmNnR5UFQj+VWNG4uf\n"
- "5lnaryN+PfUXZMTcs8AARof3fFz9tVPINHDrsGvKt8gpzgZEHkVioAXOFwg=\n"
+ "AQQABstQAXpNZkKl/K3IRSQvhjsdeSGChzvAux17KOfhfmTGqNXIAQAgBADG8kM5\n"
+ "+9iJxF/Hf2jvvpiZddN8V4RPcJH5i3tIsekmwsaoy3FMnMisGFsOFUjxtSRLmAM5\n"
+ "EtGNJayNNny0qDRo6o/LxmXhl7fVxQPnyFEPjSn93cLWVV6/0LjYaYHUsAo=\n"
"-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAL3Fr/ovZ9SMGYrAM24taKBm/NpemZaXdD/JeBXFYm5Zs3szLwJC4Etm\n"
- "zjNL6tVy+I21O1g3cs16TkflcidsjPXNx//PHAn7bqWMekjrt3SQdkHW2gDPgT2c\n"
- "zYJ/hBR96JYG796jP3pkfJz6Iz5uT/ci3A/cdaVbzM1uZbMUgYGzAgMBAAE=\n"
+ "MIGJAoGBALJTSfgKFoMA5o4dDduwgwHfjU2KE3rZ430TGK9xhBFrum2wG8ct4my7\n"
+ "LS/EbTtxhQjNSrW3D1loThQH7H//cjjrtZyFs4cKwIimpnkRWpQzDtjSUF9vwAGZ\n"
+ "nUPuStPG/hBvJROVUmHV15nAgi+bWigEtXrNCPlpGaojBBIqDRAjAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 xvJDOfvYicRfx39o776YmXXTfFeET3CR+Yt7SLHpJsI=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMHB+1dWa8BBrKE94vTqfbkSEuysG5LyyZF/WrqHq/3W+ocDLz795k8O\n"
- "2Zvgr9im/Ib4hD7IyrtRexcuBdwujdG7cBALdCcWiUTGAMkl96HNETSX+lUVIpJ9\n"
- "pMsc9O7+yz+/0Cl2RpILZCdE/7I96qHpZl3tzlRKSu15WeIm5U77AgMBAAE=\n"
+ "MIGJAoGBAMXYiBXNlbvmWAM3tVe2fC7fazqaQzsXLH39QRhPE2DyldBdsmf8anc9\n"
+ "0rbY8uS/O5WNqc0KK0wivSt8zDLxfkw9GFM3WKgvdiqvRkmpOs5GDvzRdM/yGRNc\n"
+ "gCUBe9q/pE6LQJqoWx6cCcLKGG9Ga8c4WB0ttpiVc3cfoFXEz1RbAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key GXi0a2VLcRHQMMYys85zu3IPqOn5ZTsOixYyQvTGnQs=\n"
- "ntor-onion-key-crosscert 1\n"
- "-----BEGIN BUTTERED CRUMPET-----\n"
- "AQoABf54AU3MlHAEtdPdAyWJzRBnh4brXbCR9JFLjLM40hsBMoscAJ8cHMIc71+p\n"
- "Qa+lg5JiYb551mLgtPWLy12xdhog7SXiJl3NvnMgbMZXHDqkU2YZCidnVz+xqMdh\n"
- "mjQFK4AtRwg=\n"
- "-----END BUTTERED CRUMPET-----\n"
+ "ntor-onion-key N+jVTn3dmb40NOrpkFGvGTskcX6mGPp7uruGdhIlMXk=\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "T9NHMBhuJo+TlfU3TztNgCc9fK1naNRwPOyoqr5R6lJvJ40jkHnIVOFuvuzvZ35O\n"
- "QgPbyFcMjv6leV5xcW+/I9tWaBUFXiRGI27qjCFth4Gxq2B6B2dIcQliLXSvW9b+\n"
- "CMTgDwVa4h2R2PMh18TRx1596ywE09YhCgBF3CwYsiM=\n"
+ "Cnbs898bRLOgjytkt2bzfJmewumRwscGqXDMG10y9QtU+MuZuTl+Mv0w/GmlJG0v\n"
+ "H8ECNQhv642hJOBOuiS1huF4dW2lEhFm+xh0LaxaGFFvJRtuH6NfWDmI1bhN5zbK\n"
+ "RqKeu6QamghmtcwiEym4M1fPPkGbOY2nwJhhEEZOQCg=\n"
"-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
- "router-sig-ed25519 sRpiP9kyW/DGOphp4V2VCtcKNA8i7zGuv2tnljNIPTB7r7KsTvdUk/Ha9ArRQEivO4nC2HHENtknDl3GtWIPCA\n"
+ "router-sig-ed25519 nZA7TcgGlFa64ZViIMqIVNP3d9C6XGY+5so6Ll2Yeu31N6MdIbwrYL99nfCkfwyD2islcHl0kp45c3ZZrkmQDg\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "DtORw3+gO/yUUIp70xDaWSOgQZrJAAoZTNCB7q5WCoZOngeaCiC1Gtc+Fmdn7tER\n"
- "uPqQC5H/Kh3Mi82PCj0JxvNivnNTNY1AZVaIX5YoioXVOkWF0B2pqMvFuDSdm2oJ\n"
- "29PqSVcklquu19EjJRTopIHvYn3sFhQL4LarMsYY11c=\n"
+ "gD19cH/jeIsTBAjds6FflLMXw++Ix9MoWEfFDPAxbD07rdjtU9x6Z9smDAUG29/v\n"
+ "bWvaQPz7mD62IVu/IxINEVOS7vGrSbgvFKzUm9a3FJiQf8oWfHrNE2PNPAZ8GCgF\n"
+ "sdyo0rXyPgMkuW5ZtxDxejaybzVBkIbpADFkJI3B210=\n"
"-----END SIGNATURE-----\n"
- "\n"
- "\n"
- "\n"
;
-static const char EX_RI_ED_BAD_CROSSCERT6[] =
+static const char EX_RI_ED_MISSING_CROSSCERT_SIGN[] =
"router fred 127.0.0.1 9001 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf55ARMMCtQ8pObC5bq02AUE9Lx2bqsZBBkeOsDZVaEq6JavAQAgBABtV0xF\n"
- "CsWXL/uFIBnoEsnXBeU1MvYRFrj1vR7QHdWXnxywXvBYUAC8lu/uyc8qqLp+aQSJ\n"
- "5JzpDYlg3hp1fl5k97iv5F9WrR6s554YpmgYy9agFaxZ4LmRgz7n0UJ8mwM=\n"
+ "AQQABstQAY4Q/FgXCRTVdPYd+7V5rMNtz2yUwCCUHXzduBIWfmbjAQAgBADwQyw5\n"
+ "OWRsl2fz/uGjbzBhT/2AqRNTZCZ1oIR/Lf8ZhY/JbQRCrYwMqMfJz6AHaOJ+gYE9\n"
+ "Z/ooJfYDXMkhBufAy6pgq5HQKKPY9f4drPGrcspQSilJYNsc7xdaPKHfAwk=\n"
"-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAO5qd1TndKD2pEs1ZLWsHlvfO/E7cA0H7NKGLSioGpBf4P0rtkueX4ci\n"
- "kJNa/4Fn/QsLECqEF2lUjkIc8YL+HMS6qteKvN8+nn16DfvnIhPDNZWTJjLl1bOI\n"
- "sWSSiduhanoWQnhRtl3Rxg3opdNd9ApO0DLUNy4Qy18Ai6SgksfHAgMBAAE=\n"
+ "MIGJAoGBAMk3FKSQ9eH4MipJoEzJ8ts3ujO8ed1YutjfFuRZVI658MX1ra9wZdjs\n"
+ "bKfICz0CoT3uJMs5QesGh75r1iXZuFcLq6+WJq/kzI2cIhdDRMQsP48kbKxhwI4C\n"
+ "FkDtK8urxS7Qpq7R2OhLjJwwrN2BcWa8sIOVXZaSp8qxauE11OoVAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 8EMsOTlkbJdn8/7ho28wYU/9gKkTU2QmdaCEfy3/GYU=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAJkMYNpK7eJJyGwD/xG/iNg6gzzbIwrOSvmtoP7Rot42qtBiQ9A9kdsy\n"
- "sazwkWkM93U1+1OaAADPYxeHoyHnuia95Cnc5y2lFSH3I7gnGGSPKSTwXtdyvDWZ\n"
- "P1LbmQ4Bnh5leTCNZ/eFC4/GjNVzqHxjbb8a11dQhA8dOk8PrUq9AgMBAAE=\n"
+ "MIGJAoGBAMGSYXKAwFsZbEbRjiHyGoiiq6EdY0tW9hrmW1ma1nMaIoNbjpR1AVOh\n"
+ "ItYigmRi9zwLZy1b/P9Q8dlazdafc0bb+TISwu+4Cd8BKa7Ca2B43JAR1i7StxpT\n"
+ "DMw5/QqrFw7hiTrFN3K1RVH3ZDMyCD+KjjfQh0RM9ytf3ySniUDFAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key HdSQOqvLr4YnJE1XzzVIddgKgnjaHKJqnq0GqF4wXDg=\n"
- "ntor-onion-key-crosscert 0\n"
+ "ntor-onion-key t1Ps5TqoFvAJxqCLMUcuoovr8Nq2AzwjDPB49Mi48SA=\n"
+ "ntor-onion-key-crosscert\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf55AW1XTEUKxZcv+4UgGegSydcF5TUy9hEWuPW9HtAd1ZefACVwif1deQry\n"
- "K5GeemRa32sGzujVDDe75WRiPKFT3l/EtjTq3oeVq2xwbVJklnG3ASejKTr3YcHt\n"
- "ov0jOl0jywc=\n"
+ "AQoABstQAfBDLDk5ZGyXZ/P+4aNvMGFP/YCpE1NkJnWghH8t/xmFAIQzKPwLjOWJ\n"
+ "VnP514SdbuwehSRrkUMxBSqDxzsDyC5pUCqJhrj3EuXDAMeW5Hz5ukuimdIJyvPu\n"
+ "2cLXN/1Emg4=\n"
"-----END ED25519 CERT-----\n"
"onion-key-crosscert\n"
- "-----BEGIN NAUGHTY MARMOSET-----\n"
- "BpLBsl6Yo64QzczJn0TjdcXC1Jv9IhUG2m/Re3v0voCELOP+t5vkZXXLoVL23oKv\n"
- "JheSkWiuAIEPsatb4afXZ8wZxPcQjwy3zTOBM7p9CG5fA+KYpqKTxAi+dhVYlcDo\n"
- "M7S5nMV63FclkZIT70FFTHwWed1sAKwEO3/Ny24eppc=\n"
- "-----END NAUGHTY MARMOSET-----\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "SaVwgM+jd1yrKldHqi8XalnXOplkBHFOn6AXtxDlCm4rnsb3Spt0006nErCDJJQn\n"
+ "xWkcz3mF2g3Hdf6NeSvAkH13SfqZbHZXQeYVtQHrmIF7TEHL6KHVNJD8ZxIoe0xp\n"
+ "IawxfHSj3FHheiVvXGamM/7fpWyoNvYP3cnZJv6zqCo=\n"
+ "-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
- "router-sig-ed25519 lNY8TRX/FZdH5eFbsBkFHuRi8bPDsE5P+v7zExyD/IXnKS/ffYlP8qw1XIPdEDOIzGQ14+kyPX0SotaAqHRtBA\n"
+ "router-sig-ed25519 f/KOmiv/aPMOnY3S4sKQsnp08KBrQVCT443ehtvYtiTnaSuxUC5tYY4S4rbQaGjNRFNX1Befwi4OvJ3dLFTtCA\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "BHamS+epF77iozo5cBt+tbs22m9GhwY55DRXpEWAtvn67jsMnmn7qCOLONigK1RT\n"
- "adZNezIydcCxXltgHTdKaZw4lcqv3s0KL8kI8frbBmm7PjXtWnrdXBYY+YK54MN/\n"
- "t4N3162o9hzzKSwye0gPjgzpQ1xtEIkzWhBcmE9Vw5s=\n"
+ "JtCuaAENvHhc1tLTI9kkUsRne/OlEeIgB6f+BqMIbxWDpmiw2SHTbYVx6TbKZ2wU\n"
+ "qR3R7SvapeGUIfoVhvVEzxExYTRvFvF/ICDs5vve1aoWilrFstpXsMcL5tG5+ljm\n"
+ "cGJ5PNsTJXrlOy7p/UEHyvgqWcMKxMRBjgMe6je5w7w=\n"
"-----END SIGNATURE-----\n"
- "\n"
;
-static const char EX_RI_ED_BAD_CROSSCERT7[] =
+static const char EX_RI_ED_BAD_SIG1[] =
"router fred 127.0.0.1 9001 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf55AfVmH2ReTyatl4VnS5YREtCM2dwikWuAPffq6M5bysZxAQAgBAAXoqE7\n"
- "taqwLDXLZrZukpF1eBkCwYQK9uzctHTuMdqOHChguvkfX7V4H3O76Ayqvz+Z1ut1\n"
- "KYRdgiArn3viRaBv3ZKT4Z75suMI3bjqGOSGLAKfOa0uLkOmKblHHhSUkwQ=\n"
+ "AQQABstQARhWF2mKrRP75a4g/xPp+fAkIlyKgZa5rKIzGZJiABheAQAgBAB8rr8g\n"
+ "E3MaKYmA93baIS0pvM2tjjeozZTQVzCrP2PykhNcs24ytb7LHgquweVH71Pk3Ltf\n"
+ "Dvl/2MoSFelmOjq4ikrLjntVmnIO1a3aNpt8XmeqjrVg3pBlXqdLdloedQI=\n"
"-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAOLNugzUezzzw+N1SuQWzILJYkUJyQDoVXSZjT0dzBplHCjlrv0WZCUP\n"
- "/pbonE7SlCChIovHcdiASaLj7MVaGgYDq3M1Vtgt5vhgGl10/+evBAD1QEt8AVfr\n"
- "5+PH/sbZvOWucAhNUhOlqFKAn4vdRY39VEEXC5/Jz5fsk1E/DBu5AgMBAAE=\n"
+ "MIGJAoGBAMnGnWWnyF3uo3aFhiph4x2i6yjnHC6ssgDsDR1UA0dUZ7938LcOMPU/\n"
+ "WWUQP50kRx3l7lWPRd3IBm8Xqkg5QFKIoB+0UmHp6jqpVv6p10EyJ7Am0SYcswre\n"
+ "vIZzz6XLEAVeeKVBW5p53KrzIhi8cjbOIofUspcBlHX9omB6Va2nAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 fK6/IBNzGimJgPd22iEtKbzNrY43qM2U0Fcwqz9j8pI=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAKxzg1hsYMS+0zAIrgYxSGO0GbKRrL/VhdlMEGu7ACaoqlGnmGQS3B4B\n"
- "gLk8xDdx9N//8+YTx0hUIxP38w08lubPl1WXMq8s7wAiFd06Nklf65mHs0sXVtS1\n"
- "EG3f97PQqmBpEJOwYBATNcA9e6F62P8SXNkpSjOzNaE0h9wHNKk7AgMBAAE=\n"
+ "MIGJAoGBAMy673ilZFIPOsfMdt1sNYFw9Na/UoOGH8peXmGp5gpFpkJSHamZpqGj\n"
+ "8OdW+KVU2/WzS96fEQ01wC1IiXwcjUtrD6Ny2JKJPARxPADQ31hS67z7gDVjJe9Q\n"
+ "vFzYBf5x3aBKjKHbFMUz7y4L1IeBYfb+F5RBg6yrDA6LsPKKhJdRAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key msdr3O4W4bm/xdmZLzj35363ZSFex8yQxLWsV3wRCAQ=\n"
+ "ntor-onion-key /7ar3nf3rOfiv8Ab01rqVT/ku2jiWZgHHMGW14GPhTs=\n"
"ntor-onion-key-crosscert 1\n"
"-----BEGIN ED25519 CERT-----\n"
- "VQoABx54AU3MlHAEtgPdAyWJzRBnh4brXbCR9JFLjLM40hsBMoscAJ8cHMIc71+p\n"
- "Qa+lg5JiYb551mLgtPWLy12xdhog7SXiJl3NvnMgbMZXHDqkU2YZCidnVz+xqMdh\n"
- "mjQFK4AtRwg=\n"
+ "AQoABstQAXyuvyATcxopiYD3dtohLSm8za2ON6jNlNBXMKs/Y/KSAFcBPlSKXOxY\n"
+ "F25sS5nNj58Z13bBW/WnQ7Dq0kYvS4o80iO4ds91ktwMZiiadfVu2az6tjNRb5+o\n"
+ "iShsVStqfw8=\n"
"-----END ED25519 CERT-----\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "RJJRiU0vjVtRi3bVZru3aTvV5l56X/WOOp/ii316yPAS3aAMpOm1+piFVR5MNqcB\n"
- "ZGyrA2Kx0hawdL2buU47iZ12GOCi4f1Es4V4N0TQgJICsKX38DsRdct9c1qMcqpp\n"
- "1aENSRuaw0szTIr9OgR7/8stqR5c3iF1H5fOhmTi6xM=\n"
+ "TnfcFWCbg72d4tlGSFpe/FATTeRcJVF2R+c6/d86lyPwntkdF6eEJDesEFW2Leil\n"
+ "CQP9eJMiBbaEXU7xcMn9irguQl211lZj3+G47XUFNlORU+HWAR5PNeXj6jSGK89Y\n"
+ "SIduafU14iKNUy2fzAFZooem+OzzDwMKIxTUTiqItfg=\n"
"-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
- "router-sig-ed25519 4DSdPePrToNx3WQ+4GfFelB8IyHu5Z9vTbbLZ02vfYEsCF9QeaeHbYagY/yjdt+9e71jmfM+W5MfRQd8FJ1+Dgxx\n"
+ "router-sig-ed25519 4DSdPePrToNx3WQ+4GfFelB8IyHu5Z9vTbbLZ02vfYEsCF9QeaeHbYagY/yjdt+9e71jmfM+W5MfRQd8FJ1+Dg\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "F3ZqvsyL6RRhPEnNFFIZY4WJM7LK082rseWzRkGNXjwoEwOWUK8enQ4Wjit+wozW\n"
- "4HVIY1F+vP7gm6IiOEAFgEpB4C8FGuyoFw2q0ONA2tqTcvBJDDnqbx08FO7v2Dij\n"
- "d3ucfc5gf7YNaoFCMMuyAzC56eyNk4U+6cSKy6wnJds=\n"
+ "p0PBLzGrU5B4BIwcVcTiJCsSdnWcglG2urJuOSWh2tHx0lWIg5kPUX+WGMh/xarE\n"
+ "0X7xQt6amBZxkL/d70RM222CHg4IwXhRAV1qotY9cBNDKS6nop1Pkx1HOCqmsldy\n"
+ "VSmLG15Igt/y0aYvxPhVDfPUK1UmLH7eYKA7lKOCAbs=\n"
"-----END SIGNATURE-----\n"
;
-
-static const char EX_RI_ED_MISPLACED1[] =
+static const char EX_RI_ED_BAD_SIG2[] =
"router fred 127.0.0.1 9001 0 9002\n"
- "signing-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAKT6OIN6TsDB+xcp1uLeE0K3aiHGqa7hdxMBGpvcD0UFSyzpVv1A/fJa\n"
- "tClDCwTpfTGbyK2L7AO75Ci0c7jf6Pq+V7L6R7o12g6WBTMrgsceC4YqXSKpXNhi\n"
- "oudJyPfVzBfKcJUSynv89FUQOyul/WRRqWTfv0xUsJ3yjuOESfCNAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf55AbBV9NVz0Hdl0Uiv87LiXaTAoeSXE+bheNG4Dju1GzQHAQAgBAD16h+T\n"
- "ygzSgPN4Qat5ITthvm+lvMwMVGbVNWMxNy9i33NGhgp8kqMp2iPAY+LhX8It2b+X\n"
- "8H9cBmYLO5G7AlMPj7GsuWdCdP/M/ldMvFfznlqeE3pCpRas6W48CFJ+9Ao=\n"
+ "AQQABstQAWoTtIdIR0KUNFswr/4eaP/cjngCX15TLiYqCH9qtCSHAQAgBAATcxt4\n"
+ "jNZlgrlMe5Ide4pmPN3MkpkrXFa9ZjIWjFZs/TC7Lg8D70xjvWo9l9GlIMUVcMYV\n"
+ "fWvzlrzTByup2wz9etZfpP4BfuFXgPlQyTHyANTQlEMzlXnA28lD1y8DZg0=\n"
"-----END ED25519 CERT-----\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAL3cADWgf3FVXZvBxRY9dkgCCSy9kcbk0bTbdvvhJSWHpaerpDFTrHou\n"
+ "ELWhGyu5A5yxs9YvK76R6v3Gj/wB/mIhZCJSViTSoyZnBNb0szfJVVyf1/6iOeVH\n"
+ "jtKj3B3kY/WzNVX246lVC2M47F/TmZ2n4TLE2avcnRQjAtULDQk/AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 E3MbeIzWZYK5THuSHXuKZjzdzJKZK1xWvWYyFoxWbP0=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANMO/MepK3uCkKTLRCwIWc/8URVza2gEmDx6mDTJIB/Mw8U8VRDuu4iJ\n"
- "v+LL3D8/HGLvT9a8OXbl5525Zszt8XueF3uePBF0Qp0fjGBL8GFqmrmFe6plurPJ\n"
- "TfrS/m3q+KhXAUowmghciVGDY0kMiDG9X/t/zKLMKWVDYRZk+fupAgMBAAE=\n"
+ "MIGJAoGBAL0Gax09X2sIcIQrDw9mjLVeVHnXEhMteHZtadDkXZJMjdJJaurt55hw\n"
+ "N01apm2qXB9nyUn5sShBadzygFTZzFHe1/MafUTAo7KUdJrpWZr8mBbxWFRBx0W/\n"
+ "OE2Gm1LqIETkeolT+v8LW6VvMPLyexL6myQCGB6yfa6AQkWi335bAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key I8yDO62Flx5O/QsFvgb2ArIRqwJLWetHMeZdxngRl2A=\n"
- "ntor-onion-key-crosscert 1\n"
+ "ntor-onion-key XI8YQWjxy6mxUIPwgS+ZP8GURSEw0r1IgbbOvYNLz2o=\n"
+ "ntor-onion-key-crosscert 0\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf55AfXqH5PKDNKA83hBq3khO2G+b6W8zAxUZtU1YzE3L2LfAGC1uXxN2KwW\n"
- "w4PqRidM1UPZ5jVOHceZYNQcTzzzArfBpr9OraOO2up4TGte8GVqjJNxrZc1gfjn\n"
- "CwPW5WxpFg0=\n"
+ "AQoABstQARNzG3iM1mWCuUx7kh17imY83cySmStcVr1mMhaMVmz9AN7rBobY682w\n"
+ "ItzgJHnDFJv32kjQGc3eKRpZ851GsF/Jj7WXSnLa1oLaLmfFf5tgAKlA3Mi4jUzE\n"
+ "JQCy7jvAygc=\n"
"-----END ED25519 CERT-----\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "jLg3D3VO4i0sN8p2qtB6+5C3tai/K4M89mP7z2abQnUTbynOacPoNXIk4o64DjBJ\n"
- "kaR42yfA7yQZ8Rj8abwgz0Zz6zbd+JjE+s/EklrEEtOl+jZAl3i+92FaHROJojXq\n"
- "hw+ZEPOb9zgb1UQ7S1Fo+GoqA5bdGm/Wg1kSQielkNE=\n"
+ "KxfRSdISHvFhJrKQX018NEb4rtZBZUgdrvaYWjazMkYz4o361wTOxD6lP3azblf9\n"
+ "IqhiXydwCRA7Akye7+muib7JzxSm3wX5iJknRrt8DY141pViMaMvrwXEAqEFyB6b\n"
+ "M/dYGQwUW2iYMkoQ6difHkDQihebE9lgl/WCmq4nRQs=\n"
"-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
- "router-sig-ed25519 TRKvIl/wIIRD4Xcmd6HYmy7tD0KhVGgoStpWPtX0zmXGZ7+jugItrY0frDu9n82syiruuA45ZOs1Rfi4CbOSCg\n"
+ "router-sig-ed25519 XheVxa1Z1HTviM/peYPSAB04YBivv+4v6/HGZ/K4UbEhKTrjSLcvdLG80vP6Owv8676A5al43MLMprjGn7tF6Cg\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "NYpRfurB1YhFmDAdRc2Sd77S7By2V/0kgEHpJhtySb7efiQsyOA4ZBr1zEFPAXdp\n"
- "TviKzyS9kN2fnz3hORoqFul33BDZbiLMNLtt5tzp62TYtmIg9IZdjjczbJUgbVLt\n"
- "KCJL0vM7fdbXkZX61GIBbMYwzwIiHvVxG7F/AS5RbtE=\n"
+ "j9qheDodbn9NZ1S61hjo9aCdHQgRrOqlEYrCMDv8LsMQU1LK6UjmszRxh1q9Hu6V\n"
+ "v7/qGUrsQLjg1Lfdw4qXQYmxTiWnleyncLnxn0Xd5I/S46SCsLoewgGN9uJ6gS/j\n"
+ "UdOEhvT7ShgNSemx9SpRriMKKqTuTQxRmZynr5ibvvw=\n"
"-----END SIGNATURE-----\n"
- "\n"
;
-static const char EX_RI_ED_MISPLACED2[] =
+static const char EX_RI_ED_BAD_SIG3[] =
"router fred 127.0.0.1 9001 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf55AfJo9FIePrxeDNnWT6SWkoz0/L27018XjUNWEHfaR06MAQAgBAAMgolK\n"
- "nLg3ZnVv0skzHCfmX+ZR9Ttwj7FNXfhXCsyr860S79OW5LD0/m1GcS9JflWhP+FO\n"
- "ng5cRb+aqNc8Ul+/4sQudZRx8w4U3d5rOuMGCqhQXnktH9AFzQHFq0jpAAU=\n"
+ "AQQABstQAVdvNBeuh/0X6D1QG7U4LBsMF66U4SuKDKplzNXLiKv7AQAgBADNUwKD\n"
+ "ETv10GLuZWuupZtT6HAGZNIhMHvYd1gGyBaoy86fsINj4Vxi9YctBHudNk2P8VIn\n"
+ "qFkmPvvSkJJaBgjVT638CvpTU3Bva4+8YTor4jpY3Ni6K9f9ALjg4U+UBQ8=\n"
"-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAPeK/znKLRvSUmCIUiZOgfhiRFt7XGN//C2GFuey4xkKiIr9LWMuVe9m\n"
- "Wx39Ea2UGEtNGCEVvZdJMDVRl7heFTfJTN4L1YeyWx6iNRWlpAmgQOKII7slHwlq\n"
- "seEULOLOXc9AsU/v9ba9G54DFbHfe2k44ZOwEmaQZW5VF/I0YMMdAgMBAAE=\n"
+ "MIGJAoGBANws+5gBYCgJhS4fYgStezRe+Y9mfuvTKWub9ytiZIiaPjtC4cu6+wuP\n"
+ "9bEQgiESx6GXL4L+CtcOSc8COFRPv1PxFXjkMKXfTAx57Rw8xc1qotWNshSUp7rL\n"
+ "JxSjOuEHd/dctIebor9akKPypAwnJhqrq+bqf9/kGaHckxK/ask/AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 zVMCgxE79dBi7mVrrqWbU+hwBmTSITB72HdYBsgWqMs=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAKFRzlrqPPxEW0nboAJ1qzKFb/vFtvRW0xNVb8RtbOY/NY5FV1hS8yfH\n"
- "igtugkrOBmWah7cmJhiON2j+TKeBxEoXwJMZeyV+HLbr7nY/mFhad4BQ3Frkl8d6\n"
- "1kQMhOJswMdwnnVHPNGUob4YAX0SpFA6MpBVj92zmMBeaihqUS9VAgMBAAE=\n"
+ "MIGJAoGBAMD0OLUYVhMiZz7tpxztxNwMTj4dQU9l++rRTfb+7vVZ+KAIb/8rjiU1\n"
+ "XXyV3AekijxQlOghj36lZBtethX8RyahsHmWyGqo1UmqCU1PtwfihdYuofvyI8Iu\n"
+ "V89G6QilsCPy2rpgYmEkmHt68FwlMnTjPUiKI5dZUk5WKrxsTgsxAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key br8svioLcJCAQxoo3KvlT288p8rb4lQIZNLlplkIKkw=\n"
- "ntor-onion-key-crosscert 0\n"
+ "ntor-onion-key DTa03lDz0APjbwCJN864xaYSxbPbVulLoAZIC4M4wGE=\n"
+ "ntor-onion-key-crosscert 1\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf55AQyCiUqcuDdmdW/SyTMcJ+Zf5lH1O3CPsU1d+FcKzKvzAG9XqwmRm0uJ\n"
- "E49NoHcWr9IzdIwSGo+PJSkVpk95a5p2s065BetCWxEEBJQniajQf2hZ36zmV9rq\n"
- "a6puqkEAKAM=\n"
+ "AQoABstQAc1TAoMRO/XQYu5la66lm1PocAZk0iEwe9h3WAbIFqjLABej8E/aUX6f\n"
+ "2KFbmHFALYZCxszNCfg9HGQ+hfTjuTPONZ9yzudUoTTKq8MIMCD/5WKfzMJAHq/P\n"
+ "qNQuVt/gGA8=\n"
"-----END ED25519 CERT-----\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "d6QGIVAJL5JjHUyV+aicLIdBYyxHwviKpPcp7uldRF8vfDGFpu0qFgJ5KT+3t36w\n"
- "QY1r75bvUMG/ZzGKDg95dcK0X2AK6GFlcrYyCoQEVOsuPc1QEUeK9P2s7viNQE4V\n"
- "tRwG/CvJhPfcnxErzVGfXIeYRL1r/hPNFDZSeSxPPM0=\n"
+ "syosw/6anYcwlNT5fGd1vCw9uFBUckIjGz3DmS1vVXzsTrdppcFotmzzYjV491xR\n"
+ "q8AyGyLlVIIuXabVuE+94ZpzDLWs82NqWMiYPNSNW2ctSVu+AE/KYjJCCz0SIE8/\n"
+ "bq40OQNQ6TNLWv1ubxZSDwcXrn4/VcV9IJrFjLpw2rA=\n"
"-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
- "router-sig-ed25519 ts9pFk8PnDWtXgQad09XC/ZCbruSx1U1pNOMWF9fyoNG0CodxdDH9Vglg+BOS7Nd9fmsINfPWKCVdVuSSM7zCA\n"
+ "proto Link=5\n"
"reject *:*\n"
+ "router-sig-ed25519 lemondcustard\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "YMl6mpQm7UCsPQhZKMm0aZ7fzGevWzRbQO+de20HTn7fVqMWQf2hBDJe9QTN/uDK\n"
- "/VKYT8SnIBexbrSMy1N5q8kNFKxxUtwA9GRtz620Vvc4m+lz/tnT9qucIKCDL5iJ\n"
- "eRpnls0JoAMIHKl99zdUioYubmOZuqUaRAdT8ulWy+Y=\n"
+ "d6F2sfCgQmo60QBPGGLZvMvwxw1h6DOlJO5NR31lgBrkLjnbaMJEtA8fNWOX5zW0\n"
+ "gXXrJlL0qlENGJUZeUFobxDOVzTA3dz92q97t/jqBu3pgjmyESesFFkAgqqAGjYh\n"
+ "RxUxJCDlyrmduGnl5GkjOVkS6UDhzRSRc+csxyXXp7E=\n"
"-----END SIGNATURE-----\n"
- "\n"
;
-static const char EX_RI_ED_BAD_CERT1[] =
+static const char EX_RI_ED_BAD_CROSSCERT1[] =
"router fred 127.0.0.1 9001 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf55AYf+rX8a5rzdTBGPvLdQIP8XcElDDQnJIruGqfDTj+tjAP+3XOL2UTmn\n"
- "Hu39PbLZV+m9DIj/DvG38M0hP4MmHUjP/iZG5PaCX6/aMe+nQSNuTl0IDGpIo1l8\n"
- "dZToQTFSzAQ=\n"
+ "AQQABstQAdQYl0NSJKxsHa9dGLZVBp+MohQmFDGSYOxdAmmrPS79AQAgBAD17lds\n"
+ "HKOpu0Y2u4RCynTWwgdA9YZWYgkB1GSeOzuy/8CaWrZvEg0iaZmsYIlgeujMxq/v\n"
+ "WEFzug6zYefoz93cN13o3pzAKY05A+KMvWPUnmvSlMqwlbnhjt3EjYoW9QQ=\n"
"-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAM4o2DrTwn3wrvUMm41S/hFL5ZtRHGRDh26o8htn14AKMC65vpygKFY7\n"
- "fUQVClAiJthAs5fD/8sE5XDtQrLnFv5OegQx8kSPuwyS/+5pI1bdxRJvKMOUl2Tc\n"
- "fAUhzeNBmPvW3lMi9Fksw5sCSAKQ5VH/+DlYvBGZIO49pTnOAty1AgMBAAE=\n"
+ "MIGJAoGBAMBQN6sno1t3m1izKZEoo63H5WrHfskJVor73sc7lDAo8BvQk110pIEd\n"
+ "2SGaFS9BNIUe51u4y8X+rDi3qXt5I11ifusvI1S6CMaM0p+Xh4osQGuvb31COpU7\n"
+ "MMOOxCVhmf2D/Vu1KuB+pNB91I7Id3BXRNdX7cuBCjdVEzdVZ9MTAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 9e5XbByjqbtGNruEQsp01sIHQPWGVmIJAdRknjs7sv8=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMzIsJeEWWjN3Lp6qrzaJGn8uhJPJyjy2Wt3sp7z7iD/yBWW6Q7Jku3e\n"
- "C5QfKmSmNi2pNjS0SqPjqZZNsbcxpq/bEOcZdysZG1lqi/QgxUevk57RWjh3EFsG\n"
- "TwK3ougKWB5Q6/3m32dNsnnnDqzVapgZo7Zd3V/aCo0BVtL5VXZbAgMBAAE=\n"
+ "MIGJAoGBANK1iFyjGQGns3jmNpkO8t1f2RkWQTA9VS2xwbIZ0QE2QT3miu7ny3F5\n"
+ "992sLvs/XJGRh0Wr8I06MTXYqu1aZdqF+ailw/WTWwsqkWZwwRni8zWGW20zJ4Wv\n"
+ "2X5FmPQXQFVXb1pRmICIt94zQONE67xxfzG7pPs5IVl71WRFs6JnAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key W28nwT/5FJ818M78y/5sNOkxhQ7ENBhjVhGG2j6KvFY=\n"
- "ntor-onion-key-crosscert 0\n"
+ "ntor-onion-key ddfknkGy8CYAOi/IVWmQyBLb6hgY2KZSct8tCNRXzx0=\n"
+ "ntor-onion-key-crosscert 1\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf55AYf+rX8a5rzdTBGPvLdQIP8XcElDDQnJIruGqfDTj+tjAP+3XOL2UTmn\n"
- "Hu39PbLZV+m9DIj/DvG38M0hP4MmHUjP/iZG5PaCX6/aMe+nQSNuTl0IDGpIo1l8\n"
- "dZToQTFSzAQ=\n"
+ "AQoABf55AXL4pAregsMa2ovmTBGaMCyWz/4LpICgAAuWXtTvA1IfAKo6ANUq+hi+\n"
+ "xb3J4aYafnszlj87oi/DR+SDf29wzwNw8gmaqGzJ5GbfISfABuTUCzlilZyVnLxi\n"
+ "BHcCH6PWiAQ=\n"
"-----END ED25519 CERT-----\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "FWnEjvFob0ObgqohMT7miwGsAuioCT7Urz6tyWaGWph/TP9hbFWj4MPK5mt998mn\n"
- "xA8zHSF5n/edu7wVX+rtnPrYPBmg+qN8+Pq6XMg64CwtWu+sqigsi6vtz/TfAIDL\n"
- "mypENmSY32sWPvy/CA8dAZ2ASh57EH9a+WcFModpXkM=\n"
+ "zW3a26ATVWny3gEALe2VETRNIOFKMlRMCGjAKEyGQsGddSRYm08daaZkX7TzKRFq\n"
+ "TwZAcQ4BzhwCcnQtb/zwMSW1eIdKgO1rqZLhdo/awUuRtuPeG0vPoqahIQH3X81r\n"
+ "vh/Iy6f1xp3sfasib5AO8wZWhJ+LHaA1yt7DCfQBudU=\n"
"-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
- "router-sig-ed25519 88YqJdGJS4O6XiUCNrc9xbOHxujvcN/TkCoRuQQeKfZGHM+4IhI6AcXFlPIfDYq0SAavMhVmzsDDw0ROl7vyCQ\n"
+ "router-sig-ed25519 hKynmNoTSZn+Au4mlsO+yWIvCn9g2SpITDdbKDAgdLQ8qXJRG/oxiKOlmGuhpz7Q4ETSChkfOab4II3GNhQWBg\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "cU4WDO3w9ZfVRbNUgxOQMbwS2xWXvaL+cZmIV6AAjAZVWkLEpif4g6uYu+jJUZOS\n"
- "NUT7lNOMwTu4tE4b1YJpnD9T8iW0DlOXxlvRBMQYmKwhQuYk898BDGTSk+0AY0HJ\n"
- "vv8wRVewDajNhW7tFY907IdHvPXG0u83GANxkYrRyUg=\n"
+ "X37fMViJCh6+AQbMIWW9y8XwHridRmgcW5vZT93357C1NRy4MkuJt5O7sZ9YWE9g\n"
+ "8kKeeKRjXUfudbu00P/pmTKbLBucsPounK5uSpTs18FAed1p0wRDeM3KaddQsGjI\n"
+ "WuJe8hOufwyUWdFBBLJhH1rsCLJlY5P2lC6Wgs5WyEE=\n"
"-----END SIGNATURE-----\n"
- "\n"
;
-static const char EX_RI_ED_BAD_CERT2[] =
+static const char EX_RI_ED_MISPLACED1[] =
"router fred 127.0.0.1 9001 0 9002\n"
- "identity-ed25519\n"
- "-----BEGIN WOBBLY RUTABAGA-----\n"
- "helo\n"
- "-----END WOBBLY RUTABAGA-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANZvqyqFeiekh8ApqIGK4ZtOqjaX87EzDestvAWwamVOXiPoUrzXgM3O\n"
- "l8uuTnMA4TfnjLyyA2TnaMzJylOI1OMHuW/D9B/liWDstSxWNNIlKgLQ/Dh9xBS7\n"
- "uQb2PYlI+iMkPKPyJQSTDdGHE7cdFPewUfhRtJU3F5ztm/3FLBFvAgMBAAE=\n"
+ "MIGJAoGBAKh/VcmuyOszxrGZY8xIGAbQ7bXnSVf3iL+9RBKi3Lva0oN90zLYKfKt\n"
+ "Z0hBB/lHukUeaUZhTNx8ASTcoFnTcMD8rw1XQbjVyTdPWrHNVhZEGAD8TmeOrjEP\n"
+ "6/cLJTKxY2EAv/1Uli0F+mWInINRzdsa0EB9MbU9R1yr0YZMQZ8NAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABstQAWka/Nj7mht9fCo+vwXF59aGNWMDeuOhkcBq1m/WjG2vAQAgBABDDm8X\n"
+ "xgMoftELU7Umgf44257ImjgG1okFpkTGOq+K489uFUre+q+Ikurp+4H7j9d6kCIA\n"
+ "htYSDr1LfVBzxPttICRAX0cLg1rnIWRdB8TzXehF4/0hHAjtwkYKnPiVQQI=\n"
+ "-----END ED25519 CERT-----\n"
+ "master-key-ed25519 Qw5vF8YDKH7RC1O1JoH+ONueyJo4BtaJBaZExjqviuM=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANZl8U/Z8KCPS7EBDzt8i9kNETXS7vnp9gnw3BQNXfjiDtDg9eO7ChxY\n"
- "NBwuOTXmRxfX3W9kvZ0op9Hno6hixIhHzDql+vZ+hN7yPanVVDglSUXcr31yBm5K\n"
- "kA+ZnRvH3oVQ97E4rRzpi09dtI13Pzu7JS5jRMtH+JF1kQBoNC0dAgMBAAE=\n"
+ "MIGJAoGBAO9rHWfTdV5l8VtwNtwEDhd0BtmQpqxkXN0SV9pa6NLKeVMcROmlKL0u\n"
+ "EmF5njuLZTDRJk48HaT3/anU4qUGiDxtIU2np+eFkrYyLvyiaGyc20ph4ffLVzbG\n"
+ "VCSSkIVz4TYamplaBkY6yY+IBBk1u/klmeCBvgMhSIISxUklkxudAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key lUrEL+TVXpjjHQ2BIKk34vblyDmoyMro1a6/9hJ4VRc=\n"
- "ntor-onion-key-crosscert 0\n"
+ "ntor-onion-key PKfyrBmRFyANA+2PZAXawdNZom3VF+Cfg9lKy2OjuWM=\n"
+ "ntor-onion-key-crosscert 1\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf55Abm5E7FBdd3F8N1xuz/vdv03zh2lABrmGjzPQ3AFJtntALNeQTgjv0JL\n"
- "jON4+SPNi0B2Bva3yKaSsdxiHQ1rIwQqIUVkzXmmX4jmsvJK/9gERAdD7GafTKZQ\n"
- "BaZbNXBvmQw=\n"
+ "AQoABstQAUMObxfGAyh+0QtTtSaB/jjbnsiaOAbWiQWmRMY6r4rjAJQykafOIJRQ\n"
+ "ex8+e+xpwVpyJJOidTVW2bBWG0ZIi+4W5Dj9eFiuV9x2kPTy7ZFueNAWZ7NstyTr\n"
+ "vLtNc5qRrg4=\n"
"-----END ED25519 CERT-----\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "OxkqFsw1vHUQ9iPYcKC/MHUBtbLPK6JY2i81ccAai2eW118UXcTbeCRccrXyqSkl\n"
- "RLcooZyli1D6wg9x7O8+2+HXIbUa6WcTOD1Qi7Z9wKZfk4sDUy7QHKENMRfAXwX3\n"
- "U/gqd4BflMPp4+XrYfPzz+6yQPWp0t9wXbFv5hZ9F3k=\n"
+ "tqzgSiMy4U6J/yyYhg5hVIqO0vAgAwIMYPXWDRvAIomfnIpUCkHSIdyLD+7a4Yp3\n"
+ "ZhXbLug85b6bK3pOTB2cLI9v2gwsgOyewUdt8prZLTOPDF3EDRD7UKCNMrQIIBw6\n"
+ "kKwKIJVhAQKPi+gC2n7i07Y4zjGTaV4CiWe2h6E61lc=\n"
"-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
- "router-sig-ed25519 fW6Bt4R3xVk5KMDyOcYg8n5ANP0OrQq2PQFK2cW0lTAdi+eX+oT/BeWnkrn0uSWOC/t4omCmH4Rdl8M9xtpfBA\n"
+ "router-sig-ed25519 A1DMqknKoPrPRHr1Y1j8cd22Ziwcfl7b/3VKI4pthyLnFRpb768nlHi615YdwSve4L71d+c4vGMuKyeCcGbFDQ\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "DHxiQXuLxZR0ylqwUGGePgN4KF4ItlOV/DuGmmszCO/Ut0p+5s4FP2v6Mm9M92Wj\n"
- "75rS9xF/Ts0Kf49dvgc+c5VTvhX5I5SwGQkRk0RNJtNoP0t+qXBHaFV8BlAeaWF6\n"
- "Lg3O+GUK325fQv9uDPCe37mFQV9jafAzsZUrO/ggb1U=\n"
+ "KaOyGt84OBS8/83TQWKkfMLk/r/1ebWiA2Wkgda2cWx2L3Dh9V/3PDGwAWoG6m1r\n"
+ "20mVuLKwWCCNYG2fGC4J/NMETXI5p5b1+ze1KDYiO5hQtTJvMktmfa5+p0xLB43M\n"
+ "xjzpDoX0A37hP9XJa5d1Q7G2cnd64P70QqhToDtoswc=\n"
"-----END SIGNATURE-----\n"
- "\n"
;
-static const char EX_RI_ED_BAD_CERT3[] =
+static const char EX_RI_ED_MISPLACED2[] =
"router fred 127.0.0.1 9001 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "BVVVnf55AW5TTGF9jCMl7aALZzqypD9Bj8WYnAPIrKCoIJdgMbY0AQAgBAB7eCn8\n"
- "rukx7t/egZUdqU7+FYqsnO4wdmOkLZkp0+gpF3jjk6N1Q0037NNVNZBjONB0Nm2F\n"
- "CpB3nWSJliSSKr5tOYsuBPFy5VVGYeKPakpOoxanQ1UcqevMBAQy0zf9hwA=\n"
+ "AQQABstQATjkYvZoN/RVHbJNtRWwmkazJVupqF/prNxdNJnRDWlDAQAgBADCNrLD\n"
+ "VQBs6tkIMGcR0PB+jrCvIuiQGGJzLsIfvxrG5UXWZsFEA5CnF6Lvjqu6p1CRkUF4\n"
+ "kpNC9xWcK8yDWhDCd5DLmFEDGFw/cD4rRACKatnQsGMN3KfDioWweSBI9wk=\n"
"-----END ED25519 CERT-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAPgeQNbKwpnTU+qW/2djh66hptS9rcy1B4vdyWkDTdREao2ECuCv691Y\n"
- "oIw3MpTWvpC1qHIKorunusR0FKgwXw3xQTikXbDq/1ptsekzoIA1R/hltQV3UuGH\n"
- "zdzHuQXAMX7Fdll2gyya03c3Yq5s+xSDvGdkEeaIoctKjwxp4SdNAgMBAAE=\n"
+ "MIGJAoGBAKdyNeuXJvnloOXD3iUxvvS7OBux3tpTfKxGdx124adeAKkiRL7EmXk3\n"
+ "LaUbHL3IhsVaf6JeyRzc+onEsD/uNeO0P7+GtvC5ZAkj1/6MxBaJioLGXoIacMak\n"
+ "NpmDYxhTcG75aEwgZX2RTla1j+5bIoG1o5Z76dkFMVUWsRtthFNRAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 wjayw1UAbOrZCDBnEdDwfo6wryLokBhicy7CH78axuU=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAOzWuH4cPW9rIrfi8MrruMUg4IUVHz4BxfY4/szMIUvzeEAdHn4FYkWy\n"
- "Vt7MDtUELZsmZeFNmkn72kLxnrdZ5XhxZBriq1Fzq11cSWRBF+SyE1MdcouY4GyG\n"
- "drw6T8xb8ty19q0eO6C/gw27iqXPAp1clvkroLg6Nv9lGZvsedVDAgMBAAE=\n"
+ "MIGJAoGBANBQwXgkKvrnfMDKDkV5x1bxlR07x+AOru5ypJH4qQh+GMYXpnkw0T7r\n"
+ "anIJtEFP0+FpbaRRI/xAPMpFUFsbeNH/+Yeove/6kKfv1rlgqWr/yI2XIW8Fl70i\n"
+ "DW2cnW43cwa/HDitFjE5vnkvkMWFn1XIgwhm7+NDIDbnmDkKZ8U7AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key /vYZ+9yLqG7yUnutoI57s96JBl36GTz0IDWE244rbzE=\n"
+ "ntor-onion-key CbrcCjCeTGum8vZumB6lvTA00BztRN8tNn41GLHdkUI=\n"
"ntor-onion-key-crosscert 0\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf55AZ4zVBWP/fIYEgWmyj0WpO6CkXRJjtrWXtiT02k3IddiAMpYgMemGIpN\n"
- "xj7TQRULsHHYvo4fLcKrSgndQbUUhfLTUuVhIzbnE2TBLMVOEkpxKU6mTuvTT/3h\n"
- "MJugrwTWVg4=\n"
+ "AQoABstQAcI2ssNVAGzq2QgwZxHQ8H6OsK8i6JAYYnMuwh+/GsblANS8qpQqkLmw\n"
+ "vcRttr/HvckIBY8i99OoqctPQziRUq2Up6Ag1b1MSgN3knRfi6wjmpz9Jn149kFx\n"
+ "HQ8sTCSu+QI=\n"
"-----END ED25519 CERT-----\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "c/Vqu3wtsTsYMdnhTS9Tn1Pq6jDmH4uRD5WmbaCKKrkin2DjuYSMVpypndkdlZDE\n"
- "He7uF7SUO3QG/UcRIXYOsg9MSLUmvn2kIwef8ykyqlRh95Csjo5DyattUhL2w4QF\n"
- "tJkJBQAnXWaAVW1O8XimGCAvJ84cxbmZEcpN6WKjrXI=\n"
+ "DOH8ntVhHlms3NjkOvsCf5Qu1/DhHmJOL+J8ySD89lT2RBt0K07G9vAjc4NkkUpD\n"
+ "N2e9myNWbDCp8sjsYzWfqpv94IypSBEfwQFgV6peoAZxHkq35Nj9sIJ+rQloanJJ\n"
+ "RZkWyu1GILpggcNvWS6BYQQcRxu/lStLy917s24U7co=\n"
"-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "router-sig-ed25519 whWcVxkGo+l29Hsn+BLP96MReHTxQHTSgmMMzeQ4jZ0qV6B9kkj1Ma21oyl3iTmUCOtexgOiX5fImfMLkOxFDQ\n"
+ "proto Link=5\n"
"reject *:*\n"
- "router-sig-ed25519 Ue7bkPpOoc8ca7cyQj/Vq3BP5X4vwLA5QmpLGw/WfRNVRPojJRxU3RVqWMi3JbsJFRTe6pH6ZHyXER33G5aAAA\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "ifKUtbxmqHVs8A0oT5n7Te0c6D/XqWQTc0RxX9OKGspzh6wNX26h0Xa2vpK1Q9Zu\n"
- "sj61I7vbHuZN6rxiWs9IzJgb//XaNJasX1pd9tbGSXW+yYzc9G9kaa7vp3HcnhIP\n"
- "XVWzzS8WmOiVNGcF65j6f7yGloTgN7cHMptgJG7pWes=\n"
+ "py73sIYGI4awS9g4JFTSElHCg5pWYqEjLz/jbON7pZ80GGUG5wxXVxNRwtGvMrWk\n"
+ "zG2tW7SBm0TH6wdWeE5NhN1VSjgCqw7qSk2MJS2XHn5hBRTxzF4/Es/TJaziAqvY\n"
+ "e8ehZwqDPcG0vMhd97/uxoyKNdkyObhW+RNYRtGvCxg=\n"
"-----END SIGNATURE-----\n"
- "\n"
;
-static const char EX_RI_BAD_EI_DIGEST2[] =
+static const char EX_RI_ED_BAD_CERT1[] =
"router fred 127.0.0.1 9001 0 9002\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf55ATrK8IVBWLO2yXKCqXLXJOTu89W2b+hREPO+tCrxjVqWAQAgBACG/vVx\n"
- "NK8wKVZvf34d75ZObSR0ge1N2RrAIKNslNXBq/tcllIrNE4S0ZNcMpA+hxXoVFeo\n"
- "jbxifYX7nTs5N3GrGPmkiuo82v2X6ZwoIXJGFnvWMxCjsYsUVDDxoT6h/w8=\n"
+ "AQoABf55AYf+rX8a5rzdTBGPvLdQIP8XcElDDQnJIruGqfDTj+tjAP+3XOL2UTmn\n"
+ "Hu39PbLZV+m9DIj/DvG38M0hP4MmHUjP/iZG5PaCX6/aMe+nQSNuTl0IDGpIo1l8\n"
+ "dZToQTFSzAQ=\n"
"-----END ED25519 CERT-----\n"
- "extra-info-digest E5FAC29E766D63F96AD175069640E803F2723765 99oo\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAK9wHSdRalxkuAybrSCA3dlEC1ZGc7oHOzXRGLg+z6batuiCdQtus1Rk\n"
- "LP821eZJtEMAE56aewCIHDcTiCxVa6DMqmxRjm5pfW4G5H5QCPYT6Fu0RoYck3Ef\n"
- "vkgits5/fNYGPPVC7k8AdGax5dKj5oFVGq+JWolYFRv6tyR9AThvAgMBAAE=\n"
+ "MIGJAoGBALkr+jsRorIXiOA6obO6OLPitE/d+OzWz1SH6CHRs0m5KL+T6M9t0qqK\n"
+ "O2BTOmrjPTaGdEsakkcfiZeSj02MviuSadZ/JF8FoAYx9yCbmlAh/FE3qvoY1lrE\n"
+ "mAZhA2sTc32sHusQNBKRFfGHeckaE0i9MW7L+Crq2dLcwI/YZEldAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "master-key-ed25519 brKx2WhJlN4ExqUOr6CTx20MX57JkAetrrTwpt1cEt8=\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAKxjxTQ/T/MHpFbk7/zwA7l5b3IW3yVcyVe6eIGFoYun8FI0fbYRmR4M\n"
- "G5Asu07gP9Bbgt3AFPuEqrjg4u+lIkgqTcCgKWJbAgm7fslwaDTXQ36A7I1M95PD\n"
- "GJ10Dk5v4dVbrqwoF7MSrQPFtMO91RP11nGPSvDqXZJ4XpwqwdxpAgMBAAE=\n"
+ "MIGJAoGBAM8kNdNCiheKwYmN+wA+/aCLtr1aRJtoYggQPGT3rhm8m2bOhxixjdCD\n"
+ "jiDkqfYjnaNizNnwpS47h1MWHzgTWKF/QS4JXvCG5M56KDJot2z03qbdoRUv5+Z9\n"
+ "yQIx6ad1p2Km24P4IHmAYItwFBGir7y86C6mOdX4Sp139hDJOIsZAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key LuVmHxpj4F5mPXGNi4MtxbIbLMav6frJRBsRgAvpdzo=\n"
- "ntor-onion-key-crosscert 0\n"
+ "ntor-onion-key AP9U8b/4WUiOB899TlNgoYrnUdUqrwQYLgF0Smsj8E0=\n"
+ "ntor-onion-key-crosscert 1\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf55AYb+9XE0rzApVm9/fh3vlk5tJHSB7U3ZGsAgo2yU1cGrAKBcSzwi4lY/\n"
- "salCELOLdeZzOjDNnBd6cKp2WJg7Yz5zFlbVbyNk0iwfGmucHk8vQZe5BS0Oq/Pz\n"
- "B1u/BcJv8gk=\n"
+ "AQoABstQAW6ysdloSZTeBMalDq+gk8dtDF+eyZAHra608KbdXBLfAKPMVgkcGgA4\n"
+ "8B+Bu8/lk14zBtzryJKvwg8UVOVd0tPnX7GiVyPmDCPbEZPnHG3Yvq+ir6HkiZAO\n"
+ "mirgIIhkPwI=\n"
"-----END ED25519 CERT-----\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "QsAQVdDVHtasDbhrZG4ZxImdTTMY7fz3vouAiGyZx6/jCCB5v0gHwTn4xo6pgLEW\n"
- "LQfMhQZIr76Ky67c0hAN2hihuDlfvhfVe9c2c5UOH1BOhq3llE3Hc3xGyEy3rw7r\n"
- "5y38YGi759CvsP2/L8JfXMuBg89OcgJYFa27Q6e6MdQ=\n"
+ "GnUJtlnkqHZKQAzwNPgAesR1R7hebqY/hMIKj9s/y+PxGgs+aNP2gfv4W+dtQ209\n"
+ "jHGxF+n6s2hm3Am0EFQ2h1ULTJh9uYnIs1f1kyx8DdydXdx3pZcURLRenmiRowB7\n"
+ "iGn76ICqqGVZKpGtszmSe3L35XXl7HwzJTjYzcs95vo=\n"
"-----END CROSSCERT-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
+ "proto Link=5\n"
"reject *:*\n"
- "router-sig-ed25519 5zoQ0dufeeOJ/tE/BgcWgM8JpfW1ELSXLz4dI+K8YRH/gUtaPmYJgU2QfeUHD0oy1iwv4Qvl8Ferga7aBk1+DA\n"
+ "router-sig-ed25519 RqA4oirneie/ywl6j99vc2B1mUlMfIlakR7M6M4Minf7x6t7EMOsNVvOMKBSsPaBu/qcoOwhMynHdhTCmWHpBw\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "D6KRMwkb6JmVEnpZ825SD3LMB84UmVy0i94xk44OwhoWNKLXhaSTWJgf6AqnPG5o\n"
- "QrCypSb44bYLn+VaDN5LVUl36jeZqCT4xd+4ZwIRdPOUj7vcVmyUDg3lXcAIk97Q\n"
- "E5PrQY1mQuLSIjjKInAR2NRBumNJtRw31Y/DTB7tODU=\n"
+ "Ui31suskhBbwTRc24NfUneh1c2LfUqjap5dCCfdmoVgvTSnk2RDW+IC4jwwFliWp\n"
+ "Gs2RJsPy527LRPRrXKJv3MnKO6uUPZXUjs/QZjdJgTMCzLY7jJBwnmAqj5BjUMfO\n"
+ "+S3hOhBZlDmLeYk4p+sppZjR0P9EFy2e3U3homiz1dM=\n"
"-----END SIGNATURE-----\n"
- "\n"
;
diff --git a/src/test/failing_routerdescs.template b/src/test/failing_routerdescs.template
new file mode 100644
index 0000000000..cc2bae3a40
--- /dev/null
+++ b/src/test/failing_routerdescs.template
@@ -0,0 +1,812 @@
+:::comment=this file is to be used with the makedescs.py utility
+:::name=MINIMAL
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+
+
+:::name=MAXIMAL
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject 127.0.0.1:*
+accept *:80
+reject *:*
+ipv6-policy accept 80,100,101
+uptime 1000
+hibernating 0
+unrecognized-keywords are just dandy in this format
+platform Tor 0.2.4.23 on a Banana PC Jr 6000 Series
+contact O.W.Jones
+fingerprint {d.RSA_FINGERPRINT}
+read-history 900 1,2,3,4
+write-history 900 1,2,3,4
+extra-info-digest AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+hidden-service-dir
+allow-single-hop-exits
+family $AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA $BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+caches-extra-info
+or-address [::1:2:3:4]:9999
+or-address 127.0.0.99:10000
+opt fred is a fine router
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+
+
+:::comment=this one has somebody else's signature.
+:::name=BAD_SIG1
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+-----BEGIN SIGNATURE-----
+aV5gqy5fTtsrdntTPRPGdeN376lXK+blHJuqbAL0WQ7XaMB4r+F8/whFu0cObOqD
+AqAhxkcMu721iYCkUNQvhc3FDou2i1mBJFDrhZEtux/2aXODIMG+OPdDUCyBqeQR
+oYLLfLR4ZZic1tlBFRRNdtXGF2SHeIM052F7PbeJz2A=
+-----END SIGNATURE-----
+
+
+:::name=bad_tokens
+:::type=ri
+router bob
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=bad_published
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 99:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=bad_bandwidth
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth why hello there
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=bad_onionkey
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+-----BEGIN RSA PUBLIC KEY-----
+MIGHAoGBANBKlyoqApWzG7UzmXcxhXM4T370FbN1edPbw4WAczBDXJslXCU9Xk1r
+fKfoi/+WiTGvH7RcZWPm7wnThq2u2EAO/IPPcLE9cshLBkK28EvDg5K/WsYedbY9
+1Gou+7ZSwMEPv2b13c7eWnSW1YvFa64pVDKu2sKnIjX6Bm0HZGbXAgED=
+-----END RSA PUBLIC KEY-----
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=bad_ports
+:::type=ri
+router fred 127.0.0.1 900001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=neg_bandwidth
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 -1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=bad_ip
+:::type=ri
+router fred 100.127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=bad_dirport
+:::type=ri
+router fred 127.0.0.1 9001 0 bob
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=bad_name2
+:::type=ri
+router verylongnamethatnevereverendsandgoesontoolong 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=bad_bandwidth2
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 hello 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=bad_uptime
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+uptime forever-and-a-day
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=bad_bandwidth3
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 -1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=bad_ntor_key
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key x{d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=bad_fingerprint
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+fingerprint 5555
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=mismatched_fingerprint
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+fingerprint CC43 DC8E 8C9E 3E6D 59CD 0399 2491 0C8C E1E4 50D2
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=bad_has_accept6
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+accept6 *:80
+reject6 *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=bad_no_exit_policy
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=bad_ipv6_exit_policy
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+ipv6-policy kfdslfdfj sdjfk sdfjsdf
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=bad_family
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+family aaaa,bbbb
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=zero_orport
+:::type=ri
+router fred 127.0.0.1 0 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=ed_missing_crosscert
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=ed_missing_crosscert2
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=ed_missing_crosscert_sign
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+:::name=ed_bad_sig1
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 4DSdPePrToNx3WQ+4GfFelB8IyHu5Z9vTbbLZ02vfYEsCF9QeaeHbYagY/yjdt+9e71jmfM+W5MfRQd8FJ1+Dg
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=ed_bad_sig2
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 X{d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=ed_bad_sig3
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 lemondcustard
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=ed_bad_crosscert1
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert 1
+-----BEGIN ED25519 CERT-----
+AQoABf55AXL4pAregsMa2ovmTBGaMCyWz/4LpICgAAuWXtTvA1IfAKo6ANUq+hi+
+xb3J4aYafnszlj87oi/DR+SDf29wzwNw8gmaqGzJ5GbfISfABuTUCzlilZyVnLxi
+BHcCH6PWiAQ=
+-----END ED25519 CERT-----
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=ed_misplaced1
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+signing-key
+{d.RSA_IDENTITY}
+identity-ed25519
+{d.ED_CERT}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=ed_misplaced2
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+{d.ED_CERT}
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+router-sig-ed25519 {d.ED_SIGNATURE}
+proto Link=5
+reject *:*
+router-signature
+{d.RSA_SIGNATURE}
+
+
+:::name=ed_bad_cert1
+:::type=ri
+router fred 127.0.0.1 9001 0 9002
+identity-ed25519
+-----BEGIN ED25519 CERT-----
+AQoABf55AYf+rX8a5rzdTBGPvLdQIP8XcElDDQnJIruGqfDTj+tjAP+3XOL2UTmn
+Hu39PbLZV+m9DIj/DvG38M0hP4MmHUjP/iZG5PaCX6/aMe+nQSNuTl0IDGpIo1l8
+dZToQTFSzAQ=
+-----END ED25519 CERT-----
+signing-key
+{d.RSA_IDENTITY}
+master-key-ed25519 {d.ED_IDENTITY}
+onion-key
+{d.RSA_ONION_KEY}
+ntor-onion-key {d.NTOR_ONION_KEY}
+ntor-onion-key-crosscert {d.NTOR_CROSSCERT_SIGN}
+{d.NTOR_CROSSCERT}
+onion-key-crosscert
+{d.RSA_CROSSCERT_ED}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+proto Link=5
+reject *:*
+router-sig-ed25519 {d.ED_SIGNATURE}
+router-signature
+{d.RSA_SIGNATURE}
diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am
index d0711f05d6..ef952c3812 100644
--- a/src/test/fuzz/include.am
+++ b/src/test/fuzz/include.am
@@ -7,17 +7,18 @@ FUZZING_CFLAGS = \
FUZZING_LDFLAG = \
@TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) @TOR_LDFLAGS_libevent@
FUZZING_LIBS = \
- $(TOR_INTERNAL_TESTING_LIBS) \
+ src/test/libtor-testing.a \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \
@TOR_LIBEVENT_LIBS@ $(TOR_LIBS_CRYPTLIB) \
- @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@ \
+ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@ \
@TOR_SYSTEMD_LIBS@ \
@TOR_LZMA_LIBS@ \
- @TOR_ZSTD_LIBS@
+ @TOR_ZSTD_LIBS@ \
+ @TOR_TRACE_LIBS@
oss-fuzz-prereqs: \
- $(TOR_INTERNAL_TESTING_LIBS)
+ src/test/libtor-testing.a
noinst_HEADERS += \
src/test/fuzz/fuzzing.h
diff --git a/src/test/hs_test_helpers.c b/src/test/hs_test_helpers.c
index 5116fc7169..e9aafa4760 100644
--- a/src/test/hs_test_helpers.c
+++ b/src/test/hs_test_helpers.c
@@ -75,7 +75,8 @@ 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, OP_EQ, 0);
}
- ip->auth_key_cert = tor_cert_create(signing_kp, CERT_TYPE_AUTH_HS_IP_KEY,
+ ip->auth_key_cert = tor_cert_create_ed25519(signing_kp,
+ CERT_TYPE_AUTH_HS_IP_KEY,
&auth_kp.pubkey, now,
HS_DESC_CERT_LIFETIME,
CERT_FLAG_INCLUDE_SIGNING_KEY);
@@ -110,7 +111,8 @@ hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now,
}
ed25519_keypair_from_curve25519_keypair(&ed25519_kp, &signbit,
&curve25519_kp);
- cross_cert = tor_cert_create(signing_kp, CERT_TYPE_CROSS_HS_IP_KEYS,
+ cross_cert = tor_cert_create_ed25519(signing_kp,
+ CERT_TYPE_CROSS_HS_IP_KEYS,
&ed25519_kp.pubkey, time(NULL),
HS_DESC_CERT_LIFETIME,
CERT_FLAG_INCLUDE_SIGNING_KEY);
@@ -155,7 +157,7 @@ hs_helper_build_hs_desc_impl(unsigned int no_ip,
sizeof(ed25519_public_key_t));
desc->plaintext_data.signing_key_cert =
- tor_cert_create(&blinded_kp, CERT_TYPE_SIGNING_HS_DESC,
+ tor_cert_create_ed25519(&blinded_kp, CERT_TYPE_SIGNING_HS_DESC,
&signing_kp->pubkey, now, 3600,
CERT_FLAG_INCLUDE_SIGNING_KEY);
tt_assert(desc->plaintext_data.signing_key_cert);
diff --git a/src/test/include.am b/src/test/include.am
index 7814dbca89..cdf3b20c48 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -54,6 +54,7 @@ else
# Only do this when coverage is not on, since it invokes lots of code
# in a kind of unpredictable way.
TESTSCRIPTS += src/test/test_rebind.sh
+TESTSCRIPTS += src/test/test_include.sh
endif
endif
@@ -170,6 +171,7 @@ src_test_test_SOURCES += \
src/test/test_crypto_rng.c \
src/test/test_data.c \
src/test/test_dir.c \
+ src/test/test_dirvote.c \
src/test/test_dir_common.c \
src/test/test_dir_handle_get.c \
src/test/test_dispatch.c \
@@ -193,11 +195,13 @@ src_test_test_SOURCES += \
src/test/test_hs_cache.c \
src/test/test_hs_descriptor.c \
src/test/test_hs_dos.c \
+ src/test/test_hs_metrics.c \
src/test/test_introduce.c \
src/test/test_keypin.c \
src/test/test_link_handshake.c \
src/test/test_logging.c \
src/test/test_mainloop.c \
+ src/test/test_metrics.c \
src/test/test_microdesc.c \
src/test/test_namemap.c \
src/test/test_netinfo.c \
@@ -233,6 +237,7 @@ src_test_test_SOURCES += \
src/test/test_sendme.c \
src/test/test_shared_random.c \
src/test/test_socks.c \
+ src/test/test_statefile.c \
src/test/test_stats.c \
src/test/test_status.c \
src/test/test_storagedir.c \
@@ -304,18 +309,17 @@ src_test_test_switch_id_LDADD = \
$(TOR_UTIL_TESTING_LIBS) \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \
- @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_USERENV@ \
- @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
-
+ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_USERENV@ \
+ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ @TOR_TRACE_LIBS@
src_test_test_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) \
@TOR_LDFLAGS_libevent@
src_test_test_LDADD = \
- $(TOR_INTERNAL_TESTING_LIBS) \
+ src/test/libtor-testing.a \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
- $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
+ $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
@CURVE25519_LIBS@ \
- @TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
+ @TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ @TOR_TRACE_LIBS@
src_test_test_slow_CPPFLAGS = $(src_test_test_CPPFLAGS)
src_test_test_slow_CFLAGS = $(src_test_test_CFLAGS)
@@ -339,22 +343,22 @@ src_test_test_memwipe_LDFLAGS = $(src_test_test_LDFLAGS) @CFLAGS_BUGTRAP@
src_test_bench_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) \
@TOR_LDFLAGS_libevent@
src_test_bench_LDADD = \
- $(TOR_INTERNAL_LIBS) \
+ libtor.a \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
- $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
+ $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
@CURVE25519_LIBS@ \
- @TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
+ @TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ @TOR_TRACE_LIBS@
src_test_test_workqueue_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) \
@TOR_LDFLAGS_libevent@
src_test_test_workqueue_LDADD = \
- $(TOR_INTERNAL_TESTING_LIBS) \
+ src/test/libtor-testing.a \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
- $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
+ $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
@CURVE25519_LIBS@ \
- @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
+ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ @TOR_TRACE_LIBS@
src_test_test_timers_CPPFLAGS = $(src_test_test_CPPFLAGS)
src_test_test_timers_CFLAGS = $(src_test_test_CFLAGS)
@@ -364,9 +368,9 @@ src_test_test_timers_LDADD = \
$(TOR_UTIL_TESTING_LIBS) \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
- $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
+ $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
@CURVE25519_LIBS@ \
- @TOR_LZMA_LIBS@
+ @TOR_LZMA_LIBS@ @TOR_TRACE_LIBS@
src_test_test_timers_LDFLAGS = $(src_test_test_LDFLAGS)
# ADD_C_FILE: INSERT HEADERS HERE.
@@ -398,20 +402,21 @@ noinst_PROGRAMS+= src/test/test-hs-ntor-cl
src_test_test_ntor_cl_SOURCES = src/test/test_ntor_cl.c
src_test_test_ntor_cl_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB)
src_test_test_ntor_cl_LDADD = \
- $(TOR_INTERNAL_LIBS) \
+ libtor.a \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \
- $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
- @CURVE25519_LIBS@ @TOR_LZMA_LIBS@
+ $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
+ @CURVE25519_LIBS@ @TOR_LZMA_LIBS@ @TOR_TRACE_LIBS@
src_test_test_ntor_cl_AM_CPPFLAGS = \
$(AM_CPPFLAGS)
src_test_test_hs_ntor_cl_SOURCES = src/test/test_hs_ntor_cl.c
src_test_test_hs_ntor_cl_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB)
src_test_test_hs_ntor_cl_LDADD = \
- $(TOR_INTERNAL_LIBS) \
+ libtor.a \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \
- $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @CURVE25519_LIBS@
+ $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ \
+ @CURVE25519_LIBS@ @TOR_TRACE_LIBS@
src_test_test_hs_ntor_cl_AM_CPPFLAGS = \
$(AM_CPPFLAGS)
@@ -423,7 +428,8 @@ src_test_test_bt_cl_LDADD = \
$(TOR_UTIL_TESTING_LIBS) \
$(rust_ldadd) \
@TOR_LIB_MATH@ \
- @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@
+ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
+ @TOR_TRACE_LIBS@
src_test_test_bt_cl_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS)
endif
@@ -438,6 +444,8 @@ EXTRA_DIST += \
src/test/slownacl_curve25519.py \
src/test/test_rebind.sh \
src/test/test_rebind.py \
+ src/test/test_include.sh \
+ src/test/test_include.py \
src/test/zero_length_keys.sh \
scripts/maint/run_check_subsystem_order.sh \
src/test/rust_supp.txt \
diff --git a/src/test/rend_test_helpers.c b/src/test/rend_test_helpers.c
index 61bacb4d2e..8e40167aeb 100644
--- a/src/test/rend_test_helpers.c
+++ b/src/test/rend_test_helpers.c
@@ -2,6 +2,7 @@
/* See LICENSE for licensing information */
#include "core/or/or.h"
+#include "core/or/extendinfo.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "test/test.h"
#include "feature/rend/rendcommon.h"
@@ -58,7 +59,8 @@ create_descriptor(rend_service_descriptor_t **generated, char **service_id,
for (i = 0; i < intro_points; i++) {
rend_intro_point_t *intro = tor_malloc_zero(sizeof(rend_intro_point_t));
crypto_pk_t *okey = pk_generate(2 + i);
- intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
+ intro->extend_info =
+ extend_info_new(NULL, NULL, NULL, NULL, NULL, NULL, 0);
intro->extend_info->onion_key = okey;
crypto_pk_get_digest(intro->extend_info->onion_key,
intro->extend_info->identity_digest);
@@ -66,8 +68,12 @@ create_descriptor(rend_service_descriptor_t **generated, char **service_id,
base16_encode(intro->extend_info->nickname + 1,
sizeof(intro->extend_info->nickname) - 1,
intro->extend_info->identity_digest, DIGEST_LEN);
- tor_addr_from_ipv4h(&intro->extend_info->addr, crypto_rand_int(65536));
- intro->extend_info->port = 1 + crypto_rand_int(65535);
+ tor_addr_t addr;
+ uint16_t port;
+ /* Does not cover all IP addresses. */
+ tor_addr_from_ipv4h(&addr, crypto_rand_int(65536) + 1);
+ port = 1 + crypto_rand_int(65535);
+ extend_info_add_orport(intro->extend_info, &addr, port);
intro->intro_key = crypto_pk_dup_key(pk2);
smartlist_add((*generated)->intro_nodes, intro);
}
@@ -91,4 +97,3 @@ mock_rend_data(const char *onion_address)
DIGEST_LEN));
return rend_query;
}
-
diff --git a/src/test/slow_ed25519.py b/src/test/slow_ed25519.py
index be4eeab857..df1456b811 100644
--- a/src/test/slow_ed25519.py
+++ b/src/test/slow_ed25519.py
@@ -24,7 +24,7 @@ def H(m):
def expmod(b,e,m):
if e == 0: return 1
- t = expmod(b,e/2,m)**2 % m
+ t = expmod(b,e//2,m)**2 % m
if e & 1: t = (t*b) % m
return t
@@ -32,11 +32,11 @@ def inv(x):
return expmod(x,q-2,q)
d = -121665 * inv(121666)
-I = expmod(2,(q-1)/4,q)
+I = expmod(2,(q-1)//4,q)
def xrecover(y):
xx = (y*y-1) * inv(d*y*y+1)
- x = expmod(xx,(q+3)/8,q)
+ x = expmod(xx,(q+3)//8,q)
if (x*x - xx) % q != 0: x = (x*I) % q
if x % 2 != 0: x = q-x
return x
@@ -56,23 +56,23 @@ def edwards(P,Q):
def scalarmult(P,e):
if e == 0: return [0,1]
- Q = scalarmult(P,e/2)
+ Q = scalarmult(P,e//2)
Q = edwards(Q,Q)
if e & 1: Q = edwards(Q,P)
return Q
def encodeint(y):
bits = [(y >> i) & 1 for i in range(b)]
- return ''.join([chr(sum([bits[i * 8 + j] << j for j in range(8)])) for i in range(b/8)])
+ return bytes(sum([bits[i * 8 + j] << j for j in range(8)]) for i in range(b//8))
def encodepoint(P):
x = P[0]
y = P[1]
bits = [(y >> i) & 1 for i in range(b - 1)] + [x & 1]
- return ''.join([chr(sum([bits[i * 8 + j] << j for j in range(8)])) for i in range(b/8)])
+ return bytes([(sum([bits[i * 8 + j] << j for j in range(8)])) for i in range(b//8)])
def bit(h,i):
- return (ord(h[i/8]) >> (i%8)) & 1
+ return (h[i//8] >> (i%8)) & 1
def publickey(sk):
h = H(sk)
@@ -87,7 +87,7 @@ def Hint(m):
def signature(m,sk,pk):
h = H(sk)
a = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2))
- r = Hint(''.join([h[i] for i in range(b/8,b/4)]) + m)
+ r = Hint(bytes([h[i] for i in range(b//8,b//4)]) + m)
R = scalarmult(B,r)
S = (r + Hint(encodepoint(R) + pk + m) * a) % l
return encodepoint(R) + encodeint(S)
@@ -109,12 +109,11 @@ def decodepoint(s):
return P
def checkvalid(s,m,pk):
- if len(s) != b/4: raise Exception("signature length is wrong")
- if len(pk) != b/8: raise Exception("public-key length is wrong")
- R = decodepoint(s[0:b/8])
+ if len(s) != b//4: raise Exception("signature length is wrong")
+ if len(pk) != b//8: raise Exception("public-key length is wrong")
+ R = decodepoint(s[0:b//8])
A = decodepoint(pk)
- S = decodeint(s[b/8:b/4])
+ S = decodeint(s[b//8:b//4])
h = Hint(encodepoint(R) + pk + m)
if scalarmult(B,S) != edwards(R,scalarmult(A,h)):
raise Exception("signature does not pass verification")
-
diff --git a/src/test/test-memwipe.c b/src/test/test-memwipe.c
index 4faf7bc5a1..5e4cc7678e 100644
--- a/src/test/test-memwipe.c
+++ b/src/test/test-memwipe.c
@@ -30,8 +30,8 @@ const char *s = NULL;
#define BUF_LEN 2048
#define FILL_BUFFER_IMPL() \
+ do { \
unsigned int i; \
- unsigned sum = 0; \
\
/* Fill up a 1k buffer with a recognizable pattern. */ \
for (i = 0; i < BUF_LEN; i += strlen(s)) { \
@@ -42,7 +42,8 @@ const char *s = NULL;
/* optimized away. */ \
for (i = 0; i < BUF_LEN; ++i) { \
sum += (unsigned char)buf[i]; \
- }
+ } \
+ } while (0)
#ifdef OpenBSD
/* Disable some of OpenBSD's malloc protections for this test. This helps
@@ -55,7 +56,8 @@ static unsigned
fill_a_buffer_memset(void)
{
char buf[BUF_LEN];
- FILL_BUFFER_IMPL()
+ unsigned sum = 0;
+ FILL_BUFFER_IMPL();
memset(buf, 0, sizeof(buf));
return sum;
}
@@ -64,7 +66,8 @@ static unsigned
fill_a_buffer_memwipe(void)
{
char buf[BUF_LEN];
- FILL_BUFFER_IMPL()
+ unsigned sum = 0;
+ FILL_BUFFER_IMPL();
memwipe(buf, 0, sizeof(buf));
return sum;
}
@@ -73,7 +76,8 @@ static unsigned
fill_a_buffer_nothing(void)
{
char buf[BUF_LEN];
- FILL_BUFFER_IMPL()
+ unsigned sum = 0;
+ FILL_BUFFER_IMPL();
return sum;
}
@@ -116,7 +120,8 @@ static unsigned
fill_heap_buffer_memset(void)
{
char *buf = heap_buf = raw_malloc(BUF_LEN);
- FILL_BUFFER_IMPL()
+ unsigned sum = 0;
+ FILL_BUFFER_IMPL();
memset(buf, 0, BUF_LEN);
raw_free(buf);
return sum;
@@ -126,7 +131,8 @@ static unsigned
fill_heap_buffer_memwipe(void)
{
char *buf = heap_buf = raw_malloc(BUF_LEN);
- FILL_BUFFER_IMPL()
+ unsigned sum = 0;
+ FILL_BUFFER_IMPL();
memwipe(buf, 0, BUF_LEN);
raw_free(buf);
return sum;
@@ -136,7 +142,8 @@ static unsigned
fill_heap_buffer_nothing(void)
{
char *buf = heap_buf = raw_malloc(BUF_LEN);
- FILL_BUFFER_IMPL()
+ unsigned sum = 0;
+ FILL_BUFFER_IMPL();
raw_free(buf);
return sum;
}
diff --git a/src/test/test.c b/src/test/test.c
index 4b6082ce4f..ffea158141 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+->a * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
@@ -44,6 +44,7 @@
#include "lib/compress/compress.h"
#include "app/config/config.h"
#include "core/or/connection_edge.h"
+#include "core/or/extendinfo.h"
#include "feature/rend/rendcommon.h"
#include "feature/rend/rendcache.h"
#include "feature/rend/rendparse.h"
@@ -564,7 +565,8 @@ test_rend_fns(void *arg)
for (i = 0; i < 3; i++) {
rend_intro_point_t *intro = tor_malloc_zero(sizeof(rend_intro_point_t));
crypto_pk_t *okey = pk_generate(2 + i);
- intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
+ intro->extend_info =
+ extend_info_new(NULL, NULL, NULL, NULL, NULL, NULL, 0);
intro->extend_info->onion_key = okey;
crypto_pk_get_digest(intro->extend_info->onion_key,
intro->extend_info->identity_digest);
@@ -573,9 +575,12 @@ test_rend_fns(void *arg)
base16_encode(intro->extend_info->nickname + 1,
sizeof(intro->extend_info->nickname) - 1,
intro->extend_info->identity_digest, DIGEST_LEN);
+ tor_addr_t addr;
+ uint16_t port;
/* Does not cover all IP addresses. */
- tor_addr_from_ipv4h(&intro->extend_info->addr, crypto_rand_int(65536));
- intro->extend_info->port = 1 + crypto_rand_int(65535);
+ tor_addr_from_ipv4h(&addr, crypto_rand_int(65536) + 1);
+ port = 1 + crypto_rand_int(65535);
+ extend_info_add_orport(intro->extend_info, &addr, port);
intro->intro_key = crypto_pk_dup_key(pk2);
smartlist_add(generated->intro_nodes, intro);
}
@@ -613,8 +618,12 @@ test_rend_fns(void *arg)
tt_mem_op(gen_info->identity_digest,OP_EQ, par_info->identity_digest,
DIGEST_LEN);
tt_str_op(gen_info->nickname,OP_EQ, par_info->nickname);
- tt_assert(tor_addr_eq(&gen_info->addr, &par_info->addr));
- tt_int_op(gen_info->port,OP_EQ, par_info->port);
+ const tor_addr_port_t *a1, *a2;
+ a1 = extend_info_get_orport(gen_info, AF_INET);
+ a2 = extend_info_get_orport(par_info, AF_INET);
+ tt_assert(a1 && a2);
+ tt_assert(tor_addr_eq(&a1->addr, &a2->addr));
+ tt_int_op(a2->port,OP_EQ, a2->port);
}
rend_service_descriptor_free(parsed);
@@ -700,6 +709,7 @@ struct testgroup_t testgroups[] = {
{ "dir/", dir_tests },
{ "dir/auth/process_descs/", process_descs_tests },
{ "dir/md/", microdesc_tests },
+ { "dirauth/dirvote/", dirvote_tests},
{ "dir/voting/flags/", voting_flags_tests },
{ "dir/voting/schedule/", voting_schedule_tests },
{ "dir_handle_get/", dir_handle_get_tests },
@@ -720,6 +730,7 @@ struct testgroup_t testgroups[] = {
{ "hs_descriptor/", hs_descriptor },
{ "hs_dos/", hs_dos_tests },
{ "hs_intropoint/", hs_intropoint_tests },
+ { "hs_metrics/", hs_metrics_tests },
{ "hs_ntor/", hs_ntor_tests },
{ "hs_ob/", hs_ob_tests },
{ "hs_service/", hs_service_tests },
@@ -728,6 +739,7 @@ struct testgroup_t testgroups[] = {
{ "legacy_hs/", hs_tests },
{ "link-handshake/", link_handshake_tests },
{ "mainloop/", mainloop_tests },
+ { "metrics/", metrics_tests },
{ "netinfo/", netinfo_tests },
{ "nodelist/", nodelist_tests },
{ "oom/", oom_tests },
@@ -760,6 +772,7 @@ struct testgroup_t testgroups[] = {
{ "sendme/", sendme_tests },
{ "shared-random/", sr_tests },
{ "socks/", socks_tests },
+ { "statefile/", statefile_tests },
{ "stats/", stats_tests },
{ "status/" , status_tests },
{ "storagedir/", storagedir_tests },
diff --git a/src/test/test.h b/src/test/test.h
index 18987719d0..56037648d3 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -122,6 +122,7 @@ extern struct testcase_t crypto_rng_tests[];
extern struct testcase_t crypto_tests[];
extern struct testcase_t dir_handle_get_tests[];
extern struct testcase_t dir_tests[];
+extern struct testcase_t dirvote_tests[];
extern struct testcase_t dispatch_tests[];
extern struct testcase_t dns_tests[];
extern struct testcase_t dos_tests[];
@@ -140,6 +141,7 @@ extern struct testcase_t hs_control_tests[];
extern struct testcase_t hs_descriptor[];
extern struct testcase_t hs_dos_tests[];
extern struct testcase_t hs_intropoint_tests[];
+extern struct testcase_t hs_metrics_tests[];
extern struct testcase_t hs_ntor_tests[];
extern struct testcase_t hs_ob_tests[];
extern struct testcase_t hs_service_tests[];
@@ -149,6 +151,7 @@ extern struct testcase_t keypin_tests[];
extern struct testcase_t link_handshake_tests[];
extern struct testcase_t logging_tests[];
extern struct testcase_t mainloop_tests[];
+extern struct testcase_t metrics_tests[];
extern struct testcase_t microdesc_tests[];
extern struct testcase_t namemap_tests[];
extern struct testcase_t netinfo_tests[];
@@ -186,6 +189,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 statefile_tests[];
extern struct testcase_t stats_tests[];
extern struct testcase_t status_tests[];
extern struct testcase_t storagedir_tests[];
diff --git a/src/test/test_addr.c b/src/test/test_addr.c
index cf5aad7e71..dbc581288d 100644
--- a/src/test/test_addr.c
+++ b/src/test/test_addr.c
@@ -341,6 +341,7 @@ test_addr_ip6_helpers(void *arg)
test_pton6_bad("0XYXXY");
test_pton6_bad("0x");
test_pton6_bad("0X");
+ test_pton6_bad("2000::1a00::1000:fc098");
/* test internal checking */
test_external_ip("fbff:ffff::2:7", 0);
diff --git a/src/test/test_address.c b/src/test/test_address.c
index 4cedbda347..e7007f22f3 100644
--- a/src/test/test_address.c
+++ b/src/test/test_address.c
@@ -713,7 +713,7 @@ test_address_udp_socket_trick_blackbox(void *arg)
#else /* !(0) */
/* Both of the blackbox test cases fail horribly if:
- * * The host has no external addreses.
+ * * The host has no external addresses.
* * There are multiple interfaces with either AF_INET or AF_INET6.
* * The last address isn't the one associated with the default route.
*
@@ -1152,23 +1152,23 @@ test_address_tor_addr_in_same_network_family(void *ignored)
tor_addr_parse(&a, "8.8.8.8");
tor_addr_parse(&b, "8.8.4.4");
- tt_int_op(addrs_in_same_network_family(&a, &b), OP_EQ, 1);
+ tt_int_op(router_addrs_in_same_network(&a, &b), OP_EQ, 1);
tor_addr_parse(&a, "8.8.8.8");
tor_addr_parse(&b, "1.1.1.1");
- tt_int_op(addrs_in_same_network_family(&a, &b), OP_EQ, 0);
+ tt_int_op(router_addrs_in_same_network(&a, &b), OP_EQ, 0);
tor_addr_parse(&a, "8.8.8.8");
tor_addr_parse(&b, "2001:4860:4860::8844");
- tt_int_op(addrs_in_same_network_family(&a, &b), OP_EQ, 0);
+ tt_int_op(router_addrs_in_same_network(&a, &b), OP_EQ, 0);
tor_addr_parse(&a, "2001:4860:4860::8888");
tor_addr_parse(&b, "2001:4860:4860::8844");
- tt_int_op(addrs_in_same_network_family(&a, &b), OP_EQ, 1);
+ tt_int_op(router_addrs_in_same_network(&a, &b), OP_EQ, 1);
tor_addr_parse(&a, "2001:4860:4860::8888");
tor_addr_parse(&b, "2001:470:20::2");
- tt_int_op(addrs_in_same_network_family(&a, &b), OP_EQ, 0);
+ tt_int_op(router_addrs_in_same_network(&a, &b), OP_EQ, 0);
done:
return;
@@ -1194,16 +1194,14 @@ helper_free_mock_node(node_t *node)
tor_free(node);
}
-#define NODE_SET_IPV4(node, ipv4_addr, ipv4_port) { \
- tor_addr_t addr; \
- tor_addr_parse(&addr, ipv4_addr); \
- node->ri->addr = tor_addr_to_ipv4h(&addr); \
- node->ri->or_port = ipv4_port; \
+#define NODE_SET_IPV4(node, ipv4_addr_str, ipv4_port) { \
+ tor_addr_parse(&(node)->ri->ipv4_addr, ipv4_addr_str); \
+ node->ri->ipv4_orport = ipv4_port; \
}
#define NODE_CLEAR_IPV4(node) { \
- node->ri->addr = 0; \
- node->ri->or_port = 0; \
+ tor_addr_make_unspec(&node->ri->ipv4_addr); \
+ node->ri->ipv4_orport = 0; \
}
#define NODE_SET_IPV6(node, ipv6_addr_str, ipv6_port) { \
@@ -1260,9 +1258,7 @@ mock_get_options(void)
#define TEST_ROUTER_VALID_ADDRESS_HELPER(ipv4_addr_str, ipv6_addr_str, rv) \
STMT_BEGIN \
ri = tor_malloc_zero(sizeof(routerinfo_t)); \
- tor_addr_t addr; \
- tor_addr_parse(&addr, (ipv4_addr_str)); \
- ri->addr = tor_addr_to_ipv4h(&addr); \
+ tor_addr_parse(&ri->ipv4_addr, (ipv4_addr_str)); \
tor_addr_parse(&ri->ipv6_addr, (ipv6_addr_str)); \
tt_int_op(dirserv_router_has_valid_address(ri), OP_EQ, (rv)); \
tor_free(ri); \
@@ -1320,7 +1316,7 @@ test_address_dirserv_router_addr_private(void *opt_dir_allow_private)
/* IPv6 null succeeds, because IPv4 is not internal */
{
ri = tor_malloc_zero(sizeof(routerinfo_t));
- ri->addr = 16777217; /* 1.0.0.1 */
+ tor_addr_parse(&ri->ipv4_addr, "1.0.0.1");
tt_int_op(dirserv_router_has_valid_address(ri), OP_EQ, 0);
tor_free(ri);
}
diff --git a/src/test/test_address_set.c b/src/test/test_address_set.c
index c2fe718935..a73fbab76a 100644
--- a/src/test/test_address_set.c
+++ b/src/test/test_address_set.c
@@ -114,7 +114,6 @@ test_nodelist(void *arg)
tor_addr_t addr_v4, addr_v6, dummy_addr;
tor_addr_parse(&addr_v4, "42.42.42.42");
- uint32_t ipv4h = tor_addr_to_ipv4h(&addr_v4);
tor_addr_parse(&addr_v6, "1:2:3:4::");
memset(&dummy_addr, 'A', sizeof(dummy_addr));
@@ -148,9 +147,9 @@ test_nodelist(void *arg)
memcpy(rs->descriptor_digest, md->digest, DIGEST256_LEN);
/* Setup the rs, ri and md addresses. */
- rs->addr = ipv4h;
+ tor_addr_copy(&rs->ipv4_addr, &addr_v4);
tor_addr_parse(&rs->ipv6_addr, "1:2:3:4::");
- ri->addr = ipv4h;
+ tor_addr_copy(&ri->ipv4_addr, &addr_v4);
tor_addr_parse(&ri->ipv6_addr, "1:2:3:4::");
tor_addr_parse(&md->ipv6_addr, "1:2:3:4::");
@@ -228,11 +227,11 @@ test_exit_no_reentry(void *arg)
memcpy(rs->descriptor_digest, md->digest, DIGEST256_LEN);
/* Setup the rs, ri and md addresses. */
- rs->addr = tor_addr_to_ipv4h(&addr_v4);
- rs->or_port = 444;
+ tor_addr_copy(&rs->ipv4_addr, &addr_v4);
+ rs->ipv4_orport = 444;
tor_addr_parse(&rs->ipv6_addr, "1:2:3:4::");
rs->ipv6_orport = 666;
- ri->addr = tor_addr_to_ipv4h(&addr_v4);
+ tor_addr_copy(&ri->ipv4_addr, &addr_v4);
tor_addr_parse(&ri->ipv6_addr, "1:2:3:4::");
tor_addr_parse(&md->ipv6_addr, "1:2:3:4::");
diff --git a/src/test/test_bridges.c b/src/test/test_bridges.c
index f1624a529d..1942a8cb89 100644
--- a/src/test/test_bridges.c
+++ b/src/test/test_bridges.c
@@ -592,8 +592,12 @@ test_bridges_get_transport_by_bridge_addrport(void *arg)
static void
test_bridges_node_is_a_configured_bridge(void *arg)
{
- routerinfo_t ri_ipv4 = { .addr = 0x06060606, .or_port = 6666 };
- routerstatus_t rs_ipv4 = { .addr = 0x06060606, .or_port = 6666 };
+
+ routerinfo_t ri_ipv4 = { .ipv4_orport = 6666 };
+ tor_addr_parse(&ri_ipv4.ipv4_addr, "6.6.6.6");
+
+ routerstatus_t rs_ipv4 = { .ipv4_orport = 6666 };
+ tor_addr_parse(&rs_ipv4.ipv4_addr, "6.6.6.6");
routerinfo_t ri_ipv6 = { .ipv6_orport = 6666 };
tor_addr_parse(&(ri_ipv6.ipv6_addr),
@@ -632,8 +636,8 @@ test_bridges_node_is_a_configured_bridge(void *arg)
/* It won't match bridge1, though, since bridge1 has a digest, and this
isn't it! */
- node_ri_ipv4.ri->addr = 0x06060607;
- node_ri_ipv4.ri->or_port = 6667;
+ tor_addr_parse(&node_ri_ipv4.ri->ipv4_addr, "6.6.6.7");
+ node_ri_ipv4.ri->ipv4_orport = 6667;
tt_assert(! node_is_a_configured_bridge(&node_ri_ipv4));
/* If we set the fingerprint right, though, it will match. */
base16_decode(node_ri_ipv4.identity, DIGEST_LEN,
diff --git a/src/test/test_bwmgt.c b/src/test/test_bwmgt.c
index 117783cafc..4cf83e45d0 100644
--- a/src/test/test_bwmgt.c
+++ b/src/test/test_bwmgt.c
@@ -317,8 +317,8 @@ test_bwmgt_dir_conn_global_write_low(void *arg)
memcpy(rs->descriptor_digest, md->digest, DIGEST256_LEN);
/* Set IP address. */
- rs->addr = tor_addr_to_ipv4h(&relay_addr);
- ri->addr = rs->addr;
+ tor_addr_copy(&rs->ipv4_addr, &relay_addr);
+ tor_addr_copy(&ri->ipv4_addr, &rs->ipv4_addr);
/* Add the rs to the consensus becoming a node_t. */
smartlist_add(dummy_ns->routerstatus_list, rs);
diff --git a/src/test/test_channel.c b/src/test/test_channel.c
index 83b69cc80b..d43f6e010a 100644
--- a/src/test/test_channel.c
+++ b/src/test/test_channel.c
@@ -16,6 +16,10 @@
/* For packed_cell stuff */
#define RELAY_PRIVATE
#include "core/or/relay.h"
+/* For channel_tls_t object and private functions. */
+#define CHANNEL_OBJECT_PRIVATE
+#define CHANNELTLS_PRIVATE
+#include "core/or/channeltls.h"
/* For init/free stuff */
#include "core/or/scheduler.h"
#include "feature/nodelist/networkstatus.h"
@@ -25,6 +29,8 @@
#include "core/or/origin_circuit_st.h"
#include "feature/nodelist/routerstatus_st.h"
#include "core/or/var_cell_st.h"
+#include "core/or/or_connection_st.h"
+#include "lib/net/inaddr.h"
/* Test suite stuff */
#include "test/log_test_helpers.h"
@@ -156,16 +162,23 @@ chan_test_finish_close(channel_t *ch)
}
static const char *
-chan_test_get_remote_descr(channel_t *ch, int flags)
+chan_test_describe_peer(const channel_t *ch)
{
tt_assert(ch);
- tt_int_op(flags & ~(GRD_FLAG_ORIGINAL | GRD_FLAG_ADDR_ONLY), OP_EQ, 0);
done:
return "Fake channel for unit tests; no real endpoint";
}
static int
+chan_test_get_remote_addr(const channel_t *ch, tor_addr_t *out)
+{
+ (void)ch;
+ tor_addr_from_ipv4h(out, 0x7f000001);
+ return 1;
+}
+
+static int
chan_test_num_cells_writeable(channel_t *ch)
{
tt_assert(ch);
@@ -261,7 +274,8 @@ new_fake_channel(void)
chan->close = chan_test_close;
chan->num_cells_writeable = chan_test_num_cells_writeable;
- chan->get_remote_descr = chan_test_get_remote_descr;
+ chan->describe_peer = chan_test_describe_peer;
+ chan->get_remote_addr = chan_test_get_remote_addr;
chan->write_packed_cell = chan_test_write_packed_cell;
chan->write_var_cell = chan_test_write_var_cell;
chan->state = CHANNEL_STATE_OPEN;
@@ -715,7 +729,7 @@ test_channel_inbound_cell(void *arg)
tt_int_op(chan->reason_for_closing, OP_EQ, CHANNEL_CLOSE_REQUESTED);
tt_int_op(test_close_called, OP_EQ, old_count + 1);
- /* This closes the channe so it calls in the scheduler, make sure of it. */
+ /* This closes the channel so it calls in the scheduler, make sure of it. */
old_count = test_releases_count;
chan_test_finish_close(chan);
tt_int_op(test_releases_count, OP_EQ, old_count + 1);
@@ -1368,7 +1382,7 @@ test_channel_for_extend(void *arg)
/* The expected result is chan2 because it is older than chan1. */
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(ret_chan);
tt_ptr_op(ret_chan, OP_EQ, chan2);
tt_int_op(launch, OP_EQ, 0);
@@ -1377,7 +1391,7 @@ test_channel_for_extend(void *arg)
/* Switch that around from previous test. */
chan2->timestamp_created = chan1->timestamp_created + 1;
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(ret_chan);
tt_ptr_op(ret_chan, OP_EQ, chan1);
tt_int_op(launch, OP_EQ, 0);
@@ -1387,7 +1401,7 @@ test_channel_for_extend(void *arg)
* channel 2 should be picked due to how channel_is_better() works. */
chan2->timestamp_created = chan1->timestamp_created;
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(ret_chan);
tt_ptr_op(ret_chan, OP_EQ, chan1);
tt_int_op(launch, OP_EQ, 0);
@@ -1399,7 +1413,7 @@ test_channel_for_extend(void *arg)
/* Condemned the older channel. */
chan1->state = CHANNEL_STATE_CLOSING;
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(ret_chan);
tt_ptr_op(ret_chan, OP_EQ, chan2);
tt_int_op(launch, OP_EQ, 0);
@@ -1409,7 +1423,7 @@ test_channel_for_extend(void *arg)
/* Make the older channel a client one. */
channel_mark_client(chan1);
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(ret_chan);
tt_ptr_op(ret_chan, OP_EQ, chan2);
tt_int_op(launch, OP_EQ, 0);
@@ -1421,7 +1435,7 @@ test_channel_for_extend(void *arg)
memset(&dumb_ed_id, 0, sizeof(dumb_ed_id));
ret_chan = channel_get_for_extend(digest, &dumb_ed_id,
&ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(!ret_chan);
tt_str_op(msg, OP_EQ, "Not connected. Connecting.");
tt_int_op(launch, OP_EQ, 1);
@@ -1431,7 +1445,7 @@ test_channel_for_extend(void *arg)
chan1->state = CHANNEL_STATE_OPENING;
chan2->state = CHANNEL_STATE_OPENING;
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(!ret_chan);
tt_str_op(msg, OP_EQ, "Connection in progress; waiting.");
tt_int_op(launch, OP_EQ, 0);
@@ -1441,7 +1455,7 @@ test_channel_for_extend(void *arg)
/* Mark channel 1 as bad for circuits. */
channel_mark_bad_for_new_circs(chan1);
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(ret_chan);
tt_ptr_op(ret_chan, OP_EQ, chan2);
tt_int_op(launch, OP_EQ, 0);
@@ -1452,7 +1466,7 @@ test_channel_for_extend(void *arg)
channel_mark_bad_for_new_circs(chan1);
channel_mark_bad_for_new_circs(chan2);
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(!ret_chan);
tt_str_op(msg, OP_EQ, "Connections all too old, or too non-canonical. "
" Launching a new one.");
@@ -1464,7 +1478,7 @@ test_channel_for_extend(void *arg)
test_chan_should_be_canonical = 0;
test_chan_should_match_target = 0;
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(!ret_chan);
tt_str_op(msg, OP_EQ, "Connections all too old, or too non-canonical. "
" Launching a new one.");
@@ -1535,6 +1549,54 @@ test_channel_listener(void *arg)
channel_free_all();
}
+#define TEST_SETUP_MATCHES_ADDR(orcon, addr, src, rv) STMT_BEGIN \
+ rv = tor_inet_pton(addr.family, src, &addr.addr); \
+ tt_int_op(rv, OP_EQ, 1); \
+ orcon->base_.addr = addr; \
+ STMT_END;
+
+#define TEST_MATCHES_ADDR(chan, addr4, addr6, rv, exp) STMT_BEGIN \
+ rv = channel_matches_target_addr_for_extend(chan, addr4, addr6); \
+ tt_int_op(rv, OP_EQ, exp); \
+ STMT_END;
+
+static void
+test_channel_matches_target_addr_for_extend(void *arg)
+{
+ (void) arg;
+
+ channel_tls_t *tlschan = tor_malloc_zero(sizeof(*tlschan));
+ or_connection_t *orcon = tor_malloc_zero(sizeof(*orcon));
+ channel_t *chan = &(tlschan->base_);
+ tor_addr_t addr;
+ int rv;
+
+ tlschan->conn = orcon;
+ channel_tls_common_init(tlschan);
+
+ /* Test for IPv4 addresses. */
+ addr.family = AF_INET;
+ TEST_SETUP_MATCHES_ADDR(orcon, addr, "1.2.3.4", rv);
+ TEST_MATCHES_ADDR(chan, &addr, NULL, rv, 1);
+
+ tor_inet_pton(addr.family, "2.5.3.4", &addr.addr);
+ TEST_MATCHES_ADDR(chan, &addr, NULL, rv, 0);
+
+ /* Test for IPv6 addresses. */
+ addr.family = AF_INET6;
+ TEST_SETUP_MATCHES_ADDR(orcon, addr, "3:4:7:1:9:8:09:10", rv);
+ TEST_MATCHES_ADDR(chan, NULL, &addr, rv, 1);
+
+ tor_inet_pton(addr.family, "::", &addr.addr);
+ TEST_MATCHES_ADDR(chan, NULL, &addr, rv, 0);
+
+ done:
+ circuitmux_clear_policy(chan->cmux);
+ circuitmux_free(chan->cmux);
+ tor_free(orcon);
+ tor_free(tlschan);
+}
+
struct testcase_t channel_tests[] = {
{ "inbound_cell", test_channel_inbound_cell, TT_FORK,
NULL, NULL },
@@ -1556,5 +1618,7 @@ struct testcase_t channel_tests[] = {
NULL, NULL },
{ "listener", test_channel_listener, TT_FORK,
NULL, NULL },
+ { "matches_target", test_channel_matches_target_addr_for_extend, TT_FORK,
+ NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_channeltls.c b/src/test/test_channeltls.c
index f4f5cb447e..0227779e8b 100644
--- a/src/test/test_channeltls.c
+++ b/src/test/test_channeltls.c
@@ -38,13 +38,13 @@ static or_connection_t * tlschan_connection_or_connect_mock(
const char *digest,
const ed25519_public_key_t *ed_id,
channel_tls_t *tlschan);
-static int tlschan_is_local_addr_mock(const tor_addr_t *addr);
+static bool tlschan_resolved_addr_is_local_mock(const tor_addr_t *addr);
/* Fake close method */
static void tlschan_fake_close_method(channel_t *chan);
/* Flags controlling behavior of channeltls unit test mocks */
-static int tlschan_local = 0;
+static bool tlschan_local = false;
static const buf_t * tlschan_buf_datalen_mock_target = NULL;
static size_t tlschan_buf_datalen_mock_size = 0;
@@ -67,9 +67,9 @@ test_channeltls_create(void *arg)
test_addr.addr.in_addr.s_addr = htonl(0x01020304);
/* For this test we always want the address to be treated as non-local */
- tlschan_local = 0;
- /* Install is_local_addr() mock */
- MOCK(is_local_addr, tlschan_is_local_addr_mock);
+ tlschan_local = false;
+ /* Install is_local_to_resolve_addr() mock */
+ MOCK(is_local_to_resolve_addr, tlschan_resolved_addr_is_local_mock);
/* Install mock for connection_or_connect() */
MOCK(connection_or_connect, tlschan_connection_or_connect_mock);
@@ -92,7 +92,7 @@ test_channeltls_create(void *arg)
}
UNMOCK(connection_or_connect);
- UNMOCK(is_local_addr);
+ UNMOCK(is_local_to_resolve_addr);
return;
}
@@ -116,9 +116,9 @@ test_channeltls_num_bytes_queued(void *arg)
test_addr.addr.in_addr.s_addr = htonl(0x01020304);
/* For this test we always want the address to be treated as non-local */
- tlschan_local = 0;
- /* Install is_local_addr() mock */
- MOCK(is_local_addr, tlschan_is_local_addr_mock);
+ tlschan_local = false;
+ /* Install is_local_to_resolve_addr() mock */
+ MOCK(is_local_to_resolve_addr, tlschan_resolved_addr_is_local_mock);
/* Install mock for connection_or_connect() */
MOCK(connection_or_connect, tlschan_connection_or_connect_mock);
@@ -178,7 +178,7 @@ test_channeltls_num_bytes_queued(void *arg)
}
UNMOCK(connection_or_connect);
- UNMOCK(is_local_addr);
+ UNMOCK(is_local_to_resolve_addr);
return;
}
@@ -201,9 +201,9 @@ test_channeltls_overhead_estimate(void *arg)
test_addr.addr.in_addr.s_addr = htonl(0x01020304);
/* For this test we always want the address to be treated as non-local */
- tlschan_local = 0;
- /* Install is_local_addr() mock */
- MOCK(is_local_addr, tlschan_is_local_addr_mock);
+ tlschan_local = false;
+ /* Install is_local_to_resolve_addr() mock */
+ MOCK(is_local_to_resolve_addr, tlschan_resolved_addr_is_local_mock);
/* Install mock for connection_or_connect() */
MOCK(connection_or_connect, tlschan_connection_or_connect_mock);
@@ -252,7 +252,7 @@ test_channeltls_overhead_estimate(void *arg)
}
UNMOCK(connection_or_connect);
- UNMOCK(is_local_addr);
+ UNMOCK(is_local_to_resolve_addr);
return;
}
@@ -293,7 +293,7 @@ tlschan_connection_or_connect_mock(const tor_addr_t *addr,
result->base_.port = port;
memcpy(result->identity_digest, digest, DIGEST_LEN);
result->chan = tlschan;
- memcpy(&(result->real_addr), addr, sizeof(tor_addr_t));
+ memcpy(&result->base_.addr, addr, sizeof(tor_addr_t));
result->tls = (tor_tls_t *)((void *)(&fake_tortls));
done:
@@ -321,8 +321,8 @@ tlschan_fake_close_method(channel_t *chan)
return;
}
-static int
-tlschan_is_local_addr_mock(const tor_addr_t *addr)
+static bool
+tlschan_resolved_addr_is_local_mock(const tor_addr_t *addr)
{
tt_ptr_op(addr, OP_NE, NULL);
diff --git a/src/test/test_circuitbuild.c b/src/test/test_circuitbuild.c
index 03fd176ead..299908ce82 100644
--- a/src/test/test_circuitbuild.c
+++ b/src/test/test_circuitbuild.c
@@ -19,6 +19,7 @@
#include "core/or/channel.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
#include "core/or/onion.h"
#include "core/or/cell_st.h"
@@ -29,11 +30,13 @@
#include "feature/client/entrynodes.h"
#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/node_select.h"
#include "feature/relay/circuitbuild_relay.h"
#include "feature/relay/router.h"
#include "feature/relay/routermode.h"
#include "feature/nodelist/node_st.h"
+#include "feature/nodelist/routerinfo_st.h"
/* Dummy nodes smartlist for testing */
static smartlist_t dummy_nodes;
@@ -279,10 +282,10 @@ mock_node_get_by_id(const char *identity_digest)
return mocked_node;
}
-static int mocked_supports_ed25519_link_authentication = 0;
-static int
+static bool mocked_supports_ed25519_link_authentication = 0;
+static bool
mock_node_supports_ed25519_link_authentication(const node_t *node,
- int compatible_with_us)
+ bool compatible_with_us)
{
(void)node;
(void)compatible_with_us;
@@ -821,6 +824,75 @@ test_circuit_extend_lspec_valid(void *arg)
tor_free(p_chan);
}
+#define NODE_SET_IPV4(node, ipv4_addr_str, ipv4_port) { \
+ tor_addr_parse(&node->ri->ipv4_addr, ipv4_addr_str); \
+ node->ri->ipv4_orport = ipv4_port; \
+ }
+
+#define NODE_CLEAR_IPV4(node) { \
+ tor_addr_make_unspec(&node->ri->ipv4_addr); \
+ node->ri->ipv4_orport = 0; \
+ }
+
+#define NODE_SET_IPV6(node, ipv6_addr_str, ipv6_port) { \
+ tor_addr_parse(&node->ri->ipv6_addr, ipv6_addr_str); \
+ node->ri->ipv6_orport = ipv6_port; \
+ }
+
+/* Test the different cases in circuit_extend_add_ed25519_helper(). */
+static void
+test_circuit_extend_add_ip(void *arg)
+{
+ (void) arg;
+ tor_addr_t ipv4_tmp;
+ extend_cell_t *ec = tor_malloc_zero(sizeof(extend_cell_t));
+ extend_cell_t *old_ec = tor_malloc_zero(sizeof(extend_cell_t));
+
+ node_t *fake_node = tor_malloc_zero(sizeof(node_t));
+ routerinfo_t *ri = tor_malloc_zero(sizeof(routerinfo_t));
+
+ MOCK(node_get_by_id, mock_node_get_by_id);
+
+ /* Set up the fake variables for the IPv4 test */
+ fake_node->ri = ri;
+ mocked_node = fake_node;
+ memset(ec->node_id, 0xAA, sizeof(ec->node_id));
+ memcpy(old_ec, ec, sizeof(extend_cell_t));
+ NODE_SET_IPV4(fake_node, PUBLIC_IPV4, VALID_PORT);
+
+ /* Do the IPv4 test */
+ tt_int_op(circuit_extend_add_ipv4_helper(ec), OP_EQ, 0);
+ tor_addr_copy(&ipv4_tmp, &fake_node->ri->ipv4_addr);
+ /* The IPv4 should match */
+ tt_int_op(tor_addr_compare(&ec->orport_ipv4.addr, &ipv4_tmp, CMP_SEMANTIC),
+ OP_EQ, 0);
+ tt_int_op(ec->orport_ipv4.port, OP_EQ, VALID_PORT);
+
+ /* Set up the fake variables for the IPv6 test */
+ memcpy(ec, old_ec, sizeof(extend_cell_t));
+ NODE_CLEAR_IPV4(fake_node);
+ NODE_SET_IPV6(fake_node, PUBLIC_IPV6, VALID_PORT);
+
+ /* Do the IPv6 test */
+ tt_int_op(circuit_extend_add_ipv6_helper(ec), OP_EQ, 0);
+ /* The IPv6 should match */
+ tt_int_op(tor_addr_compare(&ec->orport_ipv6.addr, &fake_node->ri->ipv6_addr,
+ CMP_SEMANTIC), OP_EQ, 0);
+ tt_int_op(ec->orport_ipv6.port, OP_EQ, VALID_PORT);
+
+ /* Cleanup */
+ mocked_node = NULL;
+
+ done:
+ UNMOCK(node_get_by_id);
+
+ tor_free(ec);
+ tor_free(old_ec);
+
+ tor_free(ri);
+ tor_free(fake_node);
+}
+
static bool can_extend_over_ipv6_result = false;
static int mock_router_can_extend_over_ipv6_calls = 0;
static bool
@@ -927,15 +999,9 @@ mock_circuit_mark_for_close_(circuit_t *circ, int reason,
static int mock_channel_connect_calls = 0;
static channel_t *mock_channel_connect_nchan = NULL;
static channel_t *
-mock_channel_connect_for_circuit(const tor_addr_t *addr,
- uint16_t port,
- const char *id_digest,
- const struct ed25519_public_key_t *ed_id)
+mock_channel_connect_for_circuit(const extend_info_t *ei)
{
- (void)addr;
- (void)port;
- (void)id_digest;
- (void)ed_id;
+ (void)ei;
mock_channel_connect_calls++;
return mock_channel_connect_nchan;
}
@@ -1148,6 +1214,7 @@ mock_channel_get_for_extend(const char *rsa_id_digest,
const ed25519_public_key_t *ed_id,
const tor_addr_t *target_ipv4_addr,
const tor_addr_t *target_ipv6_addr,
+ bool for_origin_circ,
const char **msg_out,
int *launch_out)
{
@@ -1155,6 +1222,7 @@ mock_channel_get_for_extend(const char *rsa_id_digest,
(void)ed_id;
(void)target_ipv4_addr;
(void)target_ipv6_addr;
+ (void)for_origin_circ;
/* channel_get_for_extend() requires non-NULL arguments */
tt_ptr_op(msg_out, OP_NE, NULL);
@@ -1176,6 +1244,8 @@ mock_channel_get_canonical_remote_descr(channel_t *chan)
return "mock_channel_get_canonical_remote_descr()";
}
+/* Should mock_circuit_deliver_create_cell() expect a direct connection? */
+static bool mock_circuit_deliver_create_cell_expect_direct = false;
static int mock_circuit_deliver_create_cell_calls = 0;
static int mock_circuit_deliver_create_cell_result = 0;
static int
@@ -1188,10 +1258,13 @@ mock_circuit_deliver_create_cell(circuit_t *circ,
/* circuit_deliver_create_cell() requires non-NULL arguments,
* but we only check circ and circ->n_chan here. */
tt_ptr_op(circ, OP_NE, NULL);
- tt_ptr_op(circ->n_chan, OP_NE, NULL);
+ /* We expect n_chan for relayed cells. But should we also expect it for
+ * direct connections? */
+ if (!mock_circuit_deliver_create_cell_expect_direct)
+ tt_ptr_op(circ->n_chan, OP_NE, NULL);
/* We should only ever get relayed cells from extends */
- tt_int_op(relayed, OP_EQ, 1);
+ tt_int_op(relayed, OP_EQ, !mock_circuit_deliver_create_cell_expect_direct);
mock_circuit_deliver_create_cell_calls++;
return mock_circuit_deliver_create_cell_result;
@@ -1215,7 +1288,7 @@ test_circuit_extend(void *arg)
MOCK(server_mode, mock_server_mode);
/* Mock a debug function, but otherwise ignore it */
- MOCK(channel_get_canonical_remote_descr,
+ MOCK(channel_describe_peer,
mock_channel_get_canonical_remote_descr);
setup_full_capture_of_logs(LOG_INFO);
@@ -1352,6 +1425,7 @@ test_circuit_extend(void *arg)
/* Mock circuit_deliver_create_cell(), so it doesn't crash */
mock_circuit_deliver_create_cell_calls = 0;
+ mock_circuit_deliver_create_cell_expect_direct = false;
MOCK(circuit_deliver_create_cell, mock_circuit_deliver_create_cell);
/* Test circuit established, re-using channel, successful delivery */
@@ -1407,7 +1481,7 @@ test_circuit_extend(void *arg)
UNMOCK(server_mode);
server = 0;
- UNMOCK(channel_get_canonical_remote_descr);
+ UNMOCK(channel_describe_peer);
UNMOCK(extend_cell_parse);
memset(&mock_extend_cell_parse_cell_out, 0,
@@ -1516,6 +1590,355 @@ test_onionskin_answer(void *arg)
tor_free(or_circ);
}
+/* Test the different cases in origin_circuit_init(). */
+static void
+test_origin_circuit_init(void *arg)
+{
+ (void)arg;
+ origin_circuit_t *origin_circ = NULL;
+
+ /* Init with 0 purpose and 0 flags */
+ origin_circ = origin_circuit_init(0, 0);
+ tt_int_op(origin_circ->base_.purpose, OP_EQ, 0);
+ tt_int_op(origin_circ->base_.state, OP_EQ, CIRCUIT_STATE_CHAN_WAIT);
+ tt_ptr_op(origin_circ->build_state, OP_NE, NULL);
+ tt_int_op(origin_circ->build_state->is_internal, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->is_ipv6_selftest, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->need_capacity, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->need_uptime, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->onehop_tunnel, OP_EQ, 0);
+ /* The circuits are automatically freed by the circuitlist. */
+
+ /* Init with a purpose */
+ origin_circ = origin_circuit_init(CIRCUIT_PURPOSE_C_GENERAL, 0);
+ tt_int_op(origin_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_C_GENERAL);
+
+ /* Init with each flag */
+ origin_circ = origin_circuit_init(0, CIRCLAUNCH_IS_INTERNAL);
+ tt_ptr_op(origin_circ->build_state, OP_NE, NULL);
+ tt_int_op(origin_circ->build_state->is_internal, OP_EQ, 1);
+ tt_int_op(origin_circ->build_state->is_ipv6_selftest, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->need_capacity, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->need_uptime, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->onehop_tunnel, OP_EQ, 0);
+
+ origin_circ = origin_circuit_init(0, CIRCLAUNCH_IS_IPV6_SELFTEST);
+ tt_ptr_op(origin_circ->build_state, OP_NE, NULL);
+ tt_int_op(origin_circ->build_state->is_internal, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->is_ipv6_selftest, OP_EQ, 1);
+ tt_int_op(origin_circ->build_state->need_capacity, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->need_uptime, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->onehop_tunnel, OP_EQ, 0);
+
+ origin_circ = origin_circuit_init(0, CIRCLAUNCH_NEED_CAPACITY);
+ tt_ptr_op(origin_circ->build_state, OP_NE, NULL);
+ tt_int_op(origin_circ->build_state->is_internal, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->is_ipv6_selftest, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->need_capacity, OP_EQ, 1);
+ tt_int_op(origin_circ->build_state->need_uptime, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->onehop_tunnel, OP_EQ, 0);
+
+ origin_circ = origin_circuit_init(0, CIRCLAUNCH_NEED_UPTIME);
+ tt_ptr_op(origin_circ->build_state, OP_NE, NULL);
+ tt_int_op(origin_circ->build_state->is_internal, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->is_ipv6_selftest, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->need_capacity, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->need_uptime, OP_EQ, 1);
+ tt_int_op(origin_circ->build_state->onehop_tunnel, OP_EQ, 0);
+
+ origin_circ = origin_circuit_init(0, CIRCLAUNCH_ONEHOP_TUNNEL);
+ tt_ptr_op(origin_circ->build_state, OP_NE, NULL);
+ tt_int_op(origin_circ->build_state->is_internal, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->is_ipv6_selftest, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->need_capacity, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->need_uptime, OP_EQ, 0);
+ tt_int_op(origin_circ->build_state->onehop_tunnel, OP_EQ, 1);
+
+ done:
+ /* The circuits are automatically freed by the circuitlist. */
+ ;
+}
+
+/* Test the different cases in circuit_send_next_onion_skin(). */
+static void
+test_circuit_send_next_onion_skin(void *arg)
+{
+ (void)arg;
+ origin_circuit_t *origin_circ = NULL;
+ struct timeval circ_start_time;
+ memset(&circ_start_time, 0, sizeof(circ_start_time));
+
+ extend_info_t fakehop;
+ memset(&fakehop, 0, sizeof(fakehop));
+ extend_info_t *single_fakehop = &fakehop;
+ extend_info_t *multi_fakehop[DEFAULT_ROUTE_LEN] = {&fakehop,
+ &fakehop,
+ &fakehop};
+
+ extend_info_t ipv6_hop;
+ memset(&ipv6_hop, 0, sizeof(ipv6_hop));
+ tor_addr_parse(&ipv6_hop.orports[0].addr, "1::2");
+ extend_info_t *multi_ipv6_hop[DEFAULT_ROUTE_LEN] = {&ipv6_hop,
+ &ipv6_hop,
+ &ipv6_hop};
+
+ extend_info_t ipv4_hop;
+ memset(&ipv4_hop, 0, sizeof(ipv4_hop));
+ tor_addr_from_ipv4h(&ipv4_hop.orports[0].addr, 0x20304050);
+ extend_info_t *multi_ipv4_hop[DEFAULT_ROUTE_LEN] = {&ipv4_hop,
+ &ipv4_hop,
+ &ipv4_hop};
+
+ mock_circuit_deliver_create_cell_expect_direct = false;
+ MOCK(circuit_deliver_create_cell, mock_circuit_deliver_create_cell);
+ server = 0;
+ MOCK(server_mode, mock_server_mode);
+
+ /* Try a direct connection, and succeed on a client */
+ server = 0;
+ origin_circ = new_test_origin_circuit(false,
+ circ_start_time,
+ 1,
+ &single_fakehop);
+ tt_ptr_op(origin_circ, OP_NE, NULL);
+ /* Skip some of the multi-hop checks */
+ origin_circ->build_state->onehop_tunnel = 1;
+ /* This is a direct connection */
+ mock_circuit_deliver_create_cell_expect_direct = true;
+ tt_int_op(circuit_send_next_onion_skin(origin_circ), OP_EQ, 0);
+ /* The circuits are automatically freed by the circuitlist. */
+
+ /* Try a direct connection, and succeed on a server */
+ server = 1;
+ origin_circ = new_test_origin_circuit(false,
+ circ_start_time,
+ 1,
+ &single_fakehop);
+ tt_ptr_op(origin_circ, OP_NE, NULL);
+ origin_circ->build_state->onehop_tunnel = 1;
+ mock_circuit_deliver_create_cell_expect_direct = true;
+ tt_int_op(circuit_send_next_onion_skin(origin_circ), OP_EQ, 0);
+
+ /* Start capturing bugs */
+ setup_full_capture_of_logs(LOG_WARN);
+ tor_capture_bugs_(1);
+
+ /* Try an extend, but fail the client valid address family check */
+ server = 0;
+ origin_circ = new_test_origin_circuit(true,
+ circ_start_time,
+ ARRAY_LENGTH(multi_fakehop),
+ multi_fakehop);
+ tt_ptr_op(origin_circ, OP_NE, NULL);
+ /* Fix the state */
+ origin_circ->base_.state = 0;
+ /* This is an indirect connection */
+ mock_circuit_deliver_create_cell_expect_direct = false;
+ /* Fail because the address family is invalid */
+ tt_int_op(circuit_send_next_onion_skin(origin_circ), OP_EQ,
+ -END_CIRC_REASON_INTERNAL);
+ expect_log_msg("No supported address family found in extend_info.\n");
+ mock_clean_saved_logs();
+
+ /* Try an extend, but fail the server valid address check */
+ server = 1;
+ origin_circ = new_test_origin_circuit(true,
+ circ_start_time,
+ ARRAY_LENGTH(multi_fakehop),
+ multi_fakehop);
+ tt_ptr_op(origin_circ, OP_NE, NULL);
+ origin_circ->base_.state = 0;
+ mock_circuit_deliver_create_cell_expect_direct = false;
+ tt_int_op(circuit_send_next_onion_skin(origin_circ), OP_EQ,
+ -END_CIRC_REASON_INTERNAL);
+ expect_log_msg("No supported address family found in extend_info.\n");
+ mock_clean_saved_logs();
+
+ /* Try an extend, but fail in the client code, with an IPv6 address */
+ server = 0;
+ origin_circ = new_test_origin_circuit(true,
+ circ_start_time,
+ ARRAY_LENGTH(multi_ipv6_hop),
+ multi_ipv6_hop);
+ tt_ptr_op(origin_circ, OP_NE, NULL);
+ origin_circ->base_.state = 0;
+ mock_circuit_deliver_create_cell_expect_direct = false;
+ tt_int_op(circuit_send_next_onion_skin(origin_circ), OP_EQ,
+ -END_CIRC_REASON_INTERNAL);
+ expect_log_msg("No supported address family found in extend_info.\n");
+ mock_clean_saved_logs();
+
+ /* Stop capturing bugs, but keep capturing logs */
+ tor_end_capture_bugs_();
+
+ /* Try an extend, pass the client IPv4 check, but fail later */
+ server = 0;
+ origin_circ = new_test_origin_circuit(true,
+ circ_start_time,
+ ARRAY_LENGTH(multi_ipv4_hop),
+ multi_ipv4_hop);
+ tt_ptr_op(origin_circ, OP_NE, NULL);
+ origin_circ->base_.state = 0;
+ mock_circuit_deliver_create_cell_expect_direct = false;
+ /* Fail because the circuit data is invalid */
+ tt_int_op(circuit_send_next_onion_skin(origin_circ), OP_EQ,
+ -END_CIRC_REASON_INTERNAL);
+ expect_log_msg("onion_skin_create failed.\n");
+ mock_clean_saved_logs();
+
+ /* Try an extend, pass the server IPv4 check, but fail later */
+ server = 1;
+ origin_circ = new_test_origin_circuit(true,
+ circ_start_time,
+ ARRAY_LENGTH(multi_ipv4_hop),
+ multi_ipv4_hop);
+ tt_ptr_op(origin_circ, OP_NE, NULL);
+ origin_circ->base_.state = 0;
+ mock_circuit_deliver_create_cell_expect_direct = false;
+ tt_int_op(circuit_send_next_onion_skin(origin_circ), OP_EQ,
+ -END_CIRC_REASON_INTERNAL);
+ expect_log_msg("onion_skin_create failed.\n");
+ mock_clean_saved_logs();
+
+ /* Try an extend, pass the server IPv6 check, but fail later */
+ server = 1;
+ origin_circ = new_test_origin_circuit(true,
+ circ_start_time,
+ ARRAY_LENGTH(multi_ipv6_hop),
+ multi_ipv6_hop);
+ tt_ptr_op(origin_circ, OP_NE, NULL);
+ origin_circ->base_.state = 0;
+ mock_circuit_deliver_create_cell_expect_direct = false;
+ tt_int_op(circuit_send_next_onion_skin(origin_circ), OP_EQ,
+ -END_CIRC_REASON_INTERNAL);
+ expect_log_msg("onion_skin_create failed.\n");
+ mock_clean_saved_logs();
+
+ /* Things we're not testing right now:
+ * - the addresses in the extend cell inside
+ * circuit_send_intermediate_onion_skin() matches the address in the
+ * supplied extend_info.
+ * - valid circuit data.
+ * - actually extending the circuit to each hop. */
+
+ done:
+ tor_end_capture_bugs_();
+ mock_clean_saved_logs();
+ teardown_capture_of_logs();
+
+ UNMOCK(circuit_deliver_create_cell);
+ UNMOCK(server_mode);
+ server = 0;
+
+ /* The circuits are automatically freed by the circuitlist. */
+}
+
+/* Test the different cases in cpath_build_state_to_crn_flags(). */
+static void
+test_cpath_build_state_to_crn_flags(void *arg)
+{
+ (void)arg;
+
+ cpath_build_state_t state;
+ memset(&state, 0, sizeof(state));
+
+ tt_int_op(cpath_build_state_to_crn_flags(&state), OP_EQ,
+ 0);
+
+ memset(&state, 0, sizeof(state));
+ state.need_uptime = 1;
+ tt_int_op(cpath_build_state_to_crn_flags(&state), OP_EQ,
+ CRN_NEED_UPTIME);
+
+ memset(&state, 0, sizeof(state));
+ state.need_capacity = 1;
+ tt_int_op(cpath_build_state_to_crn_flags(&state), OP_EQ,
+ CRN_NEED_CAPACITY);
+
+ memset(&state, 0, sizeof(state));
+ state.need_capacity = 1;
+ state.need_uptime = 1;
+ tt_int_op(cpath_build_state_to_crn_flags(&state), OP_EQ,
+ CRN_NEED_CAPACITY | CRN_NEED_UPTIME);
+
+ /* Check that no other flags are handled */
+ memset(&state, 0xff, sizeof(state));
+ tt_int_op(cpath_build_state_to_crn_flags(&state), OP_EQ,
+ CRN_NEED_CAPACITY | CRN_NEED_UPTIME);
+
+ done:
+ ;
+}
+
+/* Test the different cases in cpath_build_state_to_crn_ipv6_extend_flag(). */
+static void
+test_cpath_build_state_to_crn_ipv6_extend_flag(void *arg)
+{
+ (void)arg;
+
+ cpath_build_state_t state;
+
+ memset(&state, 0, sizeof(state));
+ state.desired_path_len = DEFAULT_ROUTE_LEN;
+ tt_int_op(cpath_build_state_to_crn_ipv6_extend_flag(&state, 0), OP_EQ,
+ 0);
+
+ /* Pass the state flag check, but not the length check */
+ memset(&state, 0, sizeof(state));
+ state.desired_path_len = DEFAULT_ROUTE_LEN;
+ state.is_ipv6_selftest = 1;
+ tt_int_op(cpath_build_state_to_crn_ipv6_extend_flag(&state, 0), OP_EQ,
+ 0);
+
+ /* Pass the length check, but not the state flag check */
+ memset(&state, 0, sizeof(state));
+ state.desired_path_len = DEFAULT_ROUTE_LEN;
+ tt_int_op(
+ cpath_build_state_to_crn_ipv6_extend_flag(&state,
+ DEFAULT_ROUTE_LEN - 2),
+ OP_EQ, 0);
+
+ /* Pass both checks */
+ memset(&state, 0, sizeof(state));
+ state.desired_path_len = DEFAULT_ROUTE_LEN;
+ state.is_ipv6_selftest = 1;
+ tt_int_op(
+ cpath_build_state_to_crn_ipv6_extend_flag(&state,
+ DEFAULT_ROUTE_LEN - 2),
+ OP_EQ, CRN_INITIATE_IPV6_EXTEND);
+
+ /* Check that no other flags are handled */
+ memset(&state, 0xff, sizeof(state));
+ state.desired_path_len = INT_MAX;
+ tt_int_op(cpath_build_state_to_crn_ipv6_extend_flag(&state, INT_MAX), OP_EQ,
+ 0);
+
+#ifndef ALL_BUGS_ARE_FATAL
+ /* Start capturing bugs */
+ setup_full_capture_of_logs(LOG_INFO);
+ tor_capture_bugs_(1);
+
+ /* Now test the single hop circuit case */
+#define SINGLE_HOP_ROUTE_LEN 1
+ memset(&state, 0, sizeof(state));
+ state.desired_path_len = SINGLE_HOP_ROUTE_LEN;
+ state.is_ipv6_selftest = 1;
+ tt_int_op(
+ cpath_build_state_to_crn_ipv6_extend_flag(&state,
+ SINGLE_HOP_ROUTE_LEN - 2),
+ OP_EQ, 0);
+ tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
+ tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
+ "!(ASSERT_PREDICT_UNLIKELY_(state->desired_path_len < 2))");
+ mock_clean_saved_logs();
+#endif /* !defined(ALL_BUGS_ARE_FATAL) */
+
+ done:
+ tor_end_capture_bugs_();
+ mock_clean_saved_logs();
+ teardown_capture_of_logs();
+}
+
#define TEST(name, flags, setup, cleanup) \
{ #name, test_ ## name, flags, setup, cleanup }
@@ -1525,6 +1948,9 @@ test_onionskin_answer(void *arg)
#define TEST_CIRCUIT(name, flags) \
{ #name, test_circuit_ ## name, flags, NULL, NULL }
+#define TEST_CPATH(name, flags) \
+ { #name, test_cpath_ ## name, flags, NULL, NULL }
+
#ifndef COCCI
#define TEST_CIRCUIT_PASSTHROUGH(name, flags, arg) \
{ #name "/" arg, test_circuit_ ## name, flags, \
@@ -1542,13 +1968,21 @@ struct testcase_t circuitbuild_tests[] = {
TEST_CIRCUIT(extend_state_valid, TT_FORK),
TEST_CIRCUIT(extend_add_ed25519, TT_FORK),
TEST_CIRCUIT(extend_lspec_valid, TT_FORK),
+ TEST_CIRCUIT(extend_add_ip, TT_FORK),
TEST_CIRCUIT(choose_ip_ap_for_extend, 0),
+
TEST_CIRCUIT_PASSTHROUGH(open_connection_for_extend, TT_FORK, "4"),
TEST_CIRCUIT_PASSTHROUGH(open_connection_for_extend, TT_FORK, "6"),
TEST_CIRCUIT_PASSTHROUGH(open_connection_for_extend, TT_FORK, "dual-stack"),
+
TEST_CIRCUIT(extend, TT_FORK),
TEST(onionskin_answer, TT_FORK, NULL, NULL),
+ TEST(origin_circuit_init, TT_FORK, NULL, NULL),
+ TEST_CIRCUIT(send_next_onion_skin, TT_FORK),
+ TEST_CPATH(build_state_to_crn_flags, 0),
+ TEST_CPATH(build_state_to_crn_ipv6_extend_flag, TT_FORK),
+
END_OF_TESTCASES
};
diff --git a/src/test/test_circuitmux.c b/src/test/test_circuitmux.c
index 2c11d107d0..d6e3300a30 100644
--- a/src/test/test_circuitmux.c
+++ b/src/test/test_circuitmux.c
@@ -191,7 +191,7 @@ test_cmux_attach_circuit(void *arg)
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
+ /* Query the chanid<->circid map in the cmux subsystem 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);
diff --git a/src/test/test_circuitpadding.c b/src/test/test_circuitpadding.c
index cfb24c032c..86baf54f40 100644
--- a/src/test/test_circuitpadding.c
+++ b/src/test/test_circuitpadding.c
@@ -23,6 +23,7 @@
#include "core/or/circuitbuild.h"
#include "core/or/circuitpadding.h"
#include "core/or/circuitpadding_machines.h"
+#include "core/or/extendinfo.h"
#include "core/mainloop/netstatus.h"
#include "core/crypto/relay_crypto.h"
#include "core/or/protover.h"
@@ -1361,7 +1362,7 @@ test_circuitpadding_wronghop(void *arg)
/* 5. Test that asking to stop the wrong machine does nothing */
circpad_negotiate_padding(TO_ORIGIN_CIRCUIT(client_side),
- 255, 2, CIRCPAD_COMMAND_STOP);
+ 255, 2, CIRCPAD_COMMAND_STOP, 0);
tt_ptr_op(client_side->padding_machine[0], OP_NE, NULL);
tt_ptr_op(client_side->padding_info[0], OP_NE, NULL);
tt_ptr_op(relay_side->padding_machine[0], OP_NE, NULL);
@@ -1373,7 +1374,7 @@ test_circuitpadding_wronghop(void *arg)
ret = circpad_handle_padding_negotiated(relay_side, &cell, NULL);
tt_int_op(ret, OP_EQ, -1);
- /* 7. Test garbled negotated cell (bad command 255) */
+ /* 7. Test garbled negotiated cell (bad command 255) */
memset(&cell, 0, sizeof(cell));
ret = circpad_handle_padding_negotiate(relay_side, &cell);
tt_int_op(ret, OP_EQ, -1);
@@ -1409,7 +1410,7 @@ test_circuitpadding_wronghop(void *arg)
circpad_padding_negotiated(relay_side,
CIRCPAD_MACHINE_CIRC_SETUP,
CIRCPAD_COMMAND_START,
- CIRCPAD_RESPONSE_OK);
+ CIRCPAD_RESPONSE_OK, 0);
/* verify no padding was negotiated */
tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
@@ -1418,7 +1419,7 @@ test_circuitpadding_wronghop(void *arg)
circpad_padding_negotiated(relay_side,
CIRCPAD_MACHINE_CIRC_SETUP,
CIRCPAD_COMMAND_START,
- CIRCPAD_RESPONSE_ERR);
+ CIRCPAD_RESPONSE_ERR, 0);
/* verify no padding was negotiated */
tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
@@ -1521,7 +1522,7 @@ test_circuitpadding_negotiation(void *arg)
/* Force negotiate padding. */
circpad_negotiate_padding(TO_ORIGIN_CIRCUIT(client_side),
CIRCPAD_MACHINE_CIRC_SETUP,
- 2, CIRCPAD_COMMAND_START);
+ 2, CIRCPAD_COMMAND_START, 0);
/* verify no padding was negotiated */
tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
@@ -1732,9 +1733,9 @@ helper_create_conditional_machines(void)
add->conditions.requires_vanguards = 0;
add->conditions.min_hops = 2;
- add->conditions.state_mask = CIRCPAD_CIRC_BUILDING|
+ add->conditions.apply_state_mask = CIRCPAD_CIRC_BUILDING|
CIRCPAD_CIRC_NO_STREAMS|CIRCPAD_CIRC_HAS_RELAY_EARLY;
- add->conditions.purpose_mask = CIRCPAD_PURPOSE_ALL;
+ add->conditions.apply_purpose_mask = CIRCPAD_PURPOSE_ALL;
circpad_register_padding_machine(add, origin_padding_machines);
add = helper_create_conditional_machine();
@@ -1751,9 +1752,9 @@ helper_create_conditional_machines(void)
add->conditions.requires_vanguards = 1;
add->conditions.min_hops = 3;
- add->conditions.state_mask = CIRCPAD_CIRC_OPENED|
+ add->conditions.apply_state_mask = CIRCPAD_CIRC_OPENED|
CIRCPAD_CIRC_STREAMS|CIRCPAD_CIRC_HAS_NO_RELAY_EARLY;
- add->conditions.purpose_mask = CIRCPAD_PURPOSE_ALL;
+ add->conditions.apply_purpose_mask = CIRCPAD_PURPOSE_ALL;
circpad_register_padding_machine(add, origin_padding_machines);
add = helper_create_conditional_machine();
@@ -2337,7 +2338,7 @@ helper_circpad_circ_distribution_machine_setup(int min, int max)
}
/** Simple test that the padding delays sampled from a uniform distribution
- * actually faill within the uniform distribution range. */
+ * actually fail within the uniform distribution range. */
static void
test_circuitpadding_sample_distribution(void *arg)
{
@@ -2727,8 +2728,8 @@ helper_create_ender_machine(void)
circ_client_machine.states[CIRCPAD_STATE_START].
next_state[CIRCPAD_EVENT_NONPADDING_RECV] = CIRCPAD_STATE_END;
- circ_client_machine.conditions.state_mask = CIRCPAD_STATE_ALL;
- circ_client_machine.conditions.purpose_mask = CIRCPAD_PURPOSE_ALL;
+ circ_client_machine.conditions.apply_state_mask = CIRCPAD_STATE_ALL;
+ circ_client_machine.conditions.apply_purpose_mask = CIRCPAD_PURPOSE_ALL;
}
static time_t mocked_timeofday;
@@ -3031,7 +3032,7 @@ test_circuitpadding_hs_machines(void *arg)
/* Test logic:
*
- * 1) Register the HS machines, which aim to hide the presense of
+ * 1) Register the HS machines, which aim to hide the presence of
* onion service traffic on the client-side
*
* 2) Call helper_test_hs_machines() to perform tests for the intro circuit
diff --git a/src/test/test_circuitstats.c b/src/test/test_circuitstats.c
index e15dec5a01..00ca1b544c 100644
--- a/src/test/test_circuitstats.c
+++ b/src/test/test_circuitstats.c
@@ -17,18 +17,13 @@
#include "core/or/circuituse.h"
#include "core/or/channel.h"
-#include "core/or/cpath_build_state_st.h"
#include "core/or/crypt_path_st.h"
#include "core/or/extend_info_st.h"
#include "core/or/origin_circuit_st.h"
-void test_circuitstats_timeout(void *arg);
-void test_circuitstats_hoplen(void *arg);
-origin_circuit_t *subtest_fourhop_circuit(struct timeval, int);
-origin_circuit_t *add_opened_threehop(void);
-origin_circuit_t *build_unopened_fourhop(struct timeval);
-
-int cpath_append_hop(crypt_path_t **head_ptr, extend_info_t *choice);
+static origin_circuit_t *add_opened_threehop(void);
+static origin_circuit_t *build_unopened_fourhop(struct timeval);
+static origin_circuit_t *subtest_fourhop_circuit(struct timeval, int);
static int marked_for_close;
/* Mock function because we are not trying to test the close circuit that does
@@ -45,85 +40,71 @@ mock_circuit_mark_for_close(circuit_t *circ, int reason, int line,
return;
}
-origin_circuit_t *
+static origin_circuit_t *
add_opened_threehop(void)
{
- origin_circuit_t *or_circ = origin_circuit_new();
+ struct timeval circ_start_time;
+ memset(&circ_start_time, 0, sizeof(circ_start_time));
extend_info_t fakehop;
memset(&fakehop, 0, sizeof(fakehop));
-
- TO_CIRCUIT(or_circ)->purpose = CIRCUIT_PURPOSE_C_GENERAL;
-
- or_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
- or_circ->build_state->desired_path_len = DEFAULT_ROUTE_LEN;
-
- cpath_append_hop(&or_circ->cpath, &fakehop);
- cpath_append_hop(&or_circ->cpath, &fakehop);
- cpath_append_hop(&or_circ->cpath, &fakehop);
-
- or_circ->has_opened = 1;
- TO_CIRCUIT(or_circ)->state = CIRCUIT_STATE_OPEN;
- TO_CIRCUIT(or_circ)->purpose = CIRCUIT_PURPOSE_C_GENERAL;
-
- return or_circ;
+ extend_info_t *fakehop_list[DEFAULT_ROUTE_LEN] = {&fakehop,
+ &fakehop,
+ &fakehop};
+
+ return new_test_origin_circuit(true,
+ circ_start_time,
+ DEFAULT_ROUTE_LEN,
+ fakehop_list);
}
-origin_circuit_t *
+static origin_circuit_t *
build_unopened_fourhop(struct timeval circ_start_time)
{
- origin_circuit_t *or_circ = origin_circuit_new();
- extend_info_t *fakehop = tor_malloc_zero(sizeof(extend_info_t));
- memset(fakehop, 0, sizeof(extend_info_t));
-
- TO_CIRCUIT(or_circ)->purpose = CIRCUIT_PURPOSE_C_GENERAL;
- TO_CIRCUIT(or_circ)->timestamp_began = circ_start_time;
- TO_CIRCUIT(or_circ)->timestamp_created = circ_start_time;
-
- or_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
- or_circ->build_state->desired_path_len = 4;
-
- cpath_append_hop(&or_circ->cpath, fakehop);
- cpath_append_hop(&or_circ->cpath, fakehop);
- cpath_append_hop(&or_circ->cpath, fakehop);
- cpath_append_hop(&or_circ->cpath, fakehop);
-
- tor_free(fakehop);
-
- return or_circ;
+ extend_info_t fakehop;
+ memset(&fakehop, 0, sizeof(fakehop));
+ extend_info_t *fakehop_list[4] = {&fakehop,
+ &fakehop,
+ &fakehop,
+ &fakehop};
+
+ return new_test_origin_circuit(false,
+ circ_start_time,
+ 4,
+ fakehop_list);
}
-origin_circuit_t *
+static origin_circuit_t *
subtest_fourhop_circuit(struct timeval circ_start_time, int should_timeout)
{
- origin_circuit_t *or_circ = build_unopened_fourhop(circ_start_time);
+ origin_circuit_t *origin_circ = build_unopened_fourhop(circ_start_time);
// Now make them open one at a time and call
// circuit_build_times_handle_completed_hop();
- or_circ->cpath->state = CPATH_STATE_OPEN;
- circuit_build_times_handle_completed_hop(or_circ);
+ origin_circ->cpath->state = CPATH_STATE_OPEN;
+ circuit_build_times_handle_completed_hop(origin_circ);
tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 0);
- or_circ->cpath->next->state = CPATH_STATE_OPEN;
- circuit_build_times_handle_completed_hop(or_circ);
+ origin_circ->cpath->next->state = CPATH_STATE_OPEN;
+ circuit_build_times_handle_completed_hop(origin_circ);
tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 0);
// Third hop: We should count it now.
- or_circ->cpath->next->next->state = CPATH_STATE_OPEN;
- circuit_build_times_handle_completed_hop(or_circ);
+ origin_circ->cpath->next->next->state = CPATH_STATE_OPEN;
+ circuit_build_times_handle_completed_hop(origin_circ);
tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ,
!should_timeout); // 1 if counted, 0 otherwise
// Fourth hop: Don't double count
- or_circ->cpath->next->next->next->state = CPATH_STATE_OPEN;
- circuit_build_times_handle_completed_hop(or_circ);
+ origin_circ->cpath->next->next->next->state = CPATH_STATE_OPEN;
+ circuit_build_times_handle_completed_hop(origin_circ);
tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ,
!should_timeout);
done:
- return or_circ;
+ return origin_circ;
}
-void
+static void
test_circuitstats_hoplen(void *arg)
{
/* Plan:
diff --git a/src/test/test_config.c b/src/test/test_config.c
index 71beb93f67..655535f704 100644
--- a/src/test/test_config.c
+++ b/src/test/test_config.c
@@ -53,6 +53,7 @@
#include "test/test_helpers.h"
#include "test/resolve_test_helpers.h"
+#include "test/log_test_helpers.h"
#include "feature/dirclient/dir_server_st.h"
#include "core/or/port_cfg_st.h"
@@ -407,7 +408,7 @@ good_bridge_line_test(const char *string, const char *test_addrport,
tor_free(tmp);
}
- /* If we were asked to validate a transport name, make sure tha it
+ /* If we were asked to validate a transport name, make sure that it
matches with the transport name that was parsed. */
if (test_transport && !bridge_line->transport_name)
tt_abort();
@@ -991,53 +992,72 @@ test_config_fix_my_family(void *arg)
}
static int n_hostname_01010101 = 0;
+static const char *ret_addr_lookup_01010101[2] = {
+ "1.1.1.1", "0101::0101",
+};
-/** This mock function is meant to replace tor_lookup_hostname().
- * It answers with 1.1.1.1 as IP adddress that resulted from lookup.
+/** This mock function is meant to replace tor_addr_lookup().
+ * It answers with 1.1.1.1 as IP address that resulted from lookup.
* This function increments <b>n_hostname_01010101</b> counter by one
* every time it is called.
*/
static int
-tor_lookup_hostname_01010101(const char *name, uint32_t *addr)
+tor_addr_lookup_01010101(const char *name, uint16_t family, tor_addr_t *addr)
{
n_hostname_01010101++;
- if (name && addr) {
- *addr = ntohl(0x01010101);
+ if (family == AF_INET) {
+ if (name && addr) {
+ int ret = tor_addr_parse(addr, ret_addr_lookup_01010101[0]);
+ tt_int_op(ret, OP_EQ, family);
+ }
+ } else if (family == AF_INET6) {
+ if (name && addr) {
+ int ret = tor_addr_parse(addr, ret_addr_lookup_01010101[1]);
+ tt_int_op(ret, OP_EQ, family);
+ }
}
-
+ done:
return 0;
}
static int n_hostname_localhost = 0;
-/** This mock function is meant to replace tor_lookup_hostname().
- * It answers with 127.0.0.1 as IP adddress that resulted from lookup.
+/** This mock function is meant to replace tor_addr_lookup().
+ * It answers with 127.0.0.1 as IP address that resulted from lookup.
* This function increments <b>n_hostname_localhost</b> counter by one
* every time it is called.
*/
static int
-tor_lookup_hostname_localhost(const char *name, uint32_t *addr)
+tor_addr_lookup_localhost(const char *name, uint16_t family, tor_addr_t *addr)
{
n_hostname_localhost++;
- if (name && addr) {
- *addr = 0x7f000001;
+ if (family == AF_INET) {
+ if (name && addr) {
+ tor_addr_from_ipv4h(addr, 0x7f000001);
+ }
+ } else if (family == AF_INET6) {
+ if (name && addr) {
+ int ret = tor_addr_parse(addr, "::1");
+ tt_int_op(ret, OP_EQ, AF_INET6);
+ }
}
-
+ done:
return 0;
}
static int n_hostname_failure = 0;
-/** This mock function is meant to replace tor_lookup_hostname().
+/** This mock function is meant to replace tor_addr_lookup().
* It pretends to fail by returning -1 to caller. Also, this function
* increments <b>n_hostname_failure</b> every time it is called.
*/
static int
-tor_lookup_hostname_failure(const char *name, uint32_t *addr)
+tor_addr_lookup_failure(const char *name, uint16_t family, tor_addr_t *addr)
{
(void)name;
+ (void)family;
(void)addr;
n_hostname_failure++;
@@ -1045,6 +1065,46 @@ tor_lookup_hostname_failure(const char *name, uint32_t *addr)
return -1;
}
+/** Mock function for tor_addr_lookup().
+ *
+ * Depending on the given hostname and family, resolve either to IPv4 or IPv6.
+ *
+ * If the requested hostname family is not the same as the family provided, an
+ * error is returned.
+ *
+ * Possible hostnames:
+ * - www.torproject.org.v4 for IPv4 -> 1.1.1.1
+ * - www.torproject.org.v6 for IPv6 -> [0101::0101]
+ */
+static int
+tor_addr_lookup_mixed(const char *name, uint16_t family, tor_addr_t *addr)
+{
+ tt_assert(addr);
+ tt_assert(name);
+
+ if (!strcmp(name, "www.torproject.org.v4")) {
+ if (family == AF_INET) {
+ tor_addr_from_ipv4h(addr, 0x01010101);
+ return 0;
+ }
+ /* Resolving AF_INET but the asked family is different. Failure. */
+ return -1;
+ }
+
+ if (!strcmp(name, "www.torproject.org.v6")) {
+ if (family == AF_INET6) {
+ int ret = tor_addr_parse(addr, "0101::0101");
+ tt_int_op(ret, OP_EQ, AF_INET6);
+ return 0;
+ }
+ /* Resolving AF_INET6 but the asked family is not. Failure. */
+ return -1;
+ }
+
+ done:
+ return 0;
+}
+
static int n_gethostname_replacement = 0;
/** This mock function is meant to replace tor_gethostname(). It
@@ -1099,29 +1159,39 @@ tor_gethostname_failure(char *name, size_t namelen)
return -1;
}
-static int n_get_interface_address = 0;
+static int n_get_interface_address6 = 0;
+static sa_family_t last_address6_family;
+static const char *ret_get_interface_address6_08080808[2] = {
+ "8.8.8.8", "0808::0808",
+};
/** This mock function is meant to replace get_interface_address().
* It answers with address 8.8.8.8. This function increments
* <b>n_get_interface_address</b> by one every time it is called.
*/
static int
-get_interface_address_08080808(int severity, uint32_t *addr)
+get_interface_address6_08080808(int severity, sa_family_t family,
+ tor_addr_t *addr)
{
(void)severity;
- n_get_interface_address++;
+ n_get_interface_address6++;
- if (addr) {
- *addr = ntohl(0x08080808);
+ if (family == AF_INET) {
+ if (addr) {
+ int ret = tor_addr_parse(addr, ret_get_interface_address6_08080808[0]);
+ tt_int_op(ret, OP_EQ, AF_INET);
+ }
+ } else if (family == AF_INET6) {
+ if (addr) {
+ int ret = tor_addr_parse(addr, ret_get_interface_address6_08080808[1]);
+ tt_int_op(ret, OP_EQ, AF_INET6);
+ }
}
-
+ done:
return 0;
}
-static int n_get_interface_address6 = 0;
-static sa_family_t last_address6_family;
-
/** This mock function is meant to replace get_interface_address6().
* It answers with IP address 9.9.9.9 iff both of the following are true:
* - <b>family</b> is AF_INET
@@ -1129,6 +1199,7 @@ static sa_family_t last_address6_family;
* This function increments <b>n_get_interface_address6</b> by one every
* time it is called.
*/
+#if 0
static int
get_interface_address6_replacement(int severity, sa_family_t family,
tor_addr_t *addr)
@@ -1146,25 +1217,7 @@ get_interface_address6_replacement(int severity, sa_family_t family,
return 0;
}
-
-static int n_get_interface_address_failure = 0;
-
-/**
- * This mock function is meant to replace get_interface_address().
- * It pretends to fail getting interface address by returning -1.
- * <b>n_get_interface_address_failure</b> is incremented by one
- * every time this function is called.
- */
-static int
-get_interface_address_failure(int severity, uint32_t *addr)
-{
- (void)severity;
- (void)addr;
-
- n_get_interface_address_failure++;
-
- return -1;
-}
+#endif
static int n_get_interface_address6_failure = 0;
@@ -1187,24 +1240,44 @@ get_interface_address6_failure(int severity, sa_family_t family,
return -1;
}
+/** Helper macro: to validate the returned value from find_my_address() so we
+ * don't copy those all the time. */
+#undef VALIDATE_FOUND_ADDRESS
+#define VALIDATE_FOUND_ADDRESS(ret, method, hostname) \
+ do { \
+ tt_int_op(retval, OP_EQ, ret); \
+ tt_int_op(method, OP_EQ, method_used); \
+ if (hostname == NULL) tt_assert(!hostname_out); \
+ else tt_str_op(hostname_out, OP_EQ, hostname); \
+ if (ret == true) { \
+ tt_assert(tor_addr_eq(&resolved_addr, &test_addr)); \
+ } \
+ } while (0)
+
+/** Helper macro: Cleanup the address and variables used after a
+ * find_my_address() call. */
+#undef CLEANUP_FOUND_ADDRESS
+#define CLEANUP_FOUND_ADDRESS \
+ do { \
+ config_free_lines(options->Address); \
+ config_free_lines(options->ORPort_lines); \
+ options->AddressDisableIPv6 = 0; \
+ options->ORPort_set = 0; \
+ tor_free(options->DirAuthorities); \
+ tor_free(hostname_out); \
+ tor_addr_make_unspec(&resolved_addr); \
+ tor_addr_make_unspec(&test_addr); \
+ } while (0)
+
+/** Test both IPv4 and IPv6 coexisting together in the configuration. */
static void
-test_config_resolve_my_address(void *arg)
+test_config_find_my_address_mixed(void *arg)
{
or_options_t *options;
- uint32_t resolved_addr;
- const char *method_used;
+ tor_addr_t resolved_addr, test_addr;
+ resolved_addr_method_t method_used;
char *hostname_out = NULL;
- int retval;
- int prev_n_hostname_01010101;
- int prev_n_hostname_localhost;
- int prev_n_hostname_failure;
- int prev_n_gethostname_replacement;
- int prev_n_gethostname_failure;
- int prev_n_gethostname_localhost;
- int prev_n_get_interface_address;
- int prev_n_get_interface_address_failure;
- int prev_n_get_interface_address6;
- int prev_n_get_interface_address6_failure;
+ bool retval;
(void)arg;
@@ -1212,369 +1285,530 @@ test_config_resolve_my_address(void *arg)
options_init(options);
- /*
- * CASE 1:
- * If options->Address is a valid IPv4 address string, we want
- * the corresponding address to be parsed and returned.
- */
-
- options->Address = tor_strdup("128.52.128.105");
+ /*
+ * CASE 1: Only IPv6 address. Accepted.
+ */
+ config_line_append(&options->Address, "Address",
+ "2a01:4f8:fff0:4f:266:37ff:fe2c:5d19");
+ tor_addr_parse(&test_addr, "2a01:4f8:fff0:4f:266:37ff:fe2c:5d19");
- retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
- &method_used,&hostname_out);
+ /* IPv6 address should be found and considered configured. */
+ retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, RESOLVED_ADDR_CONFIGURED, NULL);
- tt_want(retval == 0);
- tt_want_str_op(method_used,OP_EQ,"CONFIGURED");
- tt_want(hostname_out == NULL);
- tt_assert(resolved_addr == 0x80348069);
+ CLEANUP_FOUND_ADDRESS;
- tor_free(options->Address);
+ /*
+ * Case 2: IPv4 _and_ IPv6 given. Accepted.
+ */
+ config_line_append(&options->Address, "Address",
+ "2a01:4f8:fff0:4f:266:37ff:fe2c:5d19");
+ config_line_append(&options->Address, "Address", "1.1.1.1");
+ tor_addr_parse(&test_addr, "1.1.1.1");
-/*
- * CASE 2:
- * If options->Address is a valid DNS address, we want resolve_my_address()
- * function to ask tor_lookup_hostname() for help with resolving it
- * and return the address that was resolved (in host order).
- */
+ /* IPv4 address should be found and considered configured. */
+ retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, RESOLVED_ADDR_CONFIGURED, NULL);
- MOCK(tor_lookup_hostname,tor_lookup_hostname_01010101);
+ /* IPv6 address should be found and considered configured. */
+ tor_addr_parse(&test_addr, "2a01:4f8:fff0:4f:266:37ff:fe2c:5d19");
+ retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, RESOLVED_ADDR_CONFIGURED, NULL);
- tor_free(options->Address);
- options->Address = tor_strdup("www.torproject.org");
+ CLEANUP_FOUND_ADDRESS;
- prev_n_hostname_01010101 = n_hostname_01010101;
+ /*
+ * Case 3: Two hostnames, IPv4 and IPv6.
+ */
+ config_line_append(&options->Address, "Address", "www.torproject.org.v4");
+ config_line_append(&options->Address, "Address", "www.torproject.org.v6");
+
+ /* Looks at specific hostname to learn which address family to use. */
+ MOCK(tor_addr_lookup, tor_addr_lookup_mixed);
+
+ /* IPv4 address should be found and considered resolved. */
+ tor_addr_parse(&test_addr, "1.1.1.1");
+ retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, RESOLVED_ADDR_RESOLVED,
+ "www.torproject.org.v4");
+ tor_free(hostname_out);
- retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
- &method_used,&hostname_out);
+ /* IPv6 address should be found and considered resolved. */
+ tor_addr_parse(&test_addr, "0101::0101");
+ retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, RESOLVED_ADDR_RESOLVED,
+ "www.torproject.org.v6");
- tt_want(retval == 0);
- tt_want(n_hostname_01010101 == prev_n_hostname_01010101 + 1);
- tt_want_str_op(method_used,OP_EQ,"RESOLVED");
- tt_want_str_op(hostname_out,OP_EQ,"www.torproject.org");
- tt_assert(resolved_addr == 0x01010101);
+ CLEANUP_FOUND_ADDRESS;
+ UNMOCK(tor_addr_lookup);
- UNMOCK(tor_lookup_hostname);
+ /*
+ * Case 4: IPv4 address and a hostname resolving to IPV6.
+ */
+ config_line_append(&options->Address, "Address", "1.1.1.1");
+ config_line_append(&options->Address, "Address", "www.torproject.org.v6");
+
+ /* Looks at specific hostname to learn which address family to use. */
+ MOCK(tor_addr_lookup, tor_addr_lookup_mixed);
+
+ /* IPv4 address should be found and configured. */
+ tor_addr_parse(&test_addr, "1.1.1.1");
+ retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, RESOLVED_ADDR_CONFIGURED, NULL);
+
+ /* IPv6 address should be found and considered resolved. */
+ tor_addr_parse(&test_addr, "0101::0101");
+ retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, RESOLVED_ADDR_RESOLVED,
+ "www.torproject.org.v6");
+
+ CLEANUP_FOUND_ADDRESS;
+ UNMOCK(tor_addr_lookup);
- tor_free(options->Address);
+ /*
+ * Case 5: Hostname resolving to IPv4 and an IPv6 address.
+ */
+ config_line_append(&options->Address, "Address", "0101::0101");
+ config_line_append(&options->Address, "Address", "www.torproject.org.v4");
+
+ /* Looks at specific hostname to learn which address family to use. */
+ MOCK(tor_addr_lookup, tor_addr_lookup_mixed);
+
+ /* IPv4 address should be found and resolved. */
+ tor_addr_parse(&test_addr, "1.1.1.1");
+ retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, RESOLVED_ADDR_RESOLVED,
+ "www.torproject.org.v4");
tor_free(hostname_out);
-/*
- * CASE 3:
- * Given that options->Address is NULL, we want resolve_my_address()
- * to try and use tor_gethostname() to get hostname AND use
- * tor_lookup_hostname() to get IP address.
- */
+ /* IPv6 address should be found and considered resolved. */
+ tor_addr_parse(&test_addr, "0101::0101");
+ retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, RESOLVED_ADDR_CONFIGURED, NULL);
+ CLEANUP_FOUND_ADDRESS;
- resolved_addr = 0;
- tor_free(options->Address);
- options->Address = NULL;
+ UNMOCK(tor_addr_lookup);
- MOCK(tor_gethostname,tor_gethostname_replacement);
- MOCK(tor_lookup_hostname,tor_lookup_hostname_01010101);
+ done:
+ config_free_lines(options->Address);
+ or_options_free(options);
+ tor_free(hostname_out);
- prev_n_gethostname_replacement = n_gethostname_replacement;
- prev_n_hostname_01010101 = n_hostname_01010101;
+ UNMOCK(tor_addr_lookup);
+}
- retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
- &method_used,&hostname_out);
+/** Parameters for the find_my_address() test. We test both AF_INET and
+ * AF_INET6 but we have one interface to do so thus we run the same exact unit
+ * tests for both without copying them. */
+typedef struct find_my_address_params_t {
+ /* Index where the mock function results are located. For instance,
+ * tor_addr_lookup_01010101() will have its returned value depending on the
+ * family in ret_addr_lookup_01010101[].
+ *
+ * Values that can be found:
+ * AF_INET : index 0.
+ * AF_INET6: index 1.
+ */
+ int idx;
+ int family;
+ const char *public_ip;
+ const char *internal_ip;
+ const char *orport;
+} find_my_address_params_t;
+
+static find_my_address_params_t addr_param_v4 = {
+ .idx = 0,
+ .family = AF_INET,
+ .public_ip = "128.52.128.105",
+ .internal_ip = "127.0.0.1",
+};
- tt_want(retval == 0);
- tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
- tt_want(n_hostname_01010101 == prev_n_hostname_01010101 + 1);
- tt_want_str_op(method_used,OP_EQ,"GETHOSTNAME");
- tt_want_str_op(hostname_out,OP_EQ,"onionrouter!");
- tt_assert(resolved_addr == 0x01010101);
+static find_my_address_params_t addr_param_v6 = {
+ .idx = 1,
+ .family = AF_INET6,
+ .public_ip = "[4242::4242]",
+ .internal_ip = "[::1]",
+};
- UNMOCK(tor_gethostname);
- UNMOCK(tor_lookup_hostname);
+static void
+test_config_find_my_address(void *arg)
+{
+ or_options_t *options;
+ tor_addr_t resolved_addr, test_addr;
+ resolved_addr_method_t method_used;
+ char *hostname_out = NULL;
+ bool retval;
+ int prev_n_hostname_01010101;
+ int prev_n_hostname_failure;
+ int prev_n_hostname_localhost;
+ int prev_n_gethostname_replacement;
+ int prev_n_gethostname_failure;
+ int prev_n_gethostname_localhost;
+ int prev_n_get_interface_address6;
+ int prev_n_get_interface_address6_failure;
- tor_free(hostname_out);
+ const find_my_address_params_t *p = arg;
-/*
- * CASE 4:
- * Given that options->Address is a local host address, we want
- * resolve_my_address() function to fail.
- */
+ options = options_new();
+ options_init(options);
+ options->PublishServerDescriptor_ = V3_DIRINFO;
- resolved_addr = 0;
- tor_free(options->Address);
- options->Address = tor_strdup("127.0.0.1");
+ /*
+ * Case 0:
+ * AddressDisableIPv6 is set.
+ *
+ * Only run this if we are in the IPv6 test.
+ */
+ if (p->family == AF_INET6) {
+ options->AddressDisableIPv6 = 1;
+ /* Set a valid IPv6. However, the discovery should still fail. */
+ config_line_append(&options->Address, "Address", p->public_ip);
+ tor_addr_parse(&test_addr, p->public_ip);
+
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(false, RESOLVED_ADDR_NONE, NULL);
+ CLEANUP_FOUND_ADDRESS;
+ }
- retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
- &method_used,&hostname_out);
+ /*
+ * Case 1:
+ * 1. Address is a valid address.
+ *
+ * Expected to succeed.
+ */
+ config_line_append(&options->Address, "Address", p->public_ip);
+ tor_addr_parse(&test_addr, p->public_ip);
- tt_want(resolved_addr == 0);
- tt_int_op(retval, OP_EQ, -1);
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
- tor_free(options->Address);
- tor_free(hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, RESOLVED_ADDR_CONFIGURED, NULL);
+ CLEANUP_FOUND_ADDRESS;
-/*
- * CASE 5:
- * We want resolve_my_address() to fail if DNS address in options->Address
- * cannot be resolved.
- */
+ /*
+ * Case 2: Address is a resolvable address. Expected to succeed.
+ */
+ MOCK(tor_addr_lookup, tor_addr_lookup_01010101);
- MOCK(tor_lookup_hostname,tor_lookup_hostname_failure);
+ config_line_append(&options->Address, "Address", "www.torproject.org");
+ tor_addr_parse(&test_addr, ret_addr_lookup_01010101[p->idx]);
- prev_n_hostname_failure = n_hostname_failure;
+ prev_n_hostname_01010101 = n_hostname_01010101;
- tor_free(options->Address);
- options->Address = tor_strdup("www.tor-project.org");
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
- retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
- &method_used,&hostname_out);
+ tt_int_op(n_hostname_01010101, OP_EQ, ++prev_n_hostname_01010101);
+ VALIDATE_FOUND_ADDRESS(true, RESOLVED_ADDR_RESOLVED, "www.torproject.org");
+ CLEANUP_FOUND_ADDRESS;
- tt_want(n_hostname_failure == prev_n_hostname_failure + 1);
- tt_int_op(retval, OP_EQ, -1);
+ UNMOCK(tor_addr_lookup);
- UNMOCK(tor_lookup_hostname);
+ /*
+ * Case 3: Address is a local addressi (internal). Expected to fail.
+ */
+ config_line_append(&options->Address, "Address", p->internal_ip);
- tor_free(options->Address);
- tor_free(hostname_out);
+ setup_full_capture_of_logs(LOG_NOTICE);
-/*
- * CASE 6:
- * If options->Address is NULL AND gettting local hostname fails, we want
- * resolve_my_address() to fail as well.
- */
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
- MOCK(tor_gethostname,tor_gethostname_failure);
+ expect_log_msg_containing("is a private IP address. Tor relays that "
+ "use the default DirAuthorities must have "
+ "public IP addresses.");
+ teardown_capture_of_logs();
- prev_n_gethostname_failure = n_gethostname_failure;
+ VALIDATE_FOUND_ADDRESS(false, RESOLVED_ADDR_NONE, NULL);
+ CLEANUP_FOUND_ADDRESS;
- retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
- &method_used,&hostname_out);
+ /*
+ * Case 4: Address is a local address but custom authorities. Expected to
+ * succeed.
+ */
+ config_line_append(&options->Address, "Address", p->internal_ip);
+ options->DirAuthorities = tor_malloc_zero(sizeof(config_line_t));
+ tor_addr_parse(&test_addr, p->internal_ip);
- tt_want(n_gethostname_failure == prev_n_gethostname_failure + 1);
- tt_int_op(retval, OP_EQ, -1);
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
- UNMOCK(tor_gethostname);
- tor_free(hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, RESOLVED_ADDR_CONFIGURED, NULL);
+ CLEANUP_FOUND_ADDRESS;
-/*
- * CASE 7:
- * We want resolve_my_address() to try and get network interface address via
- * get_interface_address() if hostname returned by tor_gethostname() cannot be
- * resolved into IP address.
- */
-
- MOCK(tor_gethostname,tor_gethostname_replacement);
- MOCK(tor_lookup_hostname,tor_lookup_hostname_failure);
- MOCK(get_interface_address,get_interface_address_08080808);
+ /*
+ * Case 5: Multiple address in Address. Expected to fail.
+ */
+ config_line_append(&options->Address, "Address", p->public_ip);
+ config_line_append(&options->Address, "Address", p->public_ip);
- prev_n_gethostname_replacement = n_gethostname_replacement;
- prev_n_get_interface_address = n_get_interface_address;
+ setup_full_capture_of_logs(LOG_NOTICE);
- retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
- &method_used,&hostname_out);
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
- tt_want(retval == 0);
- tt_want_int_op(n_gethostname_replacement, OP_EQ,
- prev_n_gethostname_replacement + 1);
- tt_want_int_op(n_get_interface_address, OP_EQ,
- prev_n_get_interface_address + 1);
- tt_want_str_op(method_used,OP_EQ,"INTERFACE");
- tt_want(hostname_out == NULL);
- tt_assert(resolved_addr == 0x08080808);
+ expect_log_msg_containing("Found 2 Address statement of address family");
+ teardown_capture_of_logs();
- UNMOCK(get_interface_address);
- tor_free(hostname_out);
+ VALIDATE_FOUND_ADDRESS(false, RESOLVED_ADDR_NONE, NULL);
+ CLEANUP_FOUND_ADDRESS;
-/*
- * CASE 8:
- * Suppose options->Address is NULL AND hostname returned by tor_gethostname()
- * is unresolvable. We want resolve_my_address to fail if
- * get_interface_address() fails.
- */
+ /*
+ * Case 8:
+ * 1. Address is NULL
+ * 2. Interface address is a valid address.
+ *
+ * Expected to succeed.
+ */
+ options->Address = NULL;
+ tor_addr_parse(&test_addr, ret_get_interface_address6_08080808[p->idx]);
- MOCK(get_interface_address,get_interface_address_failure);
+ MOCK(get_interface_address6, get_interface_address6_08080808);
- prev_n_get_interface_address_failure = n_get_interface_address_failure;
- prev_n_gethostname_replacement = n_gethostname_replacement;
+ prev_n_get_interface_address6 = n_get_interface_address6;
- retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
- &method_used,&hostname_out);
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
- tt_want(n_get_interface_address_failure ==
- prev_n_get_interface_address_failure + 1);
- tt_want(n_gethostname_replacement ==
- prev_n_gethostname_replacement + 1);
- tt_int_op(retval, OP_EQ, -1);
+ tt_int_op(n_get_interface_address6, OP_EQ, ++prev_n_get_interface_address6);
+ VALIDATE_FOUND_ADDRESS(true, RESOLVED_ADDR_INTERFACE, NULL);
+ CLEANUP_FOUND_ADDRESS;
- UNMOCK(get_interface_address);
- tor_free(hostname_out);
+ UNMOCK(get_interface_address6);
-/*
- * CASE 9:
- * Given that options->Address is NULL AND tor_lookup_hostname()
- * fails AND hostname returned by gethostname() resolves
- * to local IP address, we want resolve_my_address() function to
- * call get_interface_address6(.,AF_INET,.) and return IP address
- * the latter function has found.
- */
+ /*
+ * Case 9:
+ * 1. Address is NULL
+ * 2. Interface address fails to be found.
+ * 3. Local hostname resolves to a valid address.
+ *
+ * Expected to succeed.
+ */
+ options->Address = NULL;
+ tor_addr_parse(&test_addr, ret_addr_lookup_01010101[p->idx]);
- MOCK(tor_lookup_hostname,tor_lookup_hostname_failure);
- MOCK(tor_gethostname,tor_gethostname_replacement);
- MOCK(get_interface_address6,get_interface_address6_replacement);
+ MOCK(get_interface_address6, get_interface_address6_failure);
+ MOCK(tor_gethostname, tor_gethostname_replacement);
+ MOCK(tor_addr_lookup, tor_addr_lookup_01010101);
+ prev_n_get_interface_address6_failure = n_get_interface_address6_failure;
+ prev_n_hostname_01010101 = n_hostname_01010101;
prev_n_gethostname_replacement = n_gethostname_replacement;
- prev_n_hostname_failure = n_hostname_failure;
- prev_n_get_interface_address6 = n_get_interface_address6;
- retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
- &method_used,&hostname_out);
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
- tt_want(last_address6_family == AF_INET);
- tt_want(n_get_interface_address6 == prev_n_get_interface_address6 + 1);
- tt_want(n_hostname_failure == prev_n_hostname_failure + 1);
- tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
- tt_want(retval == 0);
- tt_want_str_op(method_used,OP_EQ,"INTERFACE");
- tt_assert(resolved_addr == 0x09090909);
+ tt_int_op(n_get_interface_address6_failure, OP_EQ,
+ ++prev_n_get_interface_address6_failure);
+ tt_int_op(n_hostname_01010101, OP_EQ,
+ ++prev_n_hostname_01010101);
+ tt_int_op(n_gethostname_replacement, OP_EQ,
+ ++prev_n_gethostname_replacement);
+ VALIDATE_FOUND_ADDRESS(true, RESOLVED_ADDR_GETHOSTNAME, "onionrouter!");
+ CLEANUP_FOUND_ADDRESS;
- UNMOCK(tor_lookup_hostname);
- UNMOCK(tor_gethostname);
UNMOCK(get_interface_address6);
-
- tor_free(hostname_out);
+ UNMOCK(tor_gethostname);
+ UNMOCK(tor_addr_lookup);
/*
- * CASE 10: We want resolve_my_address() to fail if all of the following
- * are true:
- * 1. options->Address is not NULL
- * 2. ... but it cannot be converted to struct in_addr by
- * tor_inet_aton()
- * 3. ... and tor_lookup_hostname() fails to resolve the
- * options->Address
+ * Case 10:
+ * 1. Address is NULL
+ * 2. Interface address fails to be found.
+ * 3. Local hostname resolves to an internal address.
+ *
+ * Expected to fail.
*/
+ options->Address = NULL;
- MOCK(tor_lookup_hostname,tor_lookup_hostname_failure);
-
- prev_n_hostname_failure = n_hostname_failure;
+ MOCK(get_interface_address6, get_interface_address6_failure);
+ MOCK(tor_gethostname, tor_gethostname_localhost);
+ MOCK(tor_addr_lookup, tor_addr_lookup_localhost);
- tor_free(options->Address);
- options->Address = tor_strdup("some_hostname");
+ prev_n_get_interface_address6_failure = n_get_interface_address6_failure;
+ prev_n_hostname_localhost = n_hostname_localhost;
+ prev_n_gethostname_localhost = n_gethostname_localhost;
- retval = resolve_my_address(LOG_NOTICE, options, &resolved_addr,
- &method_used,&hostname_out);
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
- tt_want(n_hostname_failure == prev_n_hostname_failure + 1);
- tt_int_op(retval, OP_EQ, -1);
+ tt_int_op(n_get_interface_address6_failure, OP_EQ,
+ ++prev_n_get_interface_address6_failure);
+ tt_int_op(n_hostname_localhost, OP_EQ,
+ ++prev_n_hostname_localhost);
+ tt_int_op(n_gethostname_localhost, OP_EQ,
+ ++prev_n_gethostname_localhost);
+ VALIDATE_FOUND_ADDRESS(false, RESOLVED_ADDR_NONE, NULL);
+ CLEANUP_FOUND_ADDRESS;
+ UNMOCK(get_interface_address6);
UNMOCK(tor_gethostname);
- UNMOCK(tor_lookup_hostname);
-
- tor_free(hostname_out);
+ UNMOCK(tor_addr_lookup);
/*
- * CASE 11:
- * Suppose the following sequence of events:
- * 1. options->Address is NULL
- * 2. tor_gethostname() succeeds to get hostname of machine Tor
- * if running on.
- * 3. Hostname from previous step cannot be converted to
- * address by using tor_inet_aton() function.
- * 4. However, tor_lookup_hostname() succeeds in resolving the
- * hostname from step 2.
- * 5. Unfortunately, tor_addr_is_internal() deems this address
- * to be internal.
- * 6. get_interface_address6(.,AF_INET,.) returns non-internal
- * IPv4
+ * Case 11:
+ * 1. Address is NULL
+ * 2. Interface address fails to be found.
+ * 3. Local hostname fails to be found.
*
- * We want resolve_my_addr() to succeed with method "INTERFACE"
- * and address from step 6.
+ * Expected to fail.
*/
-
- tor_free(options->Address);
options->Address = NULL;
- MOCK(tor_gethostname,tor_gethostname_replacement);
- MOCK(tor_lookup_hostname,tor_lookup_hostname_localhost);
- MOCK(get_interface_address6,get_interface_address6_replacement);
+ MOCK(get_interface_address6, get_interface_address6_failure);
+ MOCK(tor_gethostname, tor_gethostname_failure);
- prev_n_gethostname_replacement = n_gethostname_replacement;
- prev_n_hostname_localhost = n_hostname_localhost;
- prev_n_get_interface_address6 = n_get_interface_address6;
+ prev_n_get_interface_address6_failure = n_get_interface_address6_failure;
+ prev_n_gethostname_failure = n_gethostname_failure;
- retval = resolve_my_address(LOG_DEBUG, options, &resolved_addr,
- &method_used,&hostname_out);
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
- tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
- tt_want(n_hostname_localhost == prev_n_hostname_localhost + 1);
- tt_want(n_get_interface_address6 == prev_n_get_interface_address6 + 1);
+ tt_int_op(n_get_interface_address6_failure, OP_EQ,
+ ++prev_n_get_interface_address6_failure);
+ tt_int_op(n_gethostname_failure, OP_EQ,
+ ++prev_n_gethostname_failure);
+ VALIDATE_FOUND_ADDRESS(false, RESOLVED_ADDR_NONE, NULL);
+ CLEANUP_FOUND_ADDRESS;
- tt_str_op(method_used,OP_EQ,"INTERFACE");
- tt_ptr_op(hostname_out, OP_EQ, NULL);
- tt_int_op(retval, OP_EQ, 0);
+ UNMOCK(get_interface_address6);
+ UNMOCK(tor_gethostname);
/*
- * CASE 11b:
- * 1-5 as above.
- * 6. get_interface_address6() fails.
+ * Case 12:
+ * 1. Address is NULL
+ * 2. Interface address fails to be found.
+ * 3. Local hostname can't be resolved.
*
- * In this subcase, we want resolve_my_address() to fail.
+ * Expected to fail.
*/
+ options->Address = NULL;
- UNMOCK(get_interface_address6);
- MOCK(get_interface_address6,get_interface_address6_failure);
+ MOCK(get_interface_address6, get_interface_address6_failure);
+ MOCK(tor_gethostname, tor_gethostname_replacement);
+ MOCK(tor_addr_lookup, tor_addr_lookup_failure);
- prev_n_gethostname_replacement = n_gethostname_replacement;
- prev_n_hostname_localhost = n_hostname_localhost;
prev_n_get_interface_address6_failure = n_get_interface_address6_failure;
+ prev_n_gethostname_replacement = n_gethostname_replacement;
+ prev_n_hostname_failure = n_hostname_failure;
- retval = resolve_my_address(LOG_DEBUG, options, &resolved_addr,
- &method_used,&hostname_out);
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
- tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
- tt_want(n_hostname_localhost == prev_n_hostname_localhost + 1);
- tt_want(n_get_interface_address6_failure ==
- prev_n_get_interface_address6_failure + 1);
+ tt_int_op(n_get_interface_address6_failure, OP_EQ,
+ ++prev_n_get_interface_address6_failure);
+ tt_int_op(n_gethostname_replacement, OP_EQ,
+ ++prev_n_gethostname_replacement);
+ tt_int_op(n_hostname_failure, OP_EQ,
+ ++prev_n_hostname_failure);
+ VALIDATE_FOUND_ADDRESS(false, RESOLVED_ADDR_NONE, NULL);
+ CLEANUP_FOUND_ADDRESS;
+
+ /*
+ * Case 13:
+ * 1. Address is NULL.
+ * 2. ORPort has a valid public address.
+ */
+ {
+ char *msg = NULL;
+ int n, w, ret;
+ char *orport_line = NULL;
+
+ options->Address = NULL;
+ tor_asprintf(&orport_line, "%s:9001", p->public_ip);
+ config_line_append(&options->ORPort_lines, "ORPort", orport_line);
+ tor_free(orport_line);
+
+ if (p->family == AF_INET6) {
+ /* XXX: Tor does _not_ allow an IPv6 only ORPort thus we need to add a
+ * bogus IPv4 at the moment. */
+ config_line_append(&options->ORPort_lines, "ORPort", "1.1.1.1:9001");
+ }
- tt_int_op(retval, OP_EQ, -1);
+ ret = parse_ports(options, 0, &msg, &n, &w);
+ tt_int_op(ret, OP_EQ, 0);
+ tor_addr_parse(&test_addr, p->public_ip);
+ }
- UNMOCK(tor_gethostname);
- UNMOCK(tor_lookup_hostname);
- UNMOCK(get_interface_address6);
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, RESOLVED_ADDR_CONFIGURED_ORPORT, NULL);
+ CLEANUP_FOUND_ADDRESS;
- /* CASE 12:
- * Suppose the following happens:
- * 1. options->Address is NULL AND options->DirAuthorities is non-NULL
- * 2. tor_gethostname() succeeds in getting hostname of a machine ...
- * 3. ... which is successfully parsed by tor_inet_aton() ...
- * 4. into IPv4 address that tor_addr_is_inernal() considers to be
- * internal.
- *
- * In this case, we want resolve_my_address() to fail.
+ /*
+ * Case 14:
+ * 1. Address is NULL.
+ * 2. ORPort has an internal address thus fails.
+ * 3. Interface as a valid address.
*/
+ {
+ char *msg = NULL;
+ int n, w, ret;
+ char *orport_line = NULL;
+
+ options->Address = NULL;
+ tor_asprintf(&orport_line, "%s:9001", p->internal_ip);
+ config_line_append(&options->ORPort_lines, "ORPort", orport_line);
+ tor_free(orport_line);
+
+ if (p->family == AF_INET6) {
+ /* XXX: Tor does _not_ allow an IPv6 only ORPort thus we need to add a
+ * bogus IPv4 at the moment. */
+ config_line_append(&options->ORPort_lines, "ORPort", "1.1.1.1:9001");
+ }
- tor_free(options->Address);
- options->Address = NULL;
- options->DirAuthorities = tor_malloc_zero(sizeof(config_line_t));
+ ret = parse_ports(options, 0, &msg, &n, &w);
+ tt_int_op(ret, OP_EQ, 0);
+ }
+ tor_addr_parse(&test_addr, ret_get_interface_address6_08080808[p->idx]);
- MOCK(tor_gethostname,tor_gethostname_localhost);
+ MOCK(get_interface_address6, get_interface_address6_08080808);
- prev_n_gethostname_localhost = n_gethostname_localhost;
+ prev_n_get_interface_address6 = n_get_interface_address6;
+
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
- retval = resolve_my_address(LOG_DEBUG, options, &resolved_addr,
- &method_used,&hostname_out);
+ tt_int_op(n_get_interface_address6, OP_EQ, ++prev_n_get_interface_address6);
+ VALIDATE_FOUND_ADDRESS(true, RESOLVED_ADDR_INTERFACE, NULL);
+ CLEANUP_FOUND_ADDRESS;
+
+ /*
+ * Case 15: Address is a local address (internal) but we unset
+ * PublishServerDescriptor_ so we are allowed to hold it.
+ */
+ options->PublishServerDescriptor_ = NO_DIRINFO;
+ if (p->family == AF_INET) {
+ options->AssumeReachable = 1;
+ }
+ config_line_append(&options->Address, "Address", p->internal_ip);
- tt_want(n_gethostname_localhost == prev_n_gethostname_localhost + 1);
- tt_int_op(retval, OP_EQ, -1);
+ tor_addr_parse(&test_addr, p->internal_ip);
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, RESOLVED_ADDR_CONFIGURED, NULL);
+ CLEANUP_FOUND_ADDRESS;
+ UNMOCK(get_interface_address6);
UNMOCK(tor_gethostname);
+ UNMOCK(tor_addr_lookup);
done:
- tor_free(options->Address);
- tor_free(options->DirAuthorities);
or_options_free(options);
- tor_free(hostname_out);
UNMOCK(tor_gethostname);
- UNMOCK(tor_lookup_hostname);
- UNMOCK(get_interface_address);
+ UNMOCK(tor_addr_lookup);
UNMOCK(get_interface_address6);
- UNMOCK(tor_gethostname);
}
static void
@@ -2073,7 +2307,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 1);
@@ -2085,7 +2319,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 0);
@@ -2097,7 +2331,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 0);
@@ -2116,7 +2350,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 1);
@@ -2128,7 +2362,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 0);
@@ -2140,7 +2374,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 0);
@@ -2152,7 +2386,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_non_default_fallback +=
- (ds->dir_port == 60093 ?
+ (ds->ipv4_dirport == 60093 ?
1 : 0)
);
tt_int_op(found_non_default_fallback, OP_EQ, 1);
@@ -2164,7 +2398,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_default_fallback +=
- (ds->dir_port == 60099 ?
+ (ds->ipv4_dirport == 60099 ?
1 : 0)
);
tt_int_op(found_default_fallback, OP_EQ, 0);
@@ -2216,7 +2450,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 1);
@@ -2228,7 +2462,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 0);
@@ -2240,7 +2474,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 0);
@@ -2259,7 +2493,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 1);
@@ -2271,7 +2505,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 0);
@@ -2283,7 +2517,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 0);
@@ -2295,7 +2529,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_non_default_fallback +=
- (ds->dir_port == 60093 ?
+ (ds->ipv4_dirport == 60093 ?
1 : 0)
);
tt_int_op(found_non_default_fallback, OP_EQ, 0);
@@ -2307,7 +2541,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_default_fallback +=
- (ds->dir_port == 60099 ?
+ (ds->ipv4_dirport == 60099 ?
1 : 0)
);
tt_int_op(found_default_fallback, OP_EQ, 0);
@@ -2359,7 +2593,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 0);
@@ -2371,7 +2605,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 1);
@@ -2383,7 +2617,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 1);
@@ -2402,7 +2636,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 0);
@@ -2414,7 +2648,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 1);
@@ -2426,7 +2660,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 1);
@@ -2438,7 +2672,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_non_default_fallback +=
- (ds->dir_port == 60093 ?
+ (ds->ipv4_dirport == 60093 ?
1 : 0)
);
tt_int_op(found_non_default_fallback, OP_EQ, 1);
@@ -2450,7 +2684,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_default_fallback +=
- (ds->dir_port == 60099 ?
+ (ds->ipv4_dirport == 60099 ?
1 : 0)
);
tt_int_op(found_default_fallback, OP_EQ, 0);
@@ -2503,7 +2737,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 0);
@@ -2515,7 +2749,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 1);
@@ -2527,7 +2761,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 1);
@@ -2546,7 +2780,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 0);
@@ -2558,7 +2792,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 1);
@@ -2570,7 +2804,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 1);
@@ -2582,7 +2816,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_non_default_fallback +=
- (ds->dir_port == 60093 ?
+ (ds->ipv4_dirport == 60093 ?
1 : 0)
);
tt_int_op(found_non_default_fallback, OP_EQ, 0);
@@ -2594,7 +2828,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_default_fallback +=
- (ds->dir_port == 60099 ?
+ (ds->ipv4_dirport == 60099 ?
1 : 0)
);
tt_int_op(found_default_fallback, OP_EQ, 0);
@@ -2657,7 +2891,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 0);
@@ -2669,7 +2903,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 1);
@@ -2681,7 +2915,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 0);
@@ -2707,7 +2941,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 0);
@@ -2719,7 +2953,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 1);
@@ -2731,7 +2965,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 0);
@@ -2743,7 +2977,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_non_default_fallback +=
- (ds->dir_port == 60093 ?
+ (ds->ipv4_dirport == 60093 ?
1 : 0)
);
tt_int_op(found_non_default_fallback, OP_EQ, 1);
@@ -2755,7 +2989,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_default_fallback +=
- (ds->dir_port == 60099 ?
+ (ds->ipv4_dirport == 60099 ?
1 : 0)
);
tt_int_op(found_default_fallback, OP_EQ, 0);
@@ -2813,7 +3047,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 0);
@@ -2825,7 +3059,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 1);
@@ -2837,7 +3071,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 0);
@@ -2863,7 +3097,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 0);
@@ -2875,7 +3109,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 1);
@@ -2887,7 +3121,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 0);
@@ -2899,7 +3133,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_non_default_fallback +=
- (ds->dir_port == 60093 ?
+ (ds->ipv4_dirport == 60093 ?
1 : 0)
);
tt_int_op(found_non_default_fallback, OP_EQ, 0);
@@ -2911,7 +3145,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_default_fallback +=
- (ds->dir_port == 60099 ?
+ (ds->ipv4_dirport == 60099 ?
1 : 0)
);
tt_int_op(found_default_fallback, OP_EQ, 1);
@@ -2979,7 +3213,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 0);
@@ -2991,7 +3225,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 0);
@@ -3003,7 +3237,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 1);
@@ -3030,7 +3264,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 0);
@@ -3042,7 +3276,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 0);
@@ -3054,7 +3288,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 1);
@@ -3066,7 +3300,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_non_default_fallback +=
- (ds->dir_port == 60093 ?
+ (ds->ipv4_dirport == 60093 ?
1 : 0)
);
tt_int_op(found_non_default_fallback, OP_EQ, 1);
@@ -3078,7 +3312,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_default_fallback +=
- (ds->dir_port == 60099 ?
+ (ds->ipv4_dirport == 60099 ?
1 : 0)
);
tt_int_op(found_default_fallback, OP_EQ, 0);
@@ -3139,7 +3373,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 0);
@@ -3151,7 +3385,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 0);
@@ -3163,7 +3397,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 1);
@@ -3190,7 +3424,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 0);
@@ -3202,7 +3436,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 0);
@@ -3214,7 +3448,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 1);
@@ -3226,7 +3460,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_non_default_fallback +=
- (ds->dir_port == 60093 ?
+ (ds->ipv4_dirport == 60093 ?
1 : 0)
);
tt_int_op(found_non_default_fallback, OP_EQ, 0);
@@ -3238,7 +3472,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_default_fallback +=
- (ds->dir_port == 60099 ?
+ (ds->ipv4_dirport == 60099 ?
1 : 0)
);
tt_int_op(found_default_fallback, OP_EQ, 0);
@@ -3306,7 +3540,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 0);
@@ -3318,7 +3552,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 0);
@@ -3330,7 +3564,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 0);
@@ -3357,7 +3591,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 0);
@@ -3369,7 +3603,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 0);
@@ -3381,7 +3615,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 0);
@@ -3393,7 +3627,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_non_default_fallback +=
- (ds->dir_port == 60093 ?
+ (ds->ipv4_dirport == 60093 ?
1 : 0)
);
tt_int_op(found_non_default_fallback, OP_EQ, 1);
@@ -3405,7 +3639,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_default_fallback +=
- (ds->dir_port == 60099 ?
+ (ds->ipv4_dirport == 60099 ?
1 : 0)
);
tt_int_op(found_default_fallback, OP_EQ, 0);
@@ -3471,7 +3705,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 0);
@@ -3483,7 +3717,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 0);
@@ -3495,7 +3729,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 0);
@@ -3522,7 +3756,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_D0 +=
- (ds->dir_port == 60090 ?
+ (ds->ipv4_dirport == 60090 ?
1 : 0)
);
tt_int_op(found_D0, OP_EQ, 0);
@@ -3534,7 +3768,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_B1 +=
- (ds->dir_port == 60091 ?
+ (ds->ipv4_dirport == 60091 ?
1 : 0)
);
tt_int_op(found_B1, OP_EQ, 0);
@@ -3546,7 +3780,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_A2 +=
- (ds->dir_port == 60092 ?
+ (ds->ipv4_dirport == 60092 ?
1 : 0)
);
tt_int_op(found_A2, OP_EQ, 0);
@@ -3558,7 +3792,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_non_default_fallback +=
- (ds->dir_port == 60093 ?
+ (ds->ipv4_dirport == 60093 ?
1 : 0)
);
tt_int_op(found_non_default_fallback, OP_EQ, 0);
@@ -3570,7 +3804,7 @@ test_config_adding_dir_servers(void *arg)
ds,
/* increment the found counter if dir_port matches */
found_default_fallback +=
- (ds->dir_port == 60099 ?
+ (ds->ipv4_dirport == 60099 ?
1 : 0)
);
tt_int_op(found_default_fallback, OP_EQ, 1);
@@ -3649,16 +3883,17 @@ test_config_default_dir_servers(void *arg)
or_options_free(opts);
}
-static int mock_router_pick_published_address_result = 0;
+static bool mock_relay_find_addr_to_publish_result = true;
-static int
-mock_router_pick_published_address(const or_options_t *options,
- uint32_t *addr, int cache_only)
+static bool
+mock_relay_find_addr_to_publish(const or_options_t *options, int family,
+ int flags, tor_addr_t *addr_out)
{
- (void)options;
- (void)addr;
- (void)cache_only;
- return mock_router_pick_published_address_result;
+ (void) options;
+ (void) family;
+ (void) flags;
+ (void) addr_out;
+ return mock_relay_find_addr_to_publish_result;
}
static int mock_router_my_exit_policy_is_reject_star_result = 0;
@@ -3694,11 +3929,11 @@ test_config_directory_fetch(void *arg)
or_options_t *options = options_new();
routerinfo_t routerinfo;
memset(&routerinfo, 0, sizeof(routerinfo));
- mock_router_pick_published_address_result = -1;
+ mock_relay_find_addr_to_publish_result = false;
mock_router_my_exit_policy_is_reject_star_result = 1;
mock_advertised_server_mode_result = 0;
mock_router_get_my_routerinfo_result = NULL;
- MOCK(router_pick_published_address, mock_router_pick_published_address);
+ MOCK(relay_find_addr_to_publish, mock_relay_find_addr_to_publish);
MOCK(router_my_exit_policy_is_reject_star,
mock_router_my_exit_policy_is_reject_star);
MOCK(advertised_server_mode, mock_advertised_server_mode);
@@ -3747,27 +3982,6 @@ test_config_directory_fetch(void *arg)
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 1);
- /* OR servers only fetch the consensus from the authorities when they don't
- * know their own address, but never use multiple directories for bootstrap
- */
- or_options_free(options);
- options = options_new();
- options->ORPort_set = 1;
-
- mock_router_pick_published_address_result = -1;
- tt_assert(server_mode(options) == 1);
- tt_assert(public_server_mode(options) == 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(dirclient_fetches_from_authorities(options), OP_EQ, 0);
- tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
- OP_EQ, 0);
-
/* Exit OR servers only fetch the consensus from the authorities when they
* refuse unknown exits, but never use multiple directories for bootstrap
*/
@@ -3775,7 +3989,7 @@ test_config_directory_fetch(void *arg)
options = options_new();
options->ORPort_set = 1;
options->ExitRelay = 1;
- mock_router_pick_published_address_result = 0;
+ mock_relay_find_addr_to_publish_result = true;
mock_router_my_exit_policy_is_reject_star_result = 0;
mock_advertised_server_mode_result = 1;
mock_router_get_my_routerinfo_result = &routerinfo;
@@ -3790,7 +4004,7 @@ test_config_directory_fetch(void *arg)
OP_EQ, 0);
options->RefuseUnknownExits = 0;
- mock_router_pick_published_address_result = 0;
+ mock_relay_find_addr_to_publish_result = true;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
@@ -3807,11 +4021,11 @@ test_config_directory_fetch(void *arg)
options->DirPort_set = 1;
options->ORPort_set = 1;
options->DirCache = 1;
- mock_router_pick_published_address_result = 0;
+ mock_relay_find_addr_to_publish_result = true;
mock_router_my_exit_policy_is_reject_star_result = 1;
mock_advertised_server_mode_result = 1;
- routerinfo.dir_port = 1;
+ routerinfo.ipv4_dirport = 1;
mock_router_get_my_routerinfo_result = &routerinfo;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
@@ -3820,7 +4034,7 @@ test_config_directory_fetch(void *arg)
OP_EQ, 0);
mock_advertised_server_mode_result = 0;
- routerinfo.dir_port = 1;
+ routerinfo.ipv4_dirport = 1;
mock_router_get_my_routerinfo_result = &routerinfo;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
@@ -3837,7 +4051,7 @@ test_config_directory_fetch(void *arg)
OP_EQ, 0);
mock_advertised_server_mode_result = 1;
- routerinfo.dir_port = 0;
+ routerinfo.ipv4_dirport = 0;
routerinfo.supports_tunnelled_dir_requests = 0;
mock_router_get_my_routerinfo_result = &routerinfo;
tt_assert(server_mode(options) == 1);
@@ -3847,7 +4061,7 @@ test_config_directory_fetch(void *arg)
OP_EQ, 0);
mock_advertised_server_mode_result = 1;
- routerinfo.dir_port = 1;
+ routerinfo.ipv4_dirport = 1;
routerinfo.supports_tunnelled_dir_requests = 1;
mock_router_get_my_routerinfo_result = &routerinfo;
tt_assert(server_mode(options) == 1);
@@ -3858,7 +4072,7 @@ test_config_directory_fetch(void *arg)
done:
or_options_free(options);
- UNMOCK(router_pick_published_address);
+ UNMOCK(relay_find_addr_to_publish);
UNMOCK(router_get_my_routerinfo);
UNMOCK(advertised_server_mode);
UNMOCK(router_my_exit_policy_is_reject_star);
@@ -4696,7 +4910,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
port_cfg = (port_cfg_t *)smartlist_get(slout, 0);
tt_int_op(port_cfg->entry_cfg.session_group, OP_EQ, 1111122);
- // Test success with a zero unix domain socket, and doesnt add it to out
+ // Test success with a zero unix domain socket, and doesn't add it to out
config_free_lines(config_port_valid); config_port_valid = NULL;
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
@@ -4706,7 +4920,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 0);
- // Test success with a one unix domain socket, and doesnt add it to out
+ // Test success with a one unix domain socket, and doesn't add it to out
config_free_lines(config_port_valid); config_port_valid = NULL;
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
@@ -4949,6 +5163,44 @@ test_config_parse_port_config__ports__server_options(void *data)
0, CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
+ /* Default address is IPv4 but pass IPv6Only flag. Should be ignored. */
+ 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("ORPort", "9050 IPv6Only");
+ ret = port_parse_config(slout, config_port_invalid, "ORPort", 0,
+ "127.0.0.1", 0, CL_PORT_SERVER_OPTIONS);
+ tt_int_op(ret, OP_EQ, 0);
+
+ /* Default address is IPv6 but pass IPv4Only flag. Should be ignored. */
+ 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("ORPort", "9050 IPv4Only");
+ ret = port_parse_config(slout, config_port_invalid, "ORPort", 0,
+ "[::]", 0, CL_PORT_SERVER_OPTIONS);
+ tt_int_op(ret, OP_EQ, 0);
+
+ /* Explicit address is IPv6 but pass IPv4Only flag. Should error. */
+ 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("ORPort",
+ "[4242::4242]:9050 IPv4Only");
+ ret = port_parse_config(slout, config_port_invalid, "ORPort", 0,
+ "[::]", 0, CL_PORT_SERVER_OPTIONS);
+ tt_int_op(ret, OP_EQ, -1);
+
+ /* Explicit address is IPv4 but pass IPv6Only flag. Should error. */
+ 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("ORPort",
+ "1.2.3.4:9050 IPv6Only");
+ ret = port_parse_config(slout, config_port_invalid, "ORPort", 0,
+ "127.0.0.1", 0, CL_PORT_SERVER_OPTIONS);
+ tt_int_op(ret, OP_EQ, -1);
+
done:
if (slout)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
@@ -4968,17 +5220,17 @@ test_config_get_first_advertised(void *data)
const tor_addr_t *addr;
// no ports are configured? We get NULL.
- port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
+ port = portconf_get_first_advertised_port(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,
+ addr = portconf_get_first_advertised_addr(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,
+ port = portconf_get_first_advertised_port(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,
+ addr = portconf_get_first_advertised_addr(CONN_TYPE_OR_LISTENER,
AF_INET6);
tt_ptr_op(addr, OP_EQ, NULL);
@@ -4992,27 +5244,27 @@ test_config_get_first_advertised(void *data)
tt_assert(r == 0);
// UNSPEC gets us nothing.
- port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
+ port = portconf_get_first_advertised_port(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,
+ addr = portconf_get_first_advertised_addr(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,
+ port = portconf_get_first_advertised_port(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,
+ addr = portconf_get_first_advertised_addr(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,
+ port = portconf_get_first_advertised_port(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,
+ addr = portconf_get_first_advertised_addr(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");
@@ -5635,6 +5887,7 @@ test_config_include_flag_both_without(void *data)
done:
tor_free(errmsg);
+ config_free_all();
}
static void
@@ -5675,6 +5928,7 @@ test_config_include_flag_torrc_only(void *data)
tor_free(errmsg);
tor_free(path);
tor_free(dir);
+ config_free_all();
}
static void
@@ -5715,6 +5969,287 @@ test_config_include_flag_defaults_only(void *data)
tor_free(errmsg);
tor_free(path);
tor_free(dir);
+ config_free_all();
+}
+
+static void
+test_config_include_wildcards(void *data)
+{
+ (void)data;
+
+ char *temp = NULL, *folder = NULL;
+ config_line_t *result = NULL;
+ char *dir = tor_strdup(get_fname("test_include_wildcards"));
+ tt_ptr_op(dir, OP_NE, NULL);
+
+#ifdef _WIN32
+ tt_int_op(mkdir(dir), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
+#endif
+
+ tor_asprintf(&temp, "%s"PATH_SEPARATOR"%s", dir, "01_one.conf");
+ tt_int_op(write_str_to_file(temp, "Test 1\n", 0), OP_EQ, 0);
+ tor_free(temp);
+
+ tor_asprintf(&temp, "%s"PATH_SEPARATOR"%s", dir, "02_two.conf");
+ tt_int_op(write_str_to_file(temp, "Test 2\n", 0), OP_EQ, 0);
+ tor_free(temp);
+
+ tor_asprintf(&temp, "%s"PATH_SEPARATOR"%s", dir, "aa_three.conf");
+ tt_int_op(write_str_to_file(temp, "Test 3\n", 0), OP_EQ, 0);
+ tor_free(temp);
+
+ tor_asprintf(&temp, "%s"PATH_SEPARATOR"%s", dir, "foo");
+ tt_int_op(write_str_to_file(temp, "Test 6\n", 0), OP_EQ, 0);
+ tor_free(temp);
+
+ tor_asprintf(&folder, "%s"PATH_SEPARATOR"%s", dir, "folder");
+
+#ifdef _WIN32
+ tt_int_op(mkdir(folder), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(folder, 0700), OP_EQ, 0);
+#endif
+
+ tor_asprintf(&temp, "%s"PATH_SEPARATOR"%s", folder, "04_four.conf");
+ tt_int_op(write_str_to_file(temp, "Test 4\n", 0), OP_EQ, 0);
+ tor_free(temp);
+
+ tor_asprintf(&temp, "%s"PATH_SEPARATOR"%s", folder, "05_five.conf");
+ tt_int_op(write_str_to_file(temp, "Test 5\n", 0), OP_EQ, 0);
+ tor_free(temp);
+
+ char torrc_contents[1000];
+ int include_used;
+
+ // test pattern that matches no file
+ tor_snprintf(torrc_contents, sizeof(torrc_contents),
+ "%%include %s"PATH_SEPARATOR"not-exist*\n",
+ dir);
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used,
+ NULL), OP_EQ, 0);
+ tt_ptr_op(result, OP_EQ, NULL);
+ tt_int_op(include_used, OP_EQ, 1);
+ config_free_lines(result);
+
+#ifndef _WIN32
+ // test wildcard escaping
+ tor_snprintf(torrc_contents, sizeof(torrc_contents),
+ "%%include %s"PATH_SEPARATOR"\\*\n",
+ dir);
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used,
+ NULL), OP_EQ, -1);
+ tt_ptr_op(result, OP_EQ, NULL);
+ tt_int_op(include_used, OP_EQ, 1);
+ config_free_lines(result);
+#endif
+
+ // test pattern *.conf
+ tor_snprintf(torrc_contents, sizeof(torrc_contents),
+ "%%include %s"PATH_SEPARATOR"*.conf\n",
+ dir);
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used,
+ NULL), OP_EQ, 0);
+ tt_ptr_op(result, OP_NE, NULL);
+ tt_int_op(include_used, OP_EQ, 1);
+
+ int len = 0;
+ config_line_t *next;
+ char expected[10];
+ for (next = result; next != NULL; next = next->next) {
+ tor_snprintf(expected, sizeof(expected), "%d", len + 1);
+ tt_str_op(next->key, OP_EQ, "Test");
+ tt_str_op(next->value, OP_EQ, expected);
+ len++;
+ }
+ tt_int_op(len, OP_EQ, 3);
+ config_free_lines(result);
+
+ // test pattern that matches folder and files
+ tor_snprintf(torrc_contents, sizeof(torrc_contents),
+ "%%include %s"PATH_SEPARATOR"*\n",
+ dir);
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used,
+ NULL), OP_EQ, 0);
+ tt_ptr_op(result, OP_NE, NULL);
+ tt_int_op(include_used, OP_EQ, 1);
+
+ len = 0;
+ for (next = result; next != NULL; next = next->next) {
+ tor_snprintf(expected, sizeof(expected), "%d", len + 1);
+ tt_str_op(next->key, OP_EQ, "Test");
+ tt_str_op(next->value, OP_EQ, expected);
+ len++;
+ }
+ tt_int_op(len, OP_EQ, 6);
+ config_free_lines(result);
+
+ // test pattern ending in PATH_SEPARATOR, test linux path separator
+ tor_snprintf(torrc_contents, sizeof(torrc_contents),
+ "%%include %s/f*/\n",
+ dir);
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used,
+ NULL), OP_EQ, 0);
+ tt_ptr_op(result, OP_NE, NULL);
+ tt_int_op(include_used, OP_EQ, 1);
+
+ len = 0;
+ for (next = result; next != NULL; next = next->next) {
+ tor_snprintf(expected, sizeof(expected), "%d", len + 1 + 3);
+ tt_str_op(next->key, OP_EQ, "Test");
+ tt_str_op(next->value, OP_EQ, expected);
+ len++;
+ }
+ tt_int_op(len, OP_EQ, 2);
+ config_free_lines(result);
+
+ // test pattern with wildcards in folder and file
+ tor_snprintf(torrc_contents, sizeof(torrc_contents),
+ "%%include %s"PATH_SEPARATOR"*"PATH_SEPARATOR"*.conf\n",
+ dir);
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used,
+ NULL), OP_EQ, 0);
+ tt_ptr_op(result, OP_NE, NULL);
+ tt_int_op(include_used, OP_EQ, 1);
+
+ len = 0;
+ for (next = result; next != NULL; next = next->next) {
+ tor_snprintf(expected, sizeof(expected), "%d", len + 1 + 3);
+ tt_str_op(next->key, OP_EQ, "Test");
+ tt_str_op(next->value, OP_EQ, expected);
+ len++;
+ }
+ tt_int_op(len, OP_EQ, 2);
+ config_free_lines(result);
+
+ done:
+ config_free_lines(result);
+ tor_free(folder);
+ tor_free(temp);
+ tor_free(dir);
+}
+
+static void
+test_config_include_hidden(void *data)
+{
+ (void)data;
+
+ char *temp = NULL, *folder = NULL;
+ config_line_t *result = NULL;
+ char *dir = tor_strdup(get_fname("test_include_hidden"));
+ tt_ptr_op(dir, OP_NE, NULL);
+
+#ifdef _WIN32
+ tt_int_op(mkdir(dir), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
+#endif
+
+ tor_asprintf(&folder, "%s"PATH_SEPARATOR"%s", dir, ".dotdir");
+
+#ifdef _WIN32
+ tt_int_op(mkdir(folder), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(folder, 0700), OP_EQ, 0);
+#endif
+
+ tor_asprintf(&temp, "%s"PATH_SEPARATOR"%s", folder, ".dotfile");
+ tt_int_op(write_str_to_file(temp, "Test 1\n", 0), OP_EQ, 0);
+ tor_free(temp);
+
+ tor_asprintf(&temp, "%s"PATH_SEPARATOR"%s", folder, "file");
+ tt_int_op(write_str_to_file(temp, "Test 2\n", 0), OP_EQ, 0);
+ tor_free(temp);
+
+ char torrc_contents[1000];
+ int include_used;
+ int len = 0;
+ config_line_t *next;
+ char expected[10];
+
+ // test wildcards do not expand to dot folders (except for windows)
+ tor_snprintf(torrc_contents, sizeof(torrc_contents),
+ "%%include %s"PATH_SEPARATOR"*\n",
+ dir);
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used,
+ NULL), OP_EQ, 0);
+ tt_int_op(include_used, OP_EQ, 1);
+#ifdef _WIN32 // wildcard expansion includes dot files on Windows
+ for (next = result; next != NULL; next = next->next) {
+ tor_snprintf(expected, sizeof(expected), "%d", len + 2);
+ tt_str_op(next->key, OP_EQ, "Test");
+ tt_str_op(next->value, OP_EQ, expected);
+ len++;
+ }
+ tt_int_op(len, OP_EQ, 1);
+#else
+ tt_ptr_op(result, OP_EQ, NULL);
+#endif
+ config_free_lines(result);
+
+ // test wildcards match hidden folders when explicitly in the pattern
+ tor_snprintf(torrc_contents, sizeof(torrc_contents),
+ "%%include %s"PATH_SEPARATOR".*\n",
+ dir);
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used,
+ NULL), OP_EQ, 0);
+ tt_ptr_op(result, OP_NE, NULL);
+ tt_int_op(include_used, OP_EQ, 1);
+
+ len = 0;
+ for (next = result; next != NULL; next = next->next) {
+ tor_snprintf(expected, sizeof(expected), "%d", len + 2);
+ tt_str_op(next->key, OP_EQ, "Test");
+ tt_str_op(next->value, OP_EQ, expected);
+ len++;
+ }
+ tt_int_op(len, OP_EQ, 1);
+ config_free_lines(result);
+
+ // test hidden dir when explicitly included
+ tor_snprintf(torrc_contents, sizeof(torrc_contents),
+ "%%include %s"PATH_SEPARATOR".dotdir\n",
+ dir);
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used,
+ NULL), OP_EQ, 0);
+ tt_ptr_op(result, OP_NE, NULL);
+ tt_int_op(include_used, OP_EQ, 1);
+
+ len = 0;
+ for (next = result; next != NULL; next = next->next) {
+ tor_snprintf(expected, sizeof(expected), "%d", len + 2);
+ tt_str_op(next->key, OP_EQ, "Test");
+ tt_str_op(next->value, OP_EQ, expected);
+ len++;
+ }
+ tt_int_op(len, OP_EQ, 1);
+ config_free_lines(result);
+
+ // test hidden file when explicitly included
+ tor_snprintf(torrc_contents, sizeof(torrc_contents),
+ "%%include %s"PATH_SEPARATOR".dotdir"PATH_SEPARATOR".dotfile\n",
+ dir);
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used,
+ NULL), OP_EQ, 0);
+ tt_ptr_op(result, OP_NE, NULL);
+ tt_int_op(include_used, OP_EQ, 1);
+
+ len = 0;
+ for (next = result; next != NULL; next = next->next) {
+ tor_snprintf(expected, sizeof(expected), "%d", len + 1);
+ tt_str_op(next->key, OP_EQ, "Test");
+ tt_str_op(next->value, OP_EQ, expected);
+ len++;
+ }
+ tt_int_op(len, OP_EQ, 1);
+ config_free_lines(result);
+
+ done:
+ config_free_lines(result);
+ tor_free(folder);
+ tor_free(temp);
+ tor_free(dir);
}
static void
@@ -5846,7 +6381,7 @@ test_config_include_opened_file_list(void *data)
smartlist_t *opened_files = smartlist_new();
char *torrcd = NULL;
char *subfolder = NULL;
- char *path = NULL;
+ char *in_subfolder = NULL;
char *empty = NULL;
char *file = NULL;
char *dot = NULL;
@@ -5875,9 +6410,9 @@ test_config_include_opened_file_list(void *data)
tt_int_op(mkdir(subfolder, 0700), OP_EQ, 0);
#endif
- tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", subfolder,
+ tor_asprintf(&in_subfolder, "%s"PATH_SEPARATOR"%s", subfolder,
"01_file_in_subfolder");
- tt_int_op(write_str_to_file(path, "Test 1\n", 0), OP_EQ, 0);
+ tt_int_op(write_str_to_file(in_subfolder, "Test 1\n", 0), OP_EQ, 0);
tor_asprintf(&empty, "%s"PATH_SEPARATOR"%s", torrcd, "empty");
tt_int_op(write_str_to_file(empty, "", 0), OP_EQ, 0);
@@ -5908,13 +6443,69 @@ test_config_include_opened_file_list(void *data)
// dot files are not opened as we ignore them when we get their name from
// their parent folder
+ // test with wildcards
+ SMARTLIST_FOREACH(opened_files, char *, f, tor_free(f));
+ smartlist_clear(opened_files);
+ config_free_lines(result);
+ tor_snprintf(torrc_contents, sizeof(torrc_contents),
+ "%%include %s"PATH_SEPARATOR"*\n",
+ torrcd);
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used,
+ opened_files), OP_EQ, 0);
+ tt_ptr_op(result, OP_NE, NULL);
+ tt_int_op(include_used, OP_EQ, 1);
+
+#ifdef _WIN32
+ tt_int_op(smartlist_len(opened_files), OP_EQ, 6);
+#else
+ tt_int_op(smartlist_len(opened_files), OP_EQ, 5);
+#endif
+ tt_int_op(smartlist_contains_string(opened_files, torrcd), OP_EQ, 1);
+ tt_int_op(smartlist_contains_string(opened_files, subfolder), OP_EQ, 1);
+ // * will match the subfolder inside torrc.d, so it will be included
+ tt_int_op(smartlist_contains_string(opened_files, in_subfolder), OP_EQ, 1);
+ tt_int_op(smartlist_contains_string(opened_files, empty), OP_EQ, 1);
+ tt_int_op(smartlist_contains_string(opened_files, file), OP_EQ, 1);
+#ifdef _WIN32
+ // * matches the dot file on Windows
+ tt_int_op(smartlist_contains_string(opened_files, dot), OP_EQ, 1);
+#endif
+
+ // test with wildcards in folder and file
+ SMARTLIST_FOREACH(opened_files, char *, f, tor_free(f));
+ smartlist_clear(opened_files);
+ config_free_lines(result);
+ tor_snprintf(torrc_contents, sizeof(torrc_contents),
+ "%%include %s"PATH_SEPARATOR"*"PATH_SEPARATOR"*\n",
+ torrcd);
+ tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used,
+ opened_files), OP_EQ, 0);
+ tt_ptr_op(result, OP_NE, NULL);
+ tt_int_op(include_used, OP_EQ, 1);
+
+#ifdef _WIN32
+ tt_int_op(smartlist_len(opened_files), OP_EQ, 6);
+#else
+ tt_int_op(smartlist_len(opened_files), OP_EQ, 5);
+#endif
+ tt_int_op(smartlist_contains_string(opened_files, torrcd), OP_EQ, 1);
+ tt_int_op(smartlist_contains_string(opened_files, subfolder), OP_EQ, 1);
+ tt_int_op(smartlist_contains_string(opened_files, in_subfolder), OP_EQ, 1);
+ // stat is called on the following files, so they count as opened
+ tt_int_op(smartlist_contains_string(opened_files, empty), OP_EQ, 1);
+ tt_int_op(smartlist_contains_string(opened_files, file), OP_EQ, 1);
+#ifdef _WIN32
+ // * matches the dot file on Windows
+ tt_int_op(smartlist_contains_string(opened_files, dot), OP_EQ, 1);
+#endif
+
done:
SMARTLIST_FOREACH(opened_files, char *, f, tor_free(f));
smartlist_free(opened_files);
config_free_lines(result);
tor_free(torrcd);
tor_free(subfolder);
- tor_free(path);
+ tor_free(in_subfolder);
tor_free(empty);
tor_free(file);
tor_free(dot);
@@ -6243,9 +6834,169 @@ test_config_getinfo_config_names(void *arg)
tor_free(answer);
}
+static void
+test_config_duplicate_orports(void *arg)
+{
+ (void)arg;
+
+ config_line_t *config_port = NULL;
+ smartlist_t *ports = smartlist_new();
+
+ // Pretend that the user has specified an implicit 0.0.0.0:9050, an implicit
+ // [::]:9050, and an explicit on [::1]:9050.
+ config_line_append(&config_port, "ORPort", "9050"); // two implicit entries.
+ config_line_append(&config_port, "ORPort", "[::1]:9050");
+
+ // Parse IPv4, then IPv6.
+ port_parse_config(ports, config_port, "OR", CONN_TYPE_OR_LISTENER, "0.0.0.0",
+ 0, CL_PORT_SERVER_OPTIONS);
+ port_parse_config(ports, config_port, "OR", CONN_TYPE_OR_LISTENER, "[::]",
+ 0, CL_PORT_SERVER_OPTIONS);
+
+ /* There should be 4 ports at this point that is:
+ * - 0.0.0.0:9050
+ * - [::]:9050
+ * - [::1]:9050
+ * - [::1]:9050
+ */
+ tt_int_op(smartlist_len(ports), OP_EQ, 4);
+
+ /* This will remove the [::] and the extra [::1]. */
+ remove_duplicate_orports(ports);
+
+ tt_int_op(smartlist_len(ports), OP_EQ, 2);
+ tt_str_op(describe_relay_port(smartlist_get(ports, 0)), OP_EQ,
+ "ORPort 9050");
+ tt_str_op(describe_relay_port(smartlist_get(ports, 1)), OP_EQ,
+ "ORPort [::1]:9050");
+
+ /* Reset. Test different ORPort value. */
+ SMARTLIST_FOREACH(ports, port_cfg_t *, p, port_cfg_free(p));
+ smartlist_free(ports);
+ config_free_lines(config_port);
+ config_port = NULL;
+ ports = smartlist_new();
+
+ /* Implicit port and then specific IPv6 addresses but more than one. */
+ config_line_append(&config_port, "ORPort", "9050"); // two implicit entries.
+ config_line_append(&config_port, "ORPort", "[4242::1]:9051");
+ config_line_append(&config_port, "ORPort", "[4242::2]:9051");
+
+ // Parse IPv4, then IPv6.
+ port_parse_config(ports, config_port, "OR", CONN_TYPE_OR_LISTENER, "0.0.0.0",
+ 0, CL_PORT_SERVER_OPTIONS);
+ port_parse_config(ports, config_port, "OR", CONN_TYPE_OR_LISTENER, "[::]",
+ 0, CL_PORT_SERVER_OPTIONS);
+
+ /* There should be 6 ports at this point that is:
+ * - 0.0.0.0:9050
+ * - [::]:9050
+ * - [4242::1]:9051
+ * - [4242::1]:9051
+ * - [4242::2]:9051
+ * - [4242::2]:9051
+ */
+ tt_int_op(smartlist_len(ports), OP_EQ, 6);
+
+ /* This will remove the [::] and the duplicates. */
+ remove_duplicate_orports(ports);
+
+ /* We have four address here, 1 IPv4 on 9050, IPv6 on 9050, IPv6 on 9051 and
+ * a different IPv6 on 9051. */
+ tt_int_op(smartlist_len(ports), OP_EQ, 4);
+ tt_str_op(describe_relay_port(smartlist_get(ports, 0)), OP_EQ,
+ "ORPort 9050");
+ tt_str_op(describe_relay_port(smartlist_get(ports, 1)), OP_EQ,
+ "ORPort [4242::1]:9051");
+ tt_str_op(describe_relay_port(smartlist_get(ports, 2)), OP_EQ,
+ "ORPort [4242::2]:9051");
+ tt_str_op(describe_relay_port(smartlist_get(ports, 3)), OP_EQ,
+ "ORPort 9050");
+
+ /* Reset. Test different ORPort value. */
+ SMARTLIST_FOREACH(ports, port_cfg_t *, p, port_cfg_free(p));
+ smartlist_free(ports);
+ config_free_lines(config_port);
+ config_port = NULL;
+ ports = smartlist_new();
+
+ /* Three different ports. */
+ config_line_append(&config_port, "ORPort", "9050"); // two implicit entries.
+ config_line_append(&config_port, "ORPort", "[4242::1]:9051");
+ config_line_append(&config_port, "ORPort", "[4242::2]:9052");
+
+ // Parse IPv4, then IPv6.
+ port_parse_config(ports, config_port, "OR", CONN_TYPE_OR_LISTENER, "0.0.0.0",
+ 0, CL_PORT_SERVER_OPTIONS);
+ port_parse_config(ports, config_port, "OR", CONN_TYPE_OR_LISTENER, "[::]",
+ 0, CL_PORT_SERVER_OPTIONS);
+
+ /* There should be 6 ports at this point that is:
+ * - 0.0.0.0:9050
+ * - [::]:9050
+ * - [4242::1]:9051
+ * - [4242::1]:9051
+ * - [4242::2]:9052
+ * - [4242::2]:9052
+ */
+ tt_int_op(smartlist_len(ports), OP_EQ, 6);
+
+ /* This will remove the [::] and the duplicates. */
+ remove_duplicate_orports(ports);
+
+ /* We have four address here, 1 IPv4 on 9050, IPv6 on 9050, IPv6 on 9051 and
+ * IPv6 on 9052. */
+ tt_int_op(smartlist_len(ports), OP_EQ, 4);
+ tt_str_op(describe_relay_port(smartlist_get(ports, 0)), OP_EQ,
+ "ORPort 9050");
+ tt_str_op(describe_relay_port(smartlist_get(ports, 1)), OP_EQ,
+ "ORPort [4242::1]:9051");
+ tt_str_op(describe_relay_port(smartlist_get(ports, 2)), OP_EQ,
+ "ORPort [4242::2]:9052");
+ tt_str_op(describe_relay_port(smartlist_get(ports, 3)), OP_EQ,
+ "ORPort 9050");
+
+ done:
+ SMARTLIST_FOREACH(ports,port_cfg_t *,pf,port_cfg_free(pf));
+ smartlist_free(ports);
+ config_free_lines(config_port);
+}
+
+static void
+test_config_multifamily_port(void *arg)
+{
+ (void) arg;
+
+ config_line_t *config_port = NULL;
+ smartlist_t *ports = smartlist_new();
+
+ config_line_append(&config_port, "SocksPort", "9050");
+ config_line_append(&config_port, "SocksPort", "[::1]:9050");
+
+ // Parse IPv4, then IPv6.
+ port_parse_config(ports, config_port, "SOCKS", CONN_TYPE_AP_LISTENER,
+ "0.0.0.0", 9050, 0);
+
+ /* There should be 2 ports at this point that is:
+ * - 0.0.0.0:9050
+ * - [::1]:9050
+ */
+ tt_int_op(smartlist_len(ports), OP_EQ, 2);
+
+ done:
+ SMARTLIST_FOREACH(ports, port_cfg_t *, cfg, port_cfg_free(cfg));
+ smartlist_free(ports);
+ config_free_lines(config_port);
+}
+
+#ifndef COCCI
#define CONFIG_TEST(name, flags) \
{ #name, test_config_ ## name, flags, NULL, NULL }
+#define CONFIG_TEST_SETUP(suffix, name, flags, setup, setup_data) \
+ { #name#suffix, test_config_ ## name, flags, setup, setup_data }
+#endif
+
struct testcase_t config_tests[] = {
CONFIG_TEST(adding_trusted_dir_server, TT_FORK),
CONFIG_TEST(adding_fallback_dir_server, TT_FORK),
@@ -6256,7 +7007,11 @@ struct testcase_t config_tests[] = {
CONFIG_TEST(adding_dir_servers, TT_FORK),
CONFIG_TEST(default_dir_servers, TT_FORK),
CONFIG_TEST(default_fallback_dirs, 0),
- CONFIG_TEST(resolve_my_address, TT_FORK),
+ CONFIG_TEST_SETUP(_v4, find_my_address, TT_FORK,
+ &passthrough_setup, &addr_param_v4),
+ CONFIG_TEST_SETUP(_v6, find_my_address, TT_FORK,
+ &passthrough_setup, &addr_param_v6),
+ CONFIG_TEST(find_my_address_mixed, TT_FORK),
CONFIG_TEST(addressmap, 0),
CONFIG_TEST(parse_bridge_line, 0),
CONFIG_TEST(parse_transport_options_line, 0),
@@ -6289,6 +7044,8 @@ struct testcase_t config_tests[] = {
CONFIG_TEST(include_flag_both_without, TT_FORK),
CONFIG_TEST(include_flag_torrc_only, TT_FORK),
CONFIG_TEST(include_flag_defaults_only, TT_FORK),
+ CONFIG_TEST(include_wildcards, 0),
+ CONFIG_TEST(include_hidden, 0),
CONFIG_TEST(dup_and_filter, 0),
CONFIG_TEST(check_bridge_distribution_setting_not_a_bridge, TT_FORK),
CONFIG_TEST(check_bridge_distribution_setting_valid, 0),
@@ -6299,5 +7056,7 @@ struct testcase_t config_tests[] = {
CONFIG_TEST(extended_fmt, 0),
CONFIG_TEST(kvline_parse, 0),
CONFIG_TEST(getinfo_config_names, 0),
+ CONFIG_TEST(duplicate_orports, 0),
+ CONFIG_TEST(multifamily_port, 0),
END_OF_TESTCASES
};
diff --git a/src/test/test_confparse.c b/src/test/test_confparse.c
index 21301ce75e..abd53dea68 100644
--- a/src/test/test_confparse.c
+++ b/src/test/test_confparse.c
@@ -344,7 +344,7 @@ test_confparse_assign_deprecated(void *arg)
config_mgr_free(mgr);
}
-/* Try to re-assign an option name that has been depreacted in favor of
+/* Try to re-assign an option name that has been deprecated in favor of
* another. */
static void
test_confparse_assign_replaced(void *arg)
diff --git a/src/test/test_connection.c b/src/test/test_connection.c
index b1252864f5..cf5626ead7 100644
--- a/src/test/test_connection.c
+++ b/src/test/test_connection.c
@@ -10,6 +10,7 @@
#include "core/or/or.h"
#include "test/test.h"
+#include "app/config/config.h"
#include "app/config/or_options_st.h"
#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
@@ -883,10 +884,8 @@ mock_node_get_mutable_by_id(const char *digest)
test_node.ri = &node_ri;
memset(test_node.identity, 'c', sizeof(test_node.identity));
- tor_addr_t ipv4_addr;
- tor_addr_parse(&ipv4_addr, "18.0.0.1");
- node_ri.addr = tor_addr_to_ipv4h(&ipv4_addr);
- node_ri.or_port = 1;
+ tor_addr_parse(&node_ri.ipv4_addr, "18.0.0.1");
+ node_ri.ipv4_orport = 1;
return &test_node;
}
@@ -913,7 +912,8 @@ test_failed_orconn_tracker(void *arg)
/* Prepare the OR connection that will be used in this test */
or_connection_t or_conn;
- tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.real_addr, "18.0.0.1"));
+ tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.canonical_orport.addr,
+ "18.0.0.1"));
tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.base_.addr, "18.0.0.1"));
or_conn.base_.port = 1;
memset(or_conn.identity_digest, 'c', sizeof(or_conn.identity_digest));
@@ -964,6 +964,114 @@ test_failed_orconn_tracker(void *arg)
;
}
+static void
+test_conn_describe(void *arg)
+{
+ (void)arg;
+ or_options_t *options = get_options_mutable();
+ options->SafeLogging_ = SAFELOG_SCRUB_ALL;
+
+ // Let's start with a listener connection since they're simple.
+ connection_t *conn = connection_new(CONN_TYPE_OR_LISTENER, AF_INET);
+ tor_addr_parse(&conn->addr, "44.22.11.11");
+ conn->port = 80;
+ tt_str_op(connection_describe(conn), OP_EQ,
+ "OR listener connection (ready) on 44.22.11.11:80");
+ // If the address is unspec, we should still work.
+ tor_addr_make_unspec(&conn->addr);
+ tt_str_op(connection_describe(conn), OP_EQ,
+ "OR listener connection (ready) on <unset>:80");
+ // Try making the address null.
+ tor_addr_make_null(&conn->addr, AF_INET);
+ tt_str_op(connection_describe(conn), OP_EQ,
+ "OR listener connection (ready) on 0.0.0.0:80");
+ // What if the address is uninitialized? (This can happen if we log about the
+ // connection before we set the address.)
+ memset(&conn->addr, 0, sizeof(conn->addr));
+ tt_str_op(connection_describe(conn), OP_EQ,
+ "OR listener connection (ready) on <unset>:80");
+ connection_free_minimal(conn);
+
+ // Try a unix socket.
+ conn = connection_new(CONN_TYPE_CONTROL_LISTENER, AF_UNIX);
+ conn->address = tor_strdup("/a/path/that/could/exist");
+ tt_str_op(connection_describe(conn), OP_EQ,
+ "Control listener connection (ready) on /a/path/that/could/exist");
+ connection_free_minimal(conn);
+
+ // Try an IPv6 address.
+ conn = connection_new(CONN_TYPE_AP_LISTENER, AF_INET6);
+ tor_addr_parse(&conn->addr, "ff00::3");
+ conn->port = 9050;
+ tt_str_op(connection_describe(conn), OP_EQ,
+ "Socks listener connection (ready) on [ff00::3]:9050");
+ connection_free_minimal(conn);
+
+ // Now let's mess with exit connections. They have some special issues.
+ options->SafeLogging_ = SAFELOG_SCRUB_NONE;
+ conn = connection_new(CONN_TYPE_EXIT, AF_INET);
+ // If address and state are unset, we should say SOMETHING.
+ tt_str_op(connection_describe(conn), OP_EQ,
+ "Exit connection (uninitialized) to <unset> (DNS lookup pending)");
+ // Now suppose that the address is set but we haven't resolved the hostname.
+ conn->port = 443;
+ conn->address = tor_strdup("www.torproject.org");
+ conn->state = EXIT_CONN_STATE_RESOLVING;
+ tt_str_op(connection_describe(conn), OP_EQ,
+ "Exit connection (waiting for dest info) to "
+ "www.torproject.org:443 (DNS lookup pending)");
+ // Now give it a hostname!
+ tor_addr_parse(&conn->addr, "192.168.8.8");
+ conn->state = EXIT_CONN_STATE_OPEN;
+ tt_str_op(connection_describe(conn), OP_EQ,
+ "Exit connection (open) to 192.168.8.8:443");
+ // But what if safelogging is on?
+ options->SafeLogging_ = SAFELOG_SCRUB_RELAY;
+ tt_str_op(connection_describe(conn), OP_EQ,
+ "Exit connection (open) to [scrubbed]");
+ connection_free_minimal(conn);
+
+ // Now at last we look at OR addresses, which are complicated.
+ conn = connection_new(CONN_TYPE_OR, AF_INET6);
+ conn->state = OR_CONN_STATE_OPEN;
+ conn->port = 8080;
+ tor_addr_parse(&conn->addr, "[ffff:3333:1111::2]");
+ // This should get scrubbed, since the lack of a set ID means we might be
+ // talking to a client.
+ tt_str_op(connection_describe(conn), OP_EQ,
+ "OR connection (open) with [scrubbed]");
+ // But now suppose we aren't safelogging? We'll get the address then.
+ options->SafeLogging_ = SAFELOG_SCRUB_NONE;
+ tt_str_op(connection_describe(conn), OP_EQ,
+ "OR connection (open) with [ffff:3333:1111::2]:8080");
+ // Suppose we have an ID, so we know it isn't a client.
+ TO_OR_CONN(conn)->identity_digest[3] = 7;
+ options->SafeLogging_ = SAFELOG_SCRUB_RELAY; // back to safelogging.
+ tt_str_op(connection_describe(conn), OP_EQ,
+ "OR connection (open) with [ffff:3333:1111::2]:8080 "
+ "ID=<none> RSA_ID=0000000700000000000000000000000000000000");
+ // Add a 'canonical address' that is the same as the one we have.
+ tor_addr_parse(&TO_OR_CONN(conn)->canonical_orport.addr,
+ "[ffff:3333:1111::2]");
+ TO_OR_CONN(conn)->canonical_orport.port = 8080;
+ tt_str_op(connection_describe(conn), OP_EQ,
+ "OR connection (open) with [ffff:3333:1111::2]:8080 "
+ "ID=<none> RSA_ID=0000000700000000000000000000000000000000");
+ // Add a different 'canonical address'
+ tor_addr_parse(&TO_OR_CONN(conn)->canonical_orport.addr,
+ "[ffff:3333:1111::8]");
+ tt_str_op(connection_describe(conn), OP_EQ,
+ "OR connection (open) with [ffff:3333:1111::2]:8080 "
+ "ID=<none> RSA_ID=0000000700000000000000000000000000000000 "
+ "canonical_addr=[ffff:3333:1111::8]:8080");
+
+ // Clear identity_digest so that free_minimal won't complain.
+ memset(TO_OR_CONN(conn)->identity_digest, 0, DIGEST_LEN);
+
+ done:
+ connection_free_minimal(conn);
+}
+
#ifndef COCCI
#define CONNECTION_TESTCASE(name, fork, setup) \
{ #name, test_conn_##name, fork, &setup, NULL }
@@ -998,5 +1106,6 @@ struct testcase_t connection_tests[] = {
//CONNECTION_TESTCASE(func_suffix, TT_FORK, setup_func_pair),
{ "failed_orconn_tracker", test_failed_orconn_tracker, TT_FORK, NULL, NULL },
+ { "describe", test_conn_describe, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_consdiffmgr.c b/src/test/test_consdiffmgr.c
index 4bec6baeb0..f4adf43549 100644
--- a/src/test/test_consdiffmgr.c
+++ b/src/test/test_consdiffmgr.c
@@ -689,7 +689,7 @@ static void
test_consdiffmgr_cleanup_bad_valid_after(void *arg)
{
/* This will seem cleanable, but isn't, because its valid-after time is
- * misformed. */
+ * malformed. */
(void)arg;
config_line_t *labels = NULL;
diff --git a/src/test/test_controller.c b/src/test/test_controller.c
index a69ec17db8..49efeb5f88 100644
--- a/src/test/test_controller.c
+++ b/src/test/test_controller.c
@@ -19,6 +19,7 @@
#include "feature/rend/rendservice.h"
#include "feature/nodelist/authcert.h"
#include "feature/nodelist/nodelist.h"
+#include "feature/stats/rephist.h"
#include "test/test.h"
#include "test/test_helpers.h"
#include "lib/net/resolve.h"
@@ -2112,6 +2113,91 @@ test_control_getconf(void *arg)
smartlist_free(reply_strs);
}
+static int
+mock_rep_hist_get_circuit_handshake(uint16_t type)
+{
+ int ret;
+
+ switch (type) {
+ case ONION_HANDSHAKE_TYPE_NTOR:
+ ret = 80;
+ break;
+ case ONION_HANDSHAKE_TYPE_TAP:
+ ret = 86;
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+static void
+test_stats(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;
+
+ /* We need these for returning the (mock) rephist. */
+ MOCK(rep_hist_get_circuit_handshake_requested,
+ mock_rep_hist_get_circuit_handshake);
+ MOCK(rep_hist_get_circuit_handshake_assigned,
+ mock_rep_hist_get_circuit_handshake);
+
+ /* NTor tests */
+ getinfo_helper_rephist(&dummy, "stats/ntor/requested",
+ &answer, &errmsg);
+ tt_ptr_op(answer, OP_NE, NULL);
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ tt_str_op(answer, OP_EQ, "80");
+ tor_free(answer);
+ errmsg = NULL;
+
+ getinfo_helper_rephist(&dummy, "stats/ntor/assigned",
+ &answer, &errmsg);
+ tt_ptr_op(answer, OP_NE, NULL);
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ tt_str_op(answer, OP_EQ, "80");
+ tor_free(answer);
+ errmsg = NULL;
+
+ /* TAP tests */
+ getinfo_helper_rephist(&dummy, "stats/tap/requested",
+ &answer, &errmsg);
+ tt_ptr_op(answer, OP_NE, NULL);
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ tt_str_op(answer, OP_EQ, "86");
+ tor_free(answer);
+ errmsg = NULL;
+
+ getinfo_helper_rephist(&dummy, "stats/tap/assigned",
+ &answer, &errmsg);
+ tt_ptr_op(answer, OP_NE, NULL);
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ tt_str_op(answer, OP_EQ, "86");
+ tor_free(answer);
+ errmsg = NULL;
+
+ getinfo_helper_rephist(&dummy, "stats/tap/onion_circuits_ddosed",
+ &answer, &errmsg);
+ tt_ptr_op(answer, OP_EQ, NULL);
+ tt_str_op(errmsg, OP_EQ, "Unrecognized handshake type");
+ errmsg = NULL;
+
+ done:
+ UNMOCK(rep_hist_get_circuit_handshake_requested);
+ UNMOCK(rep_hist_get_circuit_handshake_assigned);
+ tor_free(answer);
+
+ return;
+}
+
#ifndef COCCI
#define PARSER_TEST(type) \
{ "parse/" #type, test_controller_parse_cmd, 0, &passthrough_setup, \
@@ -2146,5 +2232,6 @@ struct testcase_t controller_tests[] = {
{ "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 },
+ { "stats", test_stats, 0, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_controller_events.c b/src/test/test_controller_events.c
index 60dfbd630a..3cd529fa10 100644
--- a/src/test/test_controller_events.c
+++ b/src/test/test_controller_events.c
@@ -437,6 +437,33 @@ test_cntev_signal(void *arg)
}
static void
+test_cntev_log_fmt(void *arg)
+{
+ (void) arg;
+ char *result = NULL;
+#define CHECK(pre, post) \
+ do { \
+ result = tor_strdup((pre)); \
+ control_logmsg_strip_newlines(result); \
+ tt_str_op(result, OP_EQ, (post)); \
+ tor_free(result); \
+ } while (0)
+
+ CHECK("There is a ", "There is a");
+ CHECK("hello", "hello");
+ CHECK("", "");
+ CHECK("Put spaces at the end ", "Put spaces at the end");
+ CHECK(" ", "");
+ CHECK("\n\n\n", "");
+ CHECK("Testing\r\n", "Testing");
+ CHECK("T e s t\ni n g\n", "T e s t i n g");
+
+ done:
+ tor_free(result);
+#undef CHECK
+}
+
+static void
setup_orconn_state(orconn_state_msg_t *msg, uint64_t gid, uint64_t chan,
int proxy_type)
{
@@ -718,6 +745,7 @@ struct testcase_t controller_event_tests[] = {
TEST(event_mask, TT_FORK),
TEST(format_stream, TT_FORK),
TEST(signal, TT_FORK),
+ TEST(log_fmt, 0),
T_PUBSUB(dirboot_defer_desc, TT_FORK),
T_PUBSUB(dirboot_defer_orconn, TT_FORK),
T_PUBSUB(orconn_state, TT_FORK),
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index 0d75a212e9..ffd6a25bd5 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -2107,21 +2107,21 @@ test_crypto_curve25519_encode(void *arg)
{
curve25519_secret_key_t seckey;
curve25519_public_key_t key1, key2, key3;
- char buf[64];
+ char buf[64], buf_nopad[64];
(void)arg;
curve25519_secret_key_generate(&seckey, 0);
curve25519_public_key_generate(&key1, &seckey);
- curve25519_public_to_base64(buf, &key1);
+ curve25519_public_to_base64(buf, &key1, true);
tt_int_op(CURVE25519_BASE64_PADDED_LEN, OP_EQ, strlen(buf));
tt_int_op(0, OP_EQ, curve25519_public_from_base64(&key2, buf));
tt_mem_op(key1.public_key,OP_EQ, key2.public_key, CURVE25519_PUBKEY_LEN);
- buf[CURVE25519_BASE64_PADDED_LEN - 1] = '\0';
- tt_int_op(CURVE25519_BASE64_PADDED_LEN-1, OP_EQ, strlen(buf));
- tt_int_op(0, OP_EQ, curve25519_public_from_base64(&key3, buf));
+ curve25519_public_to_base64(buf_nopad, &key1, false);
+ tt_int_op(CURVE25519_BASE64_LEN, OP_EQ, strlen(buf_nopad));
+ tt_int_op(0, OP_EQ, curve25519_public_from_base64(&key3, buf_nopad));
tt_mem_op(key1.public_key,OP_EQ, key3.public_key, CURVE25519_PUBKEY_LEN);
/* Now try bogus parses. */
diff --git a/src/test/test_descriptors.inc b/src/test/test_descriptors.inc
index ecbccbd43a..445768e4bf 100644
--- a/src/test/test_descriptors.inc
+++ b/src/test/test_descriptors.inc
@@ -1,305 +1,431 @@
const char TEST_DESCRIPTORS[] =
-"@uploaded-at 2014-06-08 19:20:11\n"
-"@source \"127.0.0.1\"\n"
-"router test000a 127.0.0.1 5000 0 7000\n"
-"platform Tor 0.2.5.3-alpha-dev on Linux\n"
-"protocols Link 1 2 Circuit 1\n"
-"published 2014-06-08 19:20:11\n"
-"fingerprint C7E7 CCB8 179F 8CC3 7F5C 8A04 2B3A 180B 934B 14BA\n"
-"uptime 0\n"
-"bandwidth 1073741824 1073741824 0\n"
-"extra-info-digest 67A152A4C7686FB07664F872620635F194D76D95\n"
-"caches-extra-info\n"
-"onion-key\n"
-"-----BEGIN RSA PUBLIC KEY-----\n"
-"MIGJAoGBAOuBUIEBARMkkka/TGyaQNgUEDLP0KG7sy6KNQTNOlZHUresPr/vlVjo\n"
-"HPpLMfu9M2z18c51YX/muWwY9x4MyQooD56wI4+AqXQcJRwQfQlPn3Ay82uZViA9\n"
-"DpBajRieLlKKkl145KjArpD7F5BVsqccvjErgFYXvhhjSrx7BVLnAgMBAAE=\n"
-"-----END RSA PUBLIC KEY-----\n"
-"signing-key\n"
-"-----BEGIN RSA PUBLIC KEY-----\n"
-"MIGJAoGBAN6NLnSxWQnFXxqZi5D3b0BMgV6y9NJLGjYQVP+eWtPZWgqyv4zeYsqv\n"
-"O9y6c5lvxyUxmNHfoAbe/s8f2Vf3/YaC17asAVSln4ktrr3e9iY74a9RMWHv1Gzk\n"
-"3042nMcqj3PEhRN0PoLkcOZNjjmNbaqki6qy9bWWZDNTdo+uI44dAgMBAAE=\n"
-"-----END RSA PUBLIC KEY-----\n"
-"hidden-service-dir\n"
-"contact auth0@test.test\n"
-"ntor-onion-key pK4bs08ERYN591jj7ca17Rn9Q02TIEfhnjR6hSq+fhU=\n"
-"reject *:*\n"
-"router-signature\n"
-"-----BEGIN SIGNATURE-----\n"
-"rx88DuM3Y7tODlHNDDEVzKpwh3csaG1or+T4l2Xs1oq3iHHyPEtB6QTLYrC60trG\n"
-"aAPsj3DEowGfjga1b248g2dtic8Ab+0exfjMm1RHXfDam5TXXZU3A0wMyoHjqHuf\n"
-"eChGPgFNUvEc+5YtD27qEDcUjcinYztTs7/dzxBT4PE=\n"
-"-----END SIGNATURE-----\n"
-"@uploaded-at 2014-06-08 19:20:11\n"
-"@source \"127.0.0.1\"\n"
-"router test001a 127.0.0.1 5001 0 7001\n"
-"platform Tor 0.2.5.3-alpha-dev on Linux\n"
-"protocols Link 1 2 Circuit 1\n"
-"published 2014-06-08 19:20:11\n"
-"fingerprint 35DA 711C FC62 F88B C243 DE32 DC0B C28A 3F62 2610\n"
-"uptime 0\n"
-"bandwidth 1073741824 1073741824 0\n"
-"extra-info-digest 9E12278D6CF7608071FE98CE9DCEE48FA264518A\n"
-"caches-extra-info\n"
-"onion-key\n"
-"-----BEGIN RSA PUBLIC KEY-----\n"
-"MIGJAoGBAPbyUrorqoXMW4oezqd307ZGxgobqvQs2nb3TdQyWrwsHtJmS3utdrJS\n"
-"xJUZPNHOQ2hrDWW1VvevYqRTGeXGZr9TDZ3+t/gVUttqYRhuzzgEKVAZSsTo5ctO\n"
-"QNHnzJ6Xx/w/trhWqPTeJ7R0TCyAbWW7aE3KaKdwvZilRZp/oRUnAgMBAAE=\n"
-"-----END RSA PUBLIC KEY-----\n"
-"signing-key\n"
-"-----BEGIN RSA PUBLIC KEY-----\n"
-"MIGJAoGBALwOJ7XZHBnjJEuwF3Os6eashNbTH9YnH8TBZBdKgu3iFJYqDslcMIPX\n"
-"gWCJ9apPHyh1+/8OLRWeEYlwoZzgGi0rjm/+BNeOOmJbjfyjk97DuB9/2O5zr1BM\n"
-"CvOHqQSzMD+vz1ebvfM039a2mO8lXruUFPZQaFVxk8371XP2khqhAgMBAAE=\n"
-"-----END RSA PUBLIC KEY-----\n"
-"hidden-service-dir\n"
-"contact auth1@test.test\n"
-"ntor-onion-key t5bI1ksTdigOksMKRHUDwx/34ajEvDN1IpArOxIEWgk=\n"
-"reject *:*\n"
-"router-signature\n"
-"-----BEGIN SIGNATURE-----\n"
-"KtMW7A/pzu+np6aKJSy6d7drIb4yjz8SPCo+oQNxj2IqNHJir2O2nWu69xy+K0c1\n"
-"RL05KkcDaYzr5hC80FD1H+sTpGYD28SPkQkzPw+0pReSDl93pVXh0rU6Cdcm75FC\n"
-"t0UZzDt4TsMuFB0ZYpM3phKcQPpiDG6aR0LskL/YUvY=\n"
-"-----END SIGNATURE-----\n"
-"@uploaded-at 2014-06-08 19:20:11\n"
-"@source \"127.0.0.1\"\n"
-"router test004r 127.0.0.1 5004 0 7004\n"
-"platform Tor 0.2.5.3-alpha-dev on Linux\n"
-"protocols Link 1 2 Circuit 1\n"
-"published 2014-06-08 19:20:10\n"
-"fingerprint CC6A 48BD 52BD 9A2C 6670 5863 AC31 AE17 6E63 8B02\n"
-"uptime 0\n"
-"bandwidth 1073741824 1073741824 0\n"
-"extra-info-digest B5CC249CEF394B5AFCA0C77FA7D5605615FA487C\n"
-"onion-key\n"
-"-----BEGIN RSA PUBLIC KEY-----\n"
-"MIGJAoGBAMze36Hupy7HACcF3TMv5mJuZbx3d3cS0WYLl6vTeChBgpS5CEXq6zIu\n"
-"d31YmtUcxH6fOjDOudhbnXuoh1nH4CP+LocVHAdlGG1giAm7u8yZudVvVJiIqFgQ\n"
-"wVDcWx8LbGCi5P9J/ZPKAIVsSyS7xkOqHjz3VMo/uYLbQCFAwfkdAgMBAAE=\n"
-"-----END RSA PUBLIC KEY-----\n"
-"signing-key\n"
-"-----BEGIN RSA PUBLIC KEY-----\n"
-"MIGJAoGBAM/qGP365x6bH+ug7rKVy7V5lC9Ff2Jfk0wlTFIzzwn+DMSG6xDvulKe\n"
-"wcIzgGNdQu7qlKlQUif3GPMr0KSS32cRsmoRQJcsm9+lGUK871NyZ8AyrHT+LhyF\n"
-"cs718P0iN5yKF2FikNr727kEANCzvC1l9eP4qF5GGzsNtglbJ7bTAgMBAAE=\n"
-"-----END RSA PUBLIC KEY-----\n"
-"hidden-service-dir\n"
-"ntor-onion-key a9Pavqnx7DFhMWUO0d17qF9Py8+iie4FnxTHaTgfIXY=\n"
-"reject *:25\n"
-"reject *:119\n"
-"reject *:135-139\n"
-"reject *:445\n"
-"reject *:563\n"
-"reject *:1214\n"
-"reject *:4661-4666\n"
-"reject *:6346-6429\n"
-"reject *:6699\n"
-"reject *:6881-6999\n"
-"accept *:*\n"
-"router-signature\n"
-"-----BEGIN SIGNATURE-----\n"
-"HVW7kjBgEt+Qdvcrq+NQE1F9B8uV9D38KA2Bp6cYHLWCxL6N4GS8JQqbOEtnqaj7\n"
-"Vxrv7uy1Fzb15Zr+1sUVMxNv+LLRfr+JzfETMNYVkYDrNgr1cAAVEQzFWbIziond\n"
-"xMFp64yjEW9/I+82lb5GBZEiKdEd4QqWMmQosoYMTM8=\n"
-"-----END SIGNATURE-----\n"
-"@uploaded-at 2014-06-08 19:20:12\n"
-"@source \"127.0.0.1\"\n"
-"router test002a 127.0.0.1 5002 0 7002\n"
-"platform Tor 0.2.5.3-alpha-dev on Linux\n"
-"protocols Link 1 2 Circuit 1\n"
-"published 2014-06-08 19:20:11\n"
-"fingerprint 29C7 BBB6 C437 32D5 BDF1 5671 F5C5 F1FB 6E36 4B47\n"
-"uptime 0\n"
-"bandwidth 1073741824 1073741824 0\n"
-"extra-info-digest 9BB181EA86E0130680C3CC04AD7DE4C341ADC2C7\n"
-"caches-extra-info\n"
-"onion-key\n"
-"-----BEGIN RSA PUBLIC KEY-----\n"
-"MIGJAoGBALNH19oF8Ajf+djlH/g7L+enFBf5Wwjmf3bPwNKWZ9G+B+Lg8SpfhZiw\n"
-"rUqi7h21f45BV/dN05dK6leWD8rj1T9kuM9TKBOEZxIWeq7zbXihyu4XPxP4FNTS\n"
-"+0G7BhdP4biALENmeyLhUCZaw5Ic/jFkHT4gV9S0iVZiEDwC9twXAgMBAAE=\n"
-"-----END RSA PUBLIC KEY-----\n"
-"signing-key\n"
-"-----BEGIN RSA PUBLIC KEY-----\n"
-"MIGJAoGBALeyQGMQBHgTxpO/i30uHjflTm9MNi3ZBNcOKpvBXWYgY42qTqOZ7Uam\n"
-"c5pmZhTLrQ1W8XlGDw8Cl8ktZ0ylodLZyUNajBtJvSFWTb8iwdZsshW6Ahb8TyfI\n"
-"Y7MwTlQ/7xw4mj1NEaui6bwGgEZUs18RTqhDrUc2Mcj1Yf61Rq+7AgMBAAE=\n"
-"-----END RSA PUBLIC KEY-----\n"
-"hidden-service-dir\n"
-"contact auth2@test.test\n"
-"ntor-onion-key ukR41RjtiZ69KO0SrFTvL0LoZK/ZTT01FQWmCXTCUlE=\n"
-"reject *:*\n"
-"router-signature\n"
-"-----BEGIN SIGNATURE-----\n"
-"IY2s/RY4tdahrgfGG+vW7lOvpfofoxxSo7guGpSKGxVApiroCQtumoYifnnJ88G2\n"
-"K4IbxwEO8pgO8fnz1mibblUWw2vdDNjCifc1wtXJUE+ONA0UcLRlfQ94GbL8h2PG\n"
-"72z6i1+NN0QahXMk7MUbzI7bOXTJOiO8e2Zjk9vRnxI=\n"
-"-----END SIGNATURE-----\n"
-"@uploaded-at 2014-06-08 19:20:12\n"
-"@source \"127.0.0.1\"\n"
-"router test006r 127.0.0.1 5006 0 7006\n"
-"platform Tor 0.2.5.3-alpha-dev on Linux\n"
-"protocols Link 1 2 Circuit 1\n"
-"published 2014-06-08 19:20:11\n"
-"fingerprint 829B 3FAA A42B 605A EB0B F380 8F32 8ED1 73E7 0D25\n"
-"uptime 0\n"
-"bandwidth 1073741824 1073741824 0\n"
-"extra-info-digest 7ECB757002EB9B5838B13AE6F2357A5E585131B8\n"
-"onion-key\n"
-"-----BEGIN RSA PUBLIC KEY-----\n"
-"MIGJAoGBALsNBChcLVndlS4HNXL3hxBJVgXctATz6yXcJt3bkDB5cjv7Q9fqN3Ue\n"
-"j3SI1OUBx4YrLcSLD/hELHVilLrrfbaraAFfAsydlRLjTVcMRx5FFlDd0E7TAadc\n"
-"71CkTipNnjwqz1mTRKkEFeepnh/JaFDidY9ER1rMBA5JRyBvqrD9AgMBAAE=\n"
-"-----END RSA PUBLIC KEY-----\n"
-"signing-key\n"
-"-----BEGIN RSA PUBLIC KEY-----\n"
-"MIGJAoGBAPgipA8yLj1kqrMlAH7cK7IQEdmqmfNHGXdkYQ+TKtfLh0zeEIvvh9yh\n"
-"k+vKHS+HVoHo3tecB9QjJyDyyJTiETXCupSOY+ebG648JADAvv8v1WiE+KBXtjpl\n"
-"qgDTrDj5CwGuY6cvQdej5yg1UAVlMMZSg3thL3tCYtQbOq66lAlnAgMBAAE=\n"
-"-----END RSA PUBLIC KEY-----\n"
-"hidden-service-dir\n"
-"ntor-onion-key q02F3AQsCX7+zXNpfTqBF8O8lusPhRJpQVxOnBvbOwc=\n"
-"reject *:25\n"
-"reject *:119\n"
-"reject *:135-139\n"
-"reject *:445\n"
-"reject *:563\n"
-"reject *:1214\n"
-"reject *:4661-4666\n"
-"reject *:6346-6429\n"
-"reject *:6699\n"
-"reject *:6881-6999\n"
-"accept *:*\n"
-"router-signature\n"
-"-----BEGIN SIGNATURE-----\n"
-"L1fdgoN/eXgdzIIXO63W4yGoC9lRozMU+T0Fimhd/XFV8qxeUT83Vgf63vxLUHIb\n"
-"D4a80Wj7Pm4y5a766qLGXxlz2FYjCdkp070UpgZneB+VifUlFd/bNAjsiYTstBKM\n"
-"EI2L0mhl9d/7KK8vgtadHdX1z1u7QjyF6ccnzhfqeiY=\n"
-"-----END SIGNATURE-----\n"
-"@uploaded-at 2014-06-08 19:20:12\n"
-"@source \"127.0.0.1\"\n"
-"router test003r 127.0.0.1 5003 0 7003\n"
-"platform Tor 0.2.5.3-alpha-dev on Linux\n"
-"protocols Link 1 2 Circuit 1\n"
-"published 2014-06-08 19:20:11\n"
-"fingerprint 71FD 3A35 F705 8020 D595 B711 D52A 9A0A 99BB B467\n"
-"uptime 0\n"
-"bandwidth 1073741824 1073741824 0\n"
-"extra-info-digest 3796BE0A95B699595445DFD3453CA2074E75BCE8\n"
-"onion-key\n"
-"-----BEGIN RSA PUBLIC KEY-----\n"
-"MIGJAoGBAL44ctIioIfCYFzMTYNfK5qFAPGGUpsAFmS8pThQEY/tJU14+frJDBrC\n"
-"BkLvBs05Bw7xOUb0f2geiYGowBA6028smiq5HzTO7Kaga8vfV7AnANPX+n9cfHCr\n"
-"/2cMnKkT/GZzpdk0WbUw5Kc/G1ATIPFQHA8gZAi1fsSIDDn3GRV5AgMBAAE=\n"
-"-----END RSA PUBLIC KEY-----\n"
-"signing-key\n"
-"-----BEGIN RSA PUBLIC KEY-----\n"
-"MIGJAoGBALlPo5AI1mVTi+194yOSf40caoFlxSTfXt8KjGVa1dO/bpX7L3noOjYg\n"
-"goU4Aqim7BHmBWQDE/tZNTrchFoLQFHi9N4pv/0ND3sY904pzqGpe3FeTuU8P9Jg\n"
-"q2w3MeO3GwG8CJf4FOdSkgi8UKkJhOld4g4kViQbrFLXfdFvnT/zAgMBAAE=\n"
-"-----END RSA PUBLIC KEY-----\n"
-"hidden-service-dir\n"
-"ntor-onion-key qluYCRrsesOTkavCLnNK6H1ToywyDquCyYeP0h/qol4=\n"
-"reject *:25\n"
-"reject *:119\n"
-"reject *:135-139\n"
-"reject *:445\n"
-"reject *:563\n"
-"reject *:1214\n"
-"reject *:4661-4666\n"
-"reject *:6346-6429\n"
-"reject *:6699\n"
-"reject *:6881-6999\n"
-"accept *:*\n"
-"router-signature\n"
-"-----BEGIN SIGNATURE-----\n"
-"d09K7rW/OpVzoUpfZXJuJW7a+P4pROCOZTgvDUIy/Nv+EAjcYqv95PlJ8cAMqnn3\n"
-"1oQibRmmQwn0OmG5cB8NaZiueaVIRheGzHEM8rndpHn5oFXdFvV7KKjScvfuBbTk\n"
-"RYME8XyawRaqsEZnwirDDlZuiZOjdQs8bbGsko3grJE=\n"
-"-----END SIGNATURE-----\n"
-"@uploaded-at 2014-06-08 19:20:12\n"
-"@source \"127.0.0.1\"\n"
-"router test005r 127.0.0.1 5005 0 7005\n"
-"platform Tor 0.2.5.3-alpha-dev on Linux\n"
-"protocols Link 1 2 Circuit 1\n"
-"published 2014-06-08 19:20:11\n"
-"fingerprint EB6E 42ED E6BF 5EE0 19F5 EFC1 53AD 094C 1327 7B76\n"
-"uptime 0\n"
-"bandwidth 1073741824 1073741824 0\n"
-"extra-info-digest C031EE4E1AE826C1E3C4E21D81C961869E63F5D2\n"
-"onion-key\n"
-"-----BEGIN RSA PUBLIC KEY-----\n"
-"MIGJAoGBAMd9Fm4KTSjFDzEABPZ1fwBCC2DNgee6nAmlde8FRbCVfcIHRiJyv9YG\n"
-"h530yUJal3hBfiWwy/SBA4LDz1flNCEwJm81s3waj4T9c676dAOLPcnOcJM5SbaQ\n"
-"hYPDrIZLEZHAk+IoM+avKYYocwCJXwx6WTtsedF0wJBZ9mQAJERJAgMBAAE=\n"
-"-----END RSA PUBLIC KEY-----\n"
-"signing-key\n"
-"-----BEGIN RSA PUBLIC KEY-----\n"
-"MIGJAoGBAKT7ldhV43S1CgoER/pU0Rigf0NzcSy25DQJrMRQnNmXnL03Dwuv/Iu7\n"
-"dCjgg64odnvSkXHFhkbjGcg8aXikvfbMyZTbsD8NrrP6FS6pfgPgZD9W2TK7QdHI\n"
-"QXwx1IYaaJK4nDUNfJhjrclydEdxmHbO1nLG1aS0ypn/G0EBpOSnAgMBAAE=\n"
-"-----END RSA PUBLIC KEY-----\n"
-"hidden-service-dir\n"
-"ntor-onion-key umFmyRPA0dIsi0CFYCbGIPe2+OUkyslTkKKDEohjQQg=\n"
-"reject *:25\n"
-"reject *:119\n"
-"reject *:135-139\n"
-"reject *:445\n"
-"reject *:563\n"
-"reject *:1214\n"
-"reject *:4661-4666\n"
-"reject *:6346-6429\n"
-"reject *:6699\n"
-"reject *:6881-6999\n"
-"accept *:*\n"
-"router-signature\n"
-"-----BEGIN SIGNATURE-----\n"
-"JiXEbqPgDPWEb9DzCYINRXfmvMIc/IRtvshS8Vmmn7DW67TrTLKCEAnisGo92gMA\n"
-"bhxGb9G5Mxq/8YqGoqdI2Vp6tfKlz/9AmjHzFAo01y42gafXIdr1oUS2RimA8jfF\n"
-"hwfQkbG0FYEsJrH3EUa8sMhcjsEaohK/kgklMR7OgQY=\n"
-"-----END SIGNATURE-----\n"
-"@uploaded-at 2014-06-08 19:20:12\n"
-"@source \"127.0.0.1\"\n"
-"router test007r 127.0.0.1 5007 0 7007\n"
-"platform Tor 0.2.5.3-alpha-dev on Linux\n"
-"protocols Link 1 2 Circuit 1\n"
-"published 2014-06-08 19:20:11\n"
-"fingerprint DABD 2AAF 8C9F 3B71 7839 9C08 DCD8 CD9D 341D 0002\n"
-"uptime 0\n"
-"bandwidth 1073741824 1073741824 0\n"
-"extra-info-digest F80104A0DFFB4EB429325D41D1F71E5BF8C6C726\n"
-"onion-key\n"
-"-----BEGIN RSA PUBLIC KEY-----\n"
-"MIGJAoGBAL42fYAriR/JeB/9NpVq5Y5EEHca+ugIpaSdRfbopWDtFjXLEk2jmO5A\n"
-"KoAGIkTKDr7e9101x63H+0Nh/7w3uYs/WqTXEH8/1sHwe+0PY2HL0S6qhlOo6X54\n"
-"EfK0nDDBAWFOpyiAMHRk8JVikKb56+FVIhCJgi1RIbLIiUQK2/kxAgMBAAE=\n"
-"-----END RSA PUBLIC KEY-----\n"
-"signing-key\n"
-"-----BEGIN RSA PUBLIC KEY-----\n"
-"MIGJAoGBAKQj2U5hmB68V6NQBqD8DfIkJjovvM8t6nGfYpkT8ORsROnmgI5mjM38\n"
-"cmh5GIjY9RgoOWolLmsWQ4SXtS0FvrPft1M61UMTSHzlrEeuod5KenV7vGlX2TxT\n"
-"0DoA5TL9yY7CmxCk8CNRCtN/g7WocgIiP4KCIiEZ4VE6LIb6sxUnAgMBAAE=\n"
-"-----END RSA PUBLIC KEY-----\n"
-"hidden-service-dir\n"
-"ntor-onion-key 1UBS8rTlL39u9YxRJWhz+GTG1dS15VRi4au1i5qZOyI=\n"
-"reject *:25\n"
-"reject *:119\n"
-"reject *:135-139\n"
-"reject *:445\n"
-"reject *:563\n"
-"reject *:1214\n"
-"reject *:4661-4666\n"
-"reject *:6346-6429\n"
-"reject *:6699\n"
-"reject *:6881-6999\n"
-"accept *:*\n"
-"router-signature\n"
-"-----BEGIN SIGNATURE-----\n"
-"m7xHh+XPdLN+qcMLz1dBAEAmcdCFrtdseMHCc0FyAP2kXdayxqe3o2IOOHN++bTH\n"
-"Y5iHsZembsIJJ+D/d0YEKWKh42TUWCXBu0Gbfc4OcNuR6PFlTWO2wk7rDT3HOiFr\n"
-"pe3wJqZYkLxlBDamROAlMMRe71iag89H/4EulC18opw=\n"
-"-----END SIGNATURE-----\n";
+ "@uploaded-at 2020-10-13 13:27:09\n"
+ "@source \"127.0.0.1\"\n"
+ "router test001a 127.0.0.1 5001 0 7001\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABs1eAaaOTHiF5TNABkcl/U1x6qvlb8dyNBjuezXxF2wFLgrRAQAgBAD/a0Xx\n"
+ "SqkjrxcXc1h00vvkSqjNuGb4xYg1BZUoZnwegCQmxELY6fQ3m3EzYfSSl1tbP2u8\n"
+ "sN4SBJCsV7aRdoYebs80CnrsPiUecVdTwruODb+wAKqKSl3u7+qx8dd1yAI=\n"
+ "-----END ED25519 CERT-----\n"
+ "master-key-ed25519 /2tF8UqpI68XF3NYdNL75Eqozbhm+MWINQWVKGZ8HoA\n"
+ "or-address [::]:5001\n"
+ "platform Tor 0.4.5.0-alpha-dev on Linux\n"
+ "proto Cons=1-2 Desc=1-2 DirCache=1-2 FlowCtrl=1 HSDir=1-2 HSIntro=3-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Padding=2 Relay=1-3\n"
+ "published 2020-10-13 13:27:09\n"
+ "fingerprint 2403 20EC F589 C1F4 DC0B 864B 28AF 8113 59CE FD86\n"
+ "uptime 324426\n"
+ "bandwidth 1073741824 1073741824 640416\n"
+ "extra-info-digest FD0FEB6B7F99C2E9A3C98968F6FB2C61B1688760 FDt9yIgtRYfaANh+E7NV6MUAvOR7DcJIjjBkhGMN6Vs\n"
+ "caches-extra-info\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAOrByE3R1SqUkYLMDDB408uliYrBj860aKU0sbS9F9xmxFONB4xHP6uA\n"
+ "MyBgHQGL91N30yZxWKkdRiuKpCZafxLrflx20U/JTijJugNWPBcLXG7pTaJsL7LQ\n"
+ "61WRwo7md8X5zRhSGd8Pisq2Ru2yDrd0DNfoxy2CSLJX0DN9aw4xAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALb83qDqIq7U75NuDnzZL/A1YvxMp/YqoxtKd2GuCOMRpu+DLpEJfAkB\n"
+ "0o9IP+CeCkT3JPP2irY+WEw8gLU9bx2VfdK4sm59Q7G0gWcfYsvn3wb3q43e0LOf\n"
+ "KQ/HMkZ+sJwQ5sCteAhGqbr9XNBfRE0bT5pyEZGKNg3ufCd1c7MLAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "Mr8P5CTgWB/J84yzF/zY4tnQixbFyNBXi+KXBVvRmFRKBKtRRf7NYKDlXpTWA+yv\n"
+ "lyVzzKyVlSreRIZbmS/VZrS0adj8EL8VAGVg3l/7ZumKFRB0JSiVpidd2yu0K8/2\n"
+ "qENpmGQbFco+6tj8dsxr4HrPaV7UBDxwjDR/2HADiiI=\n"
+ "-----END CROSSCERT-----\n"
+ "ntor-onion-key-crosscert 0\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABs2OAf9rRfFKqSOvFxdzWHTS++RKqM24ZvjFiDUFlShmfB6AAFr/gG3LV3nx\n"
+ "pFWmVimT3w4a9RX4sihTdCQKtYIO2JTSUaBnBBCGWNKL/pgMq13Y+fUnrrltFprb\n"
+ "ts9KP+yi/QU=\n"
+ "-----END ED25519 CERT-----\n"
+ "hidden-service-dir\n"
+ "contact auth1@test.test\n"
+ "ntor-onion-key rrw3paBStz7xhguZJDdjl/Tcpqwgv4u37Zi1zJcVNFk\n"
+ "reject *:*\n"
+ "tunnelled-dir-server\n"
+ "router-sig-ed25519 pVC4W6LarfI5xgQIjwoizvHiU6HXf0P9t7M4nWQfYduzNuIk3KPDVxZWfm+r3QDMBVDSBc9yAmFVmxFi4PfeAg\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "KHkPXBETKq3xyIckAS8BfL5Numjx2f3wLxkkDbDtsJt4nhXuL3CyWwtQGGQOqo10\n"
+ "HJfxeV2FktxHjlW08BGp8/EwnOcHsJkKg2yOlJodYXln8ATsHaMDS6inllyACIfC\n"
+ "680xs6LMJlUh/7qjPK3if7ayD+vPDCh+5IXq4n4Rn3k=\n"
+ "-----END SIGNATURE-----\n"
+ "@uploaded-at 2020-10-13 13:27:10\n"
+ "@source \"127.0.0.1\"\n"
+ "router test002a 127.0.0.1 5002 0 7002\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABs1eAW2RVTJizfLKok8vZjvtdSQfTkjJbwuBJJah89MpjJJ1AQAgBAD7AE/p\n"
+ "ZVnOoor55N3BTseFvzTESbjQVJkMEw2jNMmkMUeolbJlRtsklLCMGjY9H79EFdY1\n"
+ "QamhpTz5AR4IyKdruX5SD+h8ovvWQK/pvVD20rI7Em6Qbg8OVvEPaZwxQwo=\n"
+ "-----END ED25519 CERT-----\n"
+ "master-key-ed25519 +wBP6WVZzqKK+eTdwU7Hhb80xEm40FSZDBMNozTJpDE\n"
+ "or-address [::]:5002\n"
+ "platform Tor 0.4.5.0-alpha-dev on Linux\n"
+ "proto Cons=1-2 Desc=1-2 DirCache=1-2 FlowCtrl=1 HSDir=1-2 HSIntro=3-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Padding=2 Relay=1-3\n"
+ "published 2020-10-13 13:27:10\n"
+ "fingerprint 1849 2918 5A95 1CF2 DDA7 C3B0 1ACB 32D7 360C C4BF\n"
+ "uptime 324427\n"
+ "bandwidth 1073741824 1073741824 776649\n"
+ "extra-info-digest 8CB745E0CD4FD3E7E22739124F8FE88840CAFF05 f+jRe7cLSC7bCBEQfHhVxWYZbu5MXsdqQbFRAFhUFNo\n"
+ "caches-extra-info\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALkdaGnfYPMk4Gb6tEM0VkAHvf52ETyxn/yz876JzmbBqhMRz7BGMUKX\n"
+ "et6pLXZRrL0TbYbDkESCkWvOj9nq6pyxwoYcBTNBo/w3kdDk/RlVlc0egrvXQPgO\n"
+ "O0XJ3qjfW88aCyW4pr1XPpiLedj7GAMkHLXKSjHptKvkMH8UBIWrAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANf2NRv0Si2EBM/Bt055XgLdUAHJhAu+kI9/EOfZbHf/hXeV/NAA8QJB\n"
+ "TsqoN/v1krBFTUUZmushA7SAYJk69SipJDzYEOg3ZaaPVGanrLh7hiMTemgKh5j1\n"
+ "6ABIbUfZz4GufalIUzyVxF7qUNF7xZgKBzmxR7eW3jSabrEFdrPFAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "Q8rGB57opO5DQrRdIO4EoUphDbRNhIIYzs43UeZk+BDxYkMdMSMcmj7JqemH2AC1\n"
+ "yjOKbjy14w1cVmGvlXzvOKAA3ylpF7c3UkLhaVurKBmiZKXtZaWLns744QSGUbog\n"
+ "erN+WT0syXaXXEZGr6pPDtK9NJld/nMBw8TBGwNL8nc=\n"
+ "-----END CROSSCERT-----\n"
+ "ntor-onion-key-crosscert 1\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABs2OAfsAT+llWc6iivnk3cFOx4W/NMRJuNBUmQwTDaM0yaQxANuEvTxfukyO\n"
+ "lPKM02Lzm0hIvhFmbEqmekfwrqYG+avRmAeDc8eStlm8CQBw7LRJE++MJgAHWh9r\n"
+ "1tB3DcJxiQU=\n"
+ "-----END ED25519 CERT-----\n"
+ "hidden-service-dir\n"
+ "contact auth2@test.test\n"
+ "ntor-onion-key /vAbEzRKRi0j/0mrhyKBdNMxR56xnzl6fQvtHT/QcAE\n"
+ "reject *:*\n"
+ "tunnelled-dir-server\n"
+ "router-sig-ed25519 yo7QljYNLR1qIYtRUO4j769qUiDAOk4ueL1XQWFWi+TIenwiBc55fgUFQZAg3wgEwPM37CUdMkAMWKA2CQgSCw\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "hYDgjk0GH3xiBOgAccLQntNTYWGmzEvjozZIfqh6IzJtAfZkqpg9O7xaEiMRmkwj\n"
+ "+BHuMHiLj9BIHrMAP89pW9SoK+UfQdzKEI6VLFz/Z3c7H9F2OHse5HVc01X0Z6w7\n"
+ "eCPEOYUid7JJuVcABnJjs5PDo81LLOzY3089xRepC+c=\n"
+ "-----END SIGNATURE-----\n"
+ "@uploaded-at 2020-10-13 13:27:12\n"
+ "@source \"127.0.0.1\"\n"
+ "router test000a 127.0.0.1 5000 0 7000\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABs1eAX4HwKEhOktiFqMiJKxeCjj6o9/7Q/2+ssa3coYnhbYaAQAgBAAaycSq\n"
+ "2pbQLnRy2Yn8wiUhsge+cD6Yq3e/Bgq8hgYgJzhFP3znXvYpZJ9dT1J+4G3ykeVE\n"
+ "RK0wTU8Utb/+2XfYbXoECmBlb0Hyb87gTsB20O/d1gBssxpIcrjXwyzh/wI=\n"
+ "-----END ED25519 CERT-----\n"
+ "master-key-ed25519 GsnEqtqW0C50ctmJ/MIlIbIHvnA+mKt3vwYKvIYGICc\n"
+ "or-address [::]:5000\n"
+ "platform Tor 0.4.5.0-alpha-dev on Linux\n"
+ "proto Cons=1-2 Desc=1-2 DirCache=1-2 FlowCtrl=1 HSDir=1-2 HSIntro=3-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Padding=2 Relay=1-3\n"
+ "published 2020-10-13 13:27:12\n"
+ "fingerprint F003 9DE0 BFF7 FCB9 F2AB BC3E 6936 9DC6 83B2 D429\n"
+ "uptime 324429\n"
+ "bandwidth 1073741824 1073741824 780830\n"
+ "extra-info-digest 6233C6BC8DAEE31AFBCD71C01C74B3EC7429F77F tEmOGBsYCTolEuqcAL6f4wpaVNn98Y/ONFyZUKxsRUY\n"
+ "caches-extra-info\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANLNgThrQ1xGSi/aV/pWQUwOe0uy/ITcU/MSng6orKp0yzzzXc8Ntjfi\n"
+ "EFXuD3aEk1lUgwOvRlO2xuiOoHAZNAmim6+h4OfBcFgTeRWbfSMOdaG6Fjvc62C8\n"
+ "JJ7kvQIsJoWyCN9QF9366dM8RWLGbzkJ1Ayq6FBcgx59zh6Du2w3AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMR2w3ESy+Nifvpvzx0ZlIaHzVa/prZIonYdGS95ZsCL8ImDUvPFswAq\n"
+ "Xf0DLF8bYMfaXQhnNsDsdyH4hlfEVrTua8ww06LPQaEw1qhC9gYfUxoHQ6s4f9yC\n"
+ "23KPMsw3MWnwdNspsVDjRgJlCH3JTWStNSB0TgHoRy3LYnKjzvldAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "A3PiP6XlMo9KAO+3Y9+znbqxSujOWNBJlgtQumqbTOCsnUp4tcZiqJx1Tnmd1pN5\n"
+ "ZPpiHl9Q4gJ7OcsgyRvNKHE1t0q+CSie5U5n70Zr6ygymcsfLGoV5E/wonmbRRyW\n"
+ "roEkTHQGXUtjZ6nWRGd6nhVcLCq/mfv2w7RWvkkEMyA=\n"
+ "-----END CROSSCERT-----\n"
+ "ntor-onion-key-crosscert 1\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABs2OARrJxKraltAudHLZifzCJSGyB75wPpird78GCryGBiAnADqu/a1EDc8r\n"
+ "SVN5RI6gC4nZRjPEg2kV4kPDTILGxTEDBfo8zwogr1gKWlclqFD4AVk/4W10hi+V\n"
+ "SRNLYyQfzgk=\n"
+ "-----END ED25519 CERT-----\n"
+ "hidden-service-dir\n"
+ "contact auth0@test.test\n"
+ "ntor-onion-key VLJF0ibPKRzAq/Qc9nCN9Eyv1JBk4EMBN9jQSQtxfGM\n"
+ "reject *:*\n"
+ "tunnelled-dir-server\n"
+ "router-sig-ed25519 +wqG2xtPPfF3Qg/xEvjxOXLjMr5NCX7muDM+sVUEXiPYpPkxxN39Y6XcSMYJf6KgmO5AmlU+7csL5OdQeENlAQ\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "q23Fmc55TMJhJW5bFN4BZKt5spInNdBtXIOj78WCpHheEY3LXs0LRiU5pOMQPIhR\n"
+ "BZ8lhToo72hZr0BErZqP0AAR+7yrKdvNKFp49opwfBCQAdw+a5UxvmCxyy2zebaW\n"
+ "UWHVtAUrohyct9Bd2Ji8mwohjRz/kxLAufUMtJVw1oE=\n"
+ "-----END SIGNATURE-----\n"
+ "@uploaded-at 2020-10-13 13:27:14\n"
+ "@source \"127.0.0.1\"\n"
+ "router test007r 127.0.0.1 5007 0 7007\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABs1eAYJYgXIkzMMOaM6v7/IOs5NUaPdVHwPgYWDTZ/3ju2vnAQAgBAAHB+2c\n"
+ "K3h4v+X4dzLh1Cl8U1hwUKBSmgE6KSE+oWeM6iZ8lEFJlMPA90v9hc1xnTe9zjjS\n"
+ "LkFWFIJcR3W54CJw56uTGcd0AcrCcJKph1tebIv+7y1Kz9i6SsZBpoWxcQI=\n"
+ "-----END ED25519 CERT-----\n"
+ "master-key-ed25519 BwftnCt4eL/l+Hcy4dQpfFNYcFCgUpoBOikhPqFnjOo\n"
+ "or-address [::]:5007\n"
+ "platform Tor 0.4.5.0-alpha-dev on Linux\n"
+ "proto Cons=1-2 Desc=1-2 DirCache=1-2 FlowCtrl=1 HSDir=1-2 HSIntro=3-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Padding=2 Relay=1-3\n"
+ "published 2020-10-13 13:27:14\n"
+ "fingerprint 53F5 0783 5270 D39A 1E47 62C6 8F5E D21F C5F7 F7E9\n"
+ "uptime 324431\n"
+ "bandwidth 1073741824 1073741824 777802\n"
+ "extra-info-digest CC5F5C9F98FEE42D36C186052C88F4AF08ABCE19 q9AA03Hu526wTSvrdqNdWIzjCr+OzUREXfO6HKF6/9s\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKHxn6yov5enz1uNzpMOtk74kEpwLvlcSmEGd0gwi3VPs6V64a9X15Ku\n"
+ "OD9TXWY4pcjXTGAUZ0IDEfLziAVpUUByVL7uMXD5Lm/5CoLEGgyBqsvAynK0JymR\n"
+ "uLJKkdKosR589jGyQpgb9yEk6n/VtlJUsTutsOgYgO/KFh/dmP/5AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAL5sykSg1TVaP0WNbydIhdC2fwBNkIlPv+wR9DbZ7+4b18vGmrQz8sgJ\n"
+ "ZpSyRmfe6jkZBOvPDPOLBCtU8+QptmPX6+w2AZhPXr8kpUfYRRrrnaWtMTzYKgmj\n"
+ "R/1lC29PWzDAl98TXid08H36jCUZwcbqrOmOBBQi6hzBOPz9syb7AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "CVKyWa+nJnimA22PG9+NMklfgCwWF8EUIhgbLNZAlnC16RHvwQsnAUeEs6frstin\n"
+ "UCZ84MXSntqn/Tore0Vs102BrSjv8uIFXaXEH8jRaLcDPeYJKyBXAOINtlVtc3Ze\n"
+ "faMUiR7X3cxZsoGJPeAYjLEKghIbEj2sMfWDqfTUeYk=\n"
+ "-----END CROSSCERT-----\n"
+ "ntor-onion-key-crosscert 1\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABs2OAQcH7ZwreHi/5fh3MuHUKXxTWHBQoFKaATopIT6hZ4zqACWhqDvK437I\n"
+ "OLfulZGKeyPcWCaMHjdYp9HByRW1xZhCV98maaTkpTCy7kGa0oaHGYl1hETMeIXN\n"
+ "1I8YTDv4pQM=\n"
+ "-----END ED25519 CERT-----\n"
+ "hidden-service-dir\n"
+ "ntor-onion-key vCYC3rCCj+emJh8uNnK3OcX2mRrgPWGgeka617QnGFM\n"
+ "accept *:*\n"
+ "tunnelled-dir-server\n"
+ "router-sig-ed25519 PnDFvJl9otq2sXsDkm023L9+VAftkADmn8ocYVU8z5UcpwQ/2ZrZOUBthWOgt+j7SuiOb6rDw4KT5zWNwSusDw\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "H+/0VaNq9cX7GGj8s1ZWaaoLEuocakqcvZOUB4XoL5qmN3TCPfLMUDGM56EMkrvx\n"
+ "bzR6/iUm8RAK5bVoPMynYm3iJW7xwvXg6W4qTSIxaTX9SnZh03+UfnyPE3uykkSa\n"
+ "8+JZ6F9kqabWhi4yKsZtHt64A0/F+jyR5CvXl1kdt40=\n"
+ "-----END SIGNATURE-----\n"
+ "@uploaded-at 2020-10-13 13:27:14\n"
+ "@source \"127.0.0.1\"\n"
+ "router test006r 127.0.0.1 5006 0 7006\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABs1eAaRBmBZIcRzdZXo2qSBLNy9nZXvSyCmVMTbs+SLH8ozAAQAgBAANeGA+\n"
+ "qbvQAb9cMCjnGewaWlVp3xFaV2EWHV/IVnRmJodgXot9/W1v/eyGjzJ5mxTLLzDQ\n"
+ "a68Ry1NrLeDBX3ERX9XjiZ8YUrQlqWz8HsSZYdMoH7fDpaBG7SONxuCVqAo=\n"
+ "-----END ED25519 CERT-----\n"
+ "master-key-ed25519 DXhgPqm70AG/XDAo5xnsGlpVad8RWldhFh1fyFZ0ZiY\n"
+ "or-address [::]:5006\n"
+ "platform Tor 0.4.5.0-alpha-dev on Linux\n"
+ "proto Cons=1-2 Desc=1-2 DirCache=1-2 FlowCtrl=1 HSDir=1-2 HSIntro=3-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Padding=2 Relay=1-3\n"
+ "published 2020-10-13 13:27:14\n"
+ "fingerprint A0E2 FA39 D23F BB97 0B56 0C53 3BD8 B16D 0E63 548B\n"
+ "uptime 324431\n"
+ "bandwidth 1073741824 1073741824 347136\n"
+ "extra-info-digest BF56A5D6A1DB3090F4FE6AA37D0C4F97732AE49C B92bY5UKX7LVqvxvI4KZDlST1VQ+gy9IOO4SYIKdMnY\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALyNFEPoUDXHUprDPXMIKWoCeWDo4ztVh6yHJQE8v88tc3WiuBt7ExBP\n"
+ "3Hjrh10/julakjsQWqB/8neJc7lJqdnQqFp0G8KhViwRaWgxiMAAfgq9kRB8UDPD\n"
+ "GpgVGrvBB4mY9REnLlAeDjPK+rJ2ww5TSDe7GP5SYJh/5jBIAmShAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANnUmF9BJ77e1Vc+sIN+gXO4FGb+NYeEkzg8yTjlUCu/8eQCmNLjwO2A\n"
+ "S9cnfeK8vD0l7EgiYQWRUZRR5aK06VLDDbLZ6O5Kbey4gibgRCkXj85SGBsV0upr\n"
+ "rmozECBg3RshdvD1nRrubUYIbDQd5rH+XTYn7O42QVRodHuBJP2DAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "MsINH4fEw+GMWeLSxxmHfpSas1KEaX1RD0oo5GdyJjRs5Q2+ieDiW0T0VVN0auAp\n"
+ "niJoPf8er4oDjuJPuUTzsfiZUxBjCiMgLigdwI7FLFhbL/7dgZFzF+2a/JoFKbGv\n"
+ "2LKrEl0B8DsyG5aoF5T45eY5cx6fFXOkQjvYDEJ8cyM=\n"
+ "-----END CROSSCERT-----\n"
+ "ntor-onion-key-crosscert 0\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABs2OAQ14YD6pu9ABv1wwKOcZ7BpaVWnfEVpXYRYdX8hWdGYmANmc1AEsD0I4\n"
+ "+PKxTbE3RgpP0aUxiRBaQ3GGIvWyNZsix1bE1As/Y4N1/Vtn57b0eMd2xLokeEvG\n"
+ "JTGrTHoELA0=\n"
+ "-----END ED25519 CERT-----\n"
+ "hidden-service-dir\n"
+ "ntor-onion-key 2OKE+7fTI/CKOZ4bzzfSuNaSBzsBNlyjg7PJhWaMMmw\n"
+ "accept *:*\n"
+ "tunnelled-dir-server\n"
+ "router-sig-ed25519 Ez2DIieIvjFe8tZt5P4yOGuNH5Nw2PO6dD0hLylGhnk/elmG4hxf+qBj6LHybos88TP2fAh0mwceomGoUQQZDg\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "dxOuYd7waHjZjfWMQwKWhJxrFA/z1dKwkAZSVwglSHCCD8EmAcuerxhTiEzmKJm1\n"
+ "areR0g1oNigVyQd8Y5gYam9lgLLM4vEyHVkRhgluzKBcWnwS1PAF4oYOvMxTqBuw\n"
+ "5dfhm58uU6h8/jeKL4J4VSNnYDwY6G4+YzOcQkU25sY=\n"
+ "-----END SIGNATURE-----\n"
+ "@uploaded-at 2020-10-13 13:27:14\n"
+ "@source \"127.0.0.1\"\n"
+ "router test004r 127.0.0.1 5004 0 7004\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABs1eATTDPEX+F/fXy60oU+qlU3kFPYm11GLFpGIkXJ3+ULD1AQAgBADBcugt\n"
+ "WlMsFJtdBOshhXHYNabLhZgnsHmlCrw6MR/qpwNL7TqsdPpsEvYKAuHSozOaof4V\n"
+ "4sy9Zd1NFvwOJLyp1QkErf4TXWDoMQUCir1AcPsj/AGDIGq48DFpZUZyego=\n"
+ "-----END ED25519 CERT-----\n"
+ "master-key-ed25519 wXLoLVpTLBSbXQTrIYVx2DWmy4WYJ7B5pQq8OjEf6qc\n"
+ "or-address [::]:5004\n"
+ "platform Tor 0.4.5.0-alpha-dev on Linux\n"
+ "proto Cons=1-2 Desc=1-2 DirCache=1-2 FlowCtrl=1 HSDir=1-2 HSIntro=3-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Padding=2 Relay=1-3\n"
+ "published 2020-10-13 13:27:14\n"
+ "fingerprint C763 47FA 498E 3929 F2AC 563C B958 1249 137F F656\n"
+ "uptime 324431\n"
+ "bandwidth 1073741824 1073741824 640261\n"
+ "extra-info-digest 93E7E827FA057EEACE951B7D3F26A1E8FCCBC12B sHuKfKSpRmXKocb79/PgbMfM7z6UcGbbgW3aQvQIuRE\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMFoSwvDavnsMuT8v5D9vcWATYziPOe6erYE1cWAKMLL6BIrqUhCKEIi\n"
+ "g2hKE7XeGypQURhtV/mkvx43N1NwMTzPlbkEtL1LdDmb1kKKxsQ0kSpX75yc6g8y\n"
+ "5aKLVjPBMRDk5+eszo0qHs/lOO+Pn0M5zBurWv6Jk12iN9ETMT6XAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAOLXEVTTTkEqg47/I/JqORoqg/2r1bCa4LjPMThE6HoyvNIJRhGIsS18\n"
+ "37PZ3YGdkVY6bMdJWed4r4DGoqGu4I5p0hjv7CeONbGjIa19R4shkSKxGw8Prrr7\n"
+ "jHHg4eaK2i6p2bRPpn6V5Z/dAmfKz70682uKakZSsCA5hUoBMVr5AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "ZO/f8nN9QYAm0O2SgaH5Zb9T6o5ibiKVC3N8nwzPzEA7xxli/OR81tCobHYoTDQt\n"
+ "ZYKZXLvH0LAmjdHVVOGYAyfQKR7Ig2djVQuB4VVf8ix31jpL8guUIG14IKI/XSnz\n"
+ "ZgHnGkAkhZC+Q+FHAc341DeSHBy9iZbwooXyuK+rfnM=\n"
+ "-----END CROSSCERT-----\n"
+ "ntor-onion-key-crosscert 0\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABs2OAcFy6C1aUywUm10E6yGFcdg1psuFmCeweaUKvDoxH+qnAJDQqV067Kgn\n"
+ "q56Hsi6zUgK87nX3ENuQuKtjl86uWq1QmpmMt259vMa/rouA61sglMDGsZ1YVgEC\n"
+ "yoUVkFxVkQM=\n"
+ "-----END ED25519 CERT-----\n"
+ "hidden-service-dir\n"
+ "ntor-onion-key XBpzf4GSuvJZ/PP0PM4ECNotP/VOtHcFimQ2COb+NGA\n"
+ "accept *:*\n"
+ "tunnelled-dir-server\n"
+ "router-sig-ed25519 fUGEaiokY5dyMBtQ7x6BWBKwsJC6MQVYfewSMiWagE+T8H2EY2Lww0yowQo0+40FIKSG4g6GNpSMvs1g0cYIAg\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "h/nND9oB+dIiHzm93xm2Fi9pemP4B5B5qJkyEJg/CcpitaXvugBIw1EOWMwqrsr2\n"
+ "x7ZyDz8gUp7WcXwhqbXlsLgSFT96RC4cBG6Qjvly0t+gvvcxG7RHV2ytJ7VlakyP\n"
+ "uENuwPYre230OfOjm5Jg+wFdlF6OMLphj2Yd7o48Xcw=\n"
+ "-----END SIGNATURE-----\n"
+ "@uploaded-at 2020-10-13 13:27:34\n"
+ "@source \"127.0.0.1\"\n"
+ "router test005r 127.0.0.1 5005 0 7005\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABs1eAfTuBhu6ypB5/9avDiY3qBzulkCvfYqbFN/ABk/o4xFcAQAgBAAnmWRG\n"
+ "rIvqpb4Kk3cThEiWAll4uDCO2Y46uNm9WG7AtPt4LG+XfktG3GAxv6aVQimwlyHc\n"
+ "1x2Lfm9KG3mWWj+hxnum4Z7873OE0B9l2Hg0YQZCW/PuHSWN0rspTvY5SgA=\n"
+ "-----END ED25519 CERT-----\n"
+ "master-key-ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n"
+ "or-address [::]:5005\n"
+ "platform Tor 0.4.5.0-alpha-dev on Linux\n"
+ "proto Cons=1-2 Desc=1-2 DirCache=1-2 FlowCtrl=1 HSDir=1-2 HSIntro=3-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Padding=2 Relay=1-3\n"
+ "published 2020-10-13 13:27:34\n"
+ "fingerprint D219 590A C951 3BCD EBBA 9AB7 2100 7A4C C01B BAE3\n"
+ "uptime 324451\n"
+ "bandwidth 1073741824 1073741824 637796\n"
+ "extra-info-digest 78E6D382BC826B95B4111554EEE7D541A32AAAA3 c61Onjpq+1S0TrdvoaOvGAxew6yfO+uHNhipbemQmgA\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n"
+ "83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n"
+ "nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANBzejGAwyPTPq2Gm03wpg3qICo0uDQau8opude2mW3eyxAqOqHzC8De\n"
+ "gRgbmn040vqe9gwvH4iaHpVeTxyDwQefbfULdq6bETmX3aSUj6LKBCqqcyuOJFQu\n"
+ "7M2QfNSfHtldUABpIaqFvEA3AV8qjOoUtauoFNJKMy7Wj2//S70VAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "pD3Nkkunt8zP6PO6H3uHT0t7xnorC7cY/KfF75mFB+90pHCD9f0Xdu3Pjrur/q23\n"
+ "PIKV3hdtdsODoJuoh8LPGNAjS5rO6HMCtHNDNunNOs69bvfaO0jThnurXmOpY0sW\n"
+ "eRfBeYN2KNgrN0B1eDejfPSr03dkFY48yoUDROv9EJQ=\n"
+ "-----END CROSSCERT-----\n"
+ "ntor-onion-key-crosscert 0\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABs2OASeZZEasi+qlvgqTdxOESJYCWXi4MI7Zjjq42b1YbsC0AKc5y5qYUYvw\n"
+ "VATtWkV9DVIZbZSb9mQP5pmNaqmX+DbmINCYt8j7l+U7g3ftUyh0Wlrgevx0pFUI\n"
+ "RcIU0HKHZQA=\n"
+ "-----END ED25519 CERT-----\n"
+ "hidden-service-dir\n"
+ "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA\n"
+ "accept *:*\n"
+ "tunnelled-dir-server\n"
+ "router-sig-ed25519 Xm56dYbo/hCHWyzcdUPmfTeZ4qly2TYf1/2Q1lXKQDMJyBti8ZE8R2TTYsYimr+UtAapbzBItccZLze505nhBw\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "bbeN0lq6nCfJQXGcKa1M9TQ6b2upig7clrlVXuzKeR0JhGwnDCXUAFxDtrw3vkVo\n"
+ "ExBXXvJeBPyustFOQkdiAEWHHSW5CwEgeVCBYZeEnaiySIgDVKuu+9B53ezFdC0Y\n"
+ "iFJkKxxDx7ksxX0zdl7aPT4ORFEuRhCYS6el7YJmoyg=\n"
+ "-----END SIGNATURE-----\n"
+ "@uploaded-at 2020-10-13 13:28:13\n"
+ "@source \"127.0.0.1\"\n"
+ "router test003r 127.0.0.1 5003 0 7003\n"
+ "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQQABs1eAUC9IBXmVO3yeYhG6VI5o6+uyPI8tNFBR38n8RDxW91MAQAgBAD6reoi\n"
+ "ucfyRvLfC++3TyajT1IHbggd8/D5Gp9DlzbDf4vRNbII2iCDxilKG60yNurDcDWA\n"
+ "W9H2JRwrZpiQgQvEzGQJRISaGHQIVlEKpER7RvjDZvQG9KtHyDdH0txcdgo=\n"
+ "-----END ED25519 CERT-----\n"
+ "master-key-ed25519 +q3qIrnH8kby3wvvt08mo09SB24IHfPw+RqfQ5c2w38\n"
+ "or-address [::]:5003\n"
+ "platform Tor 0.4.5.0-alpha-dev on Linux\n"
+ "proto Cons=1-2 Desc=1-2 DirCache=1-2 FlowCtrl=1 HSDir=1-2 HSIntro=3-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Padding=2 Relay=1-3\n"
+ "published 2020-10-13 13:28:13\n"
+ "fingerprint 09C5 1D0C D3F4 F3D5 8C73 D219 9BF3 F0FC 55F5 2965\n"
+ "uptime 324490\n"
+ "bandwidth 1073741824 1073741824 640359\n"
+ "extra-info-digest 64AD921120758875124DEBC83808AE282BEA76F6 6xEyhjSnACEk+bScEqhoTI43p4+bcnFh8E+9fvBdeow\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANQMTqT/mcGSnwA7MsqKrtmK0re+XsJesFNeRwozZLKLgsB0ARoHvlAp\n"
+ "iBb/9kU++GhRBUs3EsMaU7rHN+yahDzwrVlWgRm3YV17aj1guQnHm8RaTbDtKCii\n"
+ "G0aBo2quU1LqXot/XVOE2BCFO0DO+4tZE5mCChpnALy0AYs2Dj4HAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAJ2yCCvgp0/HYyvW+DIX+nMEZ8Q1Sjzke9oEVcx1UQKFDmCCRJA4cJA5\n"
+ "xx5hVedkIXug7DJ/2xkMR+QT+Cwqxij1K0jlJlOmnixsT/TnwyyhP6eIxNef0HuG\n"
+ "MAgptAEMltR9OqDEESvfGv0cz+U4fru6xHpfH9c/P4S3aeihUbSnAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "UaR88eoWRuFJjYqns3RP92bgZv5AKYjxNrcm0SpZIOgDeayq/1mDA/jdVbDPa4de\n"
+ "KRJ9ezXCo+2O2zl6rhvsRsMgVwrZEr5Hz4+Zf1H6hpvk8NoOEBCb5g3jef6nMmGr\n"
+ "1p+NV/OULow266pKnWidPQCWLjc+ladBLQU8EJxT65Q=\n"
+ "-----END CROSSCERT-----\n"
+ "ntor-onion-key-crosscert 1\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "AQoABs2OAfqt6iK5x/JG8t8L77dPJqNPUgduCB3z8Pkan0OXNsN/AGVx0xPqhPuo\n"
+ "n9nnmtt+48y9Wkcdo43Si3Nrl96TxAiOMB0NKoTIk7++puAreR364CBPM8LM0TrT\n"
+ "AxIjl/GuMQE=\n"
+ "-----END ED25519 CERT-----\n"
+ "hidden-service-dir\n"
+ "ntor-onion-key bLeD2EdnozYyTnxk9PeRykzjPEw65lVLmlBhWk5+ATI\n"
+ "accept *:*\n"
+ "tunnelled-dir-server\n"
+ "router-sig-ed25519 wGsA4xlKdM0rzborPOil8cvAzUS2ImXvsm9PgTQDiosGf8ve3ucdDUjKLNOTd6iFVDIl4ESG2Y3eOsqAgQddBA\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "k8ndhNl9lCng7IfgeoYGWKnvmxgfo41M9Sq3754HUAVRJcVZ1RJm4OGI/Z/fw38I\n"
+ "ievnndu81y/L2cuHnSr+MTXY7B2pLXueOo8YpKlx799Wugn5dnfOhz9WHkFNhWQL\n"
+ "8iOty3iG3VIJVi0pU3qgj5Xc1zKVa3pZ/QQfs4k/g44=\n"
+ "-----END SIGNATURE-----\n";
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 3a0b8237cb..d62dd3fb9e 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -29,6 +29,7 @@
#include "lib/confmgt/confmgt.h"
#include "core/mainloop/connection.h"
#include "core/or/relay.h"
+#include "core/or/protover.h"
#include "core/or/versions.h"
#include "feature/client/bridges.h"
#include "feature/client/entrynodes.h"
@@ -100,6 +101,14 @@
#include <unistd.h>
#endif
+static void setup_ei_digests(void);
+static uint8_t digest_ei_minimal[20];
+static uint8_t digest_ei_bad_nickname[20];
+static uint8_t digest_ei_maximal[20];
+static uint8_t digest_ei_bad_tokens[20];
+static uint8_t digest_ei_bad_sig2[20];
+static uint8_t digest_ei_bad_published[20];
+
static networkstatus_t *
networkstatus_parse_vote_from_string_(const char *s,
const char **eos_out,
@@ -203,9 +212,9 @@ basic_routerinfo_new(const char *nickname, uint32_t ipv4_addr,
r1->nickname = tor_strdup(nickname);
r1->platform = tor_strdup(platform);
- r1->addr = ipv4_addr;
- r1->or_port = or_port;
- r1->dir_port = dir_port;
+ tor_addr_from_ipv4h(&r1->ipv4_addr, ipv4_addr);
+ r1->ipv4_orport = or_port;
+ r1->ipv4_dirport = dir_port;
r1->supports_tunnelled_dir_requests = 1;
router_set_rsa_onion_pkey(pk1, &r1->onion_pkey, &r1->onion_pkey_len);
@@ -216,6 +225,7 @@ basic_routerinfo_new(const char *nickname, uint32_t ipv4_addr,
r1->bandwidthcapacity = bandwidthcapacity;
r1->cache_info.published_on = published_on;
+ r1->protocol_list = tor_strdup(protover_get_supported_protocols());
if (rsa_onion_keypair_out) {
*rsa_onion_keypair_out = pk1;
@@ -236,8 +246,8 @@ get_new_router_line(const routerinfo_t *r1)
tor_asprintf(&line,
"router %s %s %d 0 %d\n",
- r1->nickname, fmt_addr32(r1->addr),
- r1->or_port, r1->dir_port);
+ r1->nickname, fmt_addr(&r1->ipv4_addr),
+ r1->ipv4_orport, r1->ipv4_dirport);
tor_assert(line);
return line;
@@ -397,18 +407,14 @@ get_new_ntor_onion_key_line(const curve25519_public_key_t *ntor_onion_pubkey)
{
char *line = NULL;
char cert_buf[256];
- int rv = 0;
tor_assert(ntor_onion_pubkey);
- rv = base64_encode(cert_buf, sizeof(cert_buf),
- (const char*)ntor_onion_pubkey->public_key, 32,
- BASE64_ENCODE_MULTILINE);
- tor_assert(rv > 0);
+ curve25519_public_to_base64(cert_buf, ntor_onion_pubkey, false);
tor_assert(strlen(cert_buf) > 0);
tor_asprintf(&line,
- "ntor-onion-key %s",
+ "ntor-onion-key %s\n",
cert_buf);
tor_assert(line);
@@ -437,13 +443,6 @@ mock_get_configured_ports(void)
return mocked_configured_ports;
}
-static tor_cert_t *
-mock_tor_cert_dup_null(const tor_cert_t *cert)
-{
- (void)cert;
- return NULL;
-}
-
static crypto_pk_t *mocked_server_identitykey = NULL;
/* Returns mocked_server_identitykey with no checks. */
@@ -638,9 +637,9 @@ 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); \
+ tt_assert(tor_addr_eq(&rp1->ipv4_addr, &r1->ipv4_addr)); \
+ tt_int_op(rp1->ipv4_orport,OP_EQ, r1->ipv4_orport); \
+ tt_int_op(rp1->ipv4_dirport,OP_EQ, r1->ipv4_dirport); \
tt_int_op(rp1->bandwidthrate,OP_EQ, r1->bandwidthrate); \
tt_int_op(rp1->bandwidthburst,OP_EQ, r1->bandwidthburst); \
tt_int_op(rp1->bandwidthcapacity,OP_EQ, r1->bandwidthcapacity); \
@@ -668,211 +667,6 @@ STMT_BEGIN \
tt_str_op(e1->nickname, OP_EQ, r1->nickname); \
STMT_END
-/** Run unit tests for router descriptor generation logic for a RSA-only
- * router. Tor versions without ed25519 (0.2.6 and earlier) are no longer
- * officially supported, but the authorities still accept their descriptors.
- */
-static void
-test_dir_formats_rsa(void *arg)
-{
- char *buf = NULL;
- char *buf2 = NULL;
- char *cp = NULL;
-
- uint8_t *rsa_cc = NULL;
-
- routerinfo_t *r1 = NULL;
- extrainfo_t *e1 = NULL;
- routerinfo_t *rp1 = NULL;
- extrainfo_t *ep1 = NULL;
-
- smartlist_t *chunks = NULL;
- const char *msg = NULL;
- int rv = -1;
-
- or_options_t *options = get_options_mutable();
- setup_dir_formats_options((const char *)arg, options);
-
- hibernate_set_state_for_testing_(HIBERNATE_STATE_LIVE);
-
- /* r1 is a minimal, RSA-only descriptor, with DirPort and IPv6 */
- r1 = basic_routerinfo_new("Magri", 0xc0a80001u /* 192.168.0.1 */,
- 9000, 9003,
- 1000, 5000, 10000,
- 0,
- NULL);
-
- /* Fake just enough of an ntor key to get by */
- curve25519_keypair_t r1_onion_keypair;
- curve25519_keypair_generate(&r1_onion_keypair, 0);
- r1->onion_curve25519_pkey = tor_memdup(&r1_onion_keypair.pubkey,
- sizeof(curve25519_public_key_t));
-
- /* Now add IPv6 */
- tor_addr_parse(&r1->ipv6_addr, "1:2:3:4::");
- r1->ipv6_orport = 9999;
-
- r1->exit_policy = NULL;
-
- /* XXXX+++ router_dump_to_string should really take this from ri. */
- options->ContactInfo = tor_strdup("Magri White "
- "<magri@elsewhere.example.com>");
-
- setup_mock_configured_ports(r1->or_port, r1->dir_port);
-
- buf = router_dump_router_to_string(r1, r1->identity_pkey, NULL, NULL, NULL);
- tt_assert(buf);
-
- tor_free(options->ContactInfo);
- cleanup_mock_configured_ports();
-
- /* Synthesise a router descriptor, without the signature */
- chunks = smartlist_new();
-
- smartlist_add(chunks, get_new_router_line(r1));
- smartlist_add_strdup(chunks, "or-address [1:2:3:4::]:9999\n");
-
- smartlist_add(chunks, get_new_platform_line());
- smartlist_add(chunks, get_new_published_line(r1));
- smartlist_add(chunks, get_new_fingerprint_line(r1));
-
- smartlist_add(chunks, get_new_uptime_line(0));
- smartlist_add(chunks, get_new_bandwidth_line(r1));
-
- smartlist_add(chunks, get_new_onion_key_block(r1));
- smartlist_add(chunks, get_new_signing_key_block(r1));
-
- smartlist_add_strdup(chunks, "hidden-service-dir\n");
-
- smartlist_add_strdup(chunks, "contact Magri White "
- "<magri@elsewhere.example.com>\n");
-
- smartlist_add(chunks, get_new_bridge_distribution_request_line(options));
- smartlist_add(chunks, get_new_ntor_onion_key_line(&r1_onion_keypair.pubkey));
- smartlist_add_strdup(chunks, "reject *:*\n");
- smartlist_add_strdup(chunks, "tunnelled-dir-server\n");
-
- smartlist_add_strdup(chunks, "router-signature\n");
-
- size_t len_out = 0;
- buf2 = smartlist_join_strings(chunks, "", 0, &len_out);
- SMARTLIST_FOREACH(chunks, char *, s, tor_free(s));
- smartlist_free(chunks);
-
- tt_assert(len_out > 0);
-
- buf[strlen(buf2)] = '\0'; /* Don't compare the sig; it's never the same
- * twice */
-
- tt_str_op(buf,OP_EQ, buf2);
- tor_free(buf);
-
- setup_mock_configured_ports(r1->or_port, r1->dir_port);
-
- buf = router_dump_router_to_string(r1, r1->identity_pkey, NULL, NULL, NULL);
- tt_assert(buf);
-
- cleanup_mock_configured_ports();
-
- /* Now, try to parse buf */
- cp = buf;
- rp1 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL,NULL);
-
- CHECK_ROUTERINFO_CONSISTENCY(r1, rp1);
-
- tt_assert(rp1->policy_is_reject_star);
-
- tor_free(buf);
- routerinfo_free(rp1);
-
- /* Test extrainfo creation.
- * We avoid calling router_build_fresh_unsigned_routerinfo(), because it's
- * too complex. Instead, we re-use the manually-created routerinfos.
- */
-
- /* Set up standard mocks and data */
- setup_mocks_for_fresh_descriptor(r1, NULL);
-
- /* router_build_fresh_signed_extrainfo() passes the result of
- * get_master_signing_key_cert() directly to tor_cert_dup(), which fails on
- * NULL. But we want a NULL ei->cache_info.signing_key_cert to test the
- * non-ed key path.
- */
- MOCK(tor_cert_dup, mock_tor_cert_dup_null);
-
- /* Fake just enough of an ORPort and DirPort to get by */
- setup_mock_configured_ports(r1->or_port, r1->dir_port);
-
- /* Test some of the low-level static functions. */
- e1 = router_build_fresh_signed_extrainfo(r1);
- tt_assert(e1);
- router_update_routerinfo_from_extrainfo(r1, e1);
- rv = router_dump_and_sign_routerinfo_descriptor_body(r1);
- tt_assert(rv == 0);
- msg = "";
- rv = routerinfo_incompatible_with_extrainfo(r1->identity_pkey, e1,
- &r1->cache_info, &msg);
- /* If they are incompatible, fail and show the msg string */
- tt_str_op(msg, OP_EQ, "");
- tt_assert(rv == 0);
-
- /* Now cleanup */
- cleanup_mocks_for_fresh_descriptor();
-
- UNMOCK(tor_cert_dup);
-
- cleanup_mock_configured_ports();
-
- CHECK_EXTRAINFO_CONSISTENCY(r1, e1);
-
- /* Test that the signed ri is parseable */
- tt_assert(r1->cache_info.signed_descriptor_body);
- cp = r1->cache_info.signed_descriptor_body;
- rp1 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL,NULL);
-
- CHECK_ROUTERINFO_CONSISTENCY(r1, rp1);
-
- tt_assert(rp1->policy_is_reject_star);
-
- routerinfo_free(rp1);
-
- /* Test that the signed ei is parseable */
- tt_assert(e1->cache_info.signed_descriptor_body);
- cp = e1->cache_info.signed_descriptor_body;
- ep1 = extrainfo_parse_entry_from_string((const char*)cp,NULL,1,NULL,NULL);
-
- CHECK_EXTRAINFO_CONSISTENCY(r1, ep1);
-
- /* In future tests, we could check the actual extrainfo statistics. */
-
- extrainfo_free(ep1);
-
- done:
- dirserv_free_fingerprint_list();
-
- tor_free(options->ContactInfo);
- tor_free(options->Nickname);
-
- cleanup_mock_configured_ports();
- cleanup_mocks_for_fresh_descriptor();
-
- if (chunks) {
- SMARTLIST_FOREACH(chunks, char *, s, tor_free(s));
- smartlist_free(chunks);
- }
-
- routerinfo_free(r1);
- routerinfo_free(rp1);
-
- extrainfo_free(e1);
- extrainfo_free(ep1);
-
- tor_free(rsa_cc);
-
- tor_free(buf);
- tor_free(buf2);
-}
-
/* Check that the exit policy in rp2 is as expected. */
#define CHECK_PARSED_EXIT_POLICY(rp2) \
STMT_BEGIN \
@@ -947,7 +741,7 @@ test_dir_formats_rsa_ed25519(void *arg)
ed25519_secret_key_from_seed(&kp2.seckey,
(const uint8_t*)"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
ed25519_public_key_generate(&kp2.pubkey, &kp2.seckey);
- r2->cache_info.signing_key_cert = tor_cert_create(&kp1,
+ r2->cache_info.signing_key_cert = tor_cert_create_ed25519(&kp1,
CERT_TYPE_ID_SIGNING,
&kp2.pubkey,
now, 86400,
@@ -970,7 +764,7 @@ test_dir_formats_rsa_ed25519(void *arg)
smartlist_add(r2->exit_policy, ex2);
/* Fake just enough of an ORPort to get by */
- setup_mock_configured_ports(r2->or_port, 0);
+ setup_mock_configured_ports(r2->ipv4_orport, 0);
buf = router_dump_router_to_string(r2,
r2->identity_pkey, r2_onion_pkey,
@@ -1003,6 +797,8 @@ test_dir_formats_rsa_ed25519(void *arg)
}
smartlist_add(chunks, get_new_platform_line());
+ smartlist_add_asprintf(chunks,
+ "proto %s\n", protover_get_supported_protocols());
smartlist_add(chunks, get_new_published_line(r2));
smartlist_add(chunks, get_new_fingerprint_line(r2));
@@ -1066,9 +862,11 @@ test_dir_formats_rsa_ed25519(void *arg)
tt_str_op(buf, OP_EQ, buf2);
tor_free(buf);
- setup_mock_configured_ports(r2->or_port, 0);
+ setup_mock_configured_ports(r2->ipv4_orport, 0);
- buf = router_dump_router_to_string(r2, r2->identity_pkey, NULL, NULL, NULL);
+ buf = router_dump_router_to_string(r2, r2->identity_pkey,
+ r2_onion_pkey,
+ &r2_onion_keypair, &kp2);
tt_assert(buf);
cleanup_mock_configured_ports();
@@ -1112,7 +910,7 @@ test_dir_formats_rsa_ed25519(void *arg)
MOCK(get_current_curve25519_keypair, mock_get_current_curve25519_keypair);
/* Fake just enough of an ORPort to get by */
- setup_mock_configured_ports(r2->or_port, 0);
+ setup_mock_configured_ports(r2->ipv4_orport, 0);
/* Test the high-level interface. */
rv = router_build_fresh_descriptor(&r2_out, &e2);
@@ -1221,14 +1019,12 @@ test_dir_routerinfo_parsing(void *arg)
again = 999; \
ri = router_parse_entry_from_string((s), NULL, 0, 0, NULL, &again); \
tt_assert(ri == NULL); \
- tt_int_op(again, OP_EQ, (againval)); \
+ tt_int_op(again, OP_EQ, (againval)); \
} while (0)
CHECK_OK(EX_RI_MINIMAL);
CHECK_OK(EX_RI_MAXIMAL);
- CHECK_OK(EX_RI_MINIMAL_ED);
-
/* good annotations prepended */
routerinfo_free(ri);
ri = router_parse_entry_from_string(EX_RI_MINIMAL, NULL, 0, 0,
@@ -1263,14 +1059,13 @@ test_dir_routerinfo_parsing(void *arg)
tt_ptr_op(ri, OP_EQ, NULL);
CHECK_FAIL(EX_RI_BAD_SIG1, 1);
- CHECK_FAIL(EX_RI_BAD_SIG2, 1);
CHECK_FAIL(EX_RI_BAD_TOKENS, 0);
CHECK_FAIL(EX_RI_BAD_PUBLISHED, 0);
CHECK_FAIL(EX_RI_NEG_BANDWIDTH, 0);
CHECK_FAIL(EX_RI_BAD_BANDWIDTH, 0);
CHECK_FAIL(EX_RI_BAD_BANDWIDTH2, 0);
- CHECK_FAIL(EX_RI_BAD_ONIONKEY1, 0);
- CHECK_FAIL(EX_RI_BAD_ONIONKEY2, 0);
+ CHECK_FAIL(EX_RI_BAD_BANDWIDTH3, 0);
+ CHECK_FAIL(EX_RI_BAD_ONIONKEY, 0);
CHECK_FAIL(EX_RI_BAD_PORTS, 0);
CHECK_FAIL(EX_RI_BAD_IP, 0);
CHECK_FAIL(EX_RI_BAD_DIRPORT, 0);
@@ -1293,22 +1088,10 @@ test_dir_routerinfo_parsing(void *arg)
CHECK_FAIL(EX_RI_ED_BAD_SIG1, 0);
CHECK_FAIL(EX_RI_ED_BAD_SIG2, 0);
CHECK_FAIL(EX_RI_ED_BAD_SIG3, 0);
- CHECK_FAIL(EX_RI_ED_BAD_SIG4, 0);
CHECK_FAIL(EX_RI_ED_BAD_CROSSCERT1, 0);
- CHECK_FAIL(EX_RI_ED_BAD_CROSSCERT3, 0);
- CHECK_FAIL(EX_RI_ED_BAD_CROSSCERT4, 0);
- CHECK_FAIL(EX_RI_ED_BAD_CROSSCERT5, 0);
- CHECK_FAIL(EX_RI_ED_BAD_CROSSCERT6, 0);
- CHECK_FAIL(EX_RI_ED_BAD_CROSSCERT7, 0);
CHECK_FAIL(EX_RI_ED_MISPLACED1, 0);
CHECK_FAIL(EX_RI_ED_MISPLACED2, 0);
CHECK_FAIL(EX_RI_ED_BAD_CERT1, 0);
- CHECK_FAIL(EX_RI_ED_BAD_CERT2, 0);
- CHECK_FAIL(EX_RI_ED_BAD_CERT3, 0);
-
- /* This is allowed; we just ignore it. */
- CHECK_OK(EX_RI_BAD_EI_DIGEST);
- CHECK_OK(EX_RI_BAD_EI_DIGEST2);
#undef CHECK_FAIL
#undef CHECK_OK
@@ -1364,14 +1147,10 @@ test_dir_extrainfo_parsing(void *arg)
tt_assert(ei->pending_sig);
CHECK_OK(EX_EI_MAXIMAL);
tt_assert(ei->pending_sig);
- CHECK_OK(EX_EI_GOOD_ED_EI);
- tt_assert(ei->pending_sig);
map = (struct digest_ri_map_t *)digestmap_new();
ADD(EX_EI_MINIMAL);
ADD(EX_EI_MAXIMAL);
- ADD(EX_EI_GOOD_ED_EI);
- ADD(EX_EI_BAD_FP);
ADD(EX_EI_BAD_NICKNAME);
ADD(EX_EI_BAD_TOKENS);
ADD(EX_EI_BAD_START);
@@ -1381,8 +1160,6 @@ test_dir_extrainfo_parsing(void *arg)
ADD(EX_EI_ED_MISSING_CERT);
ADD(EX_EI_ED_BAD_CERT1);
ADD(EX_EI_ED_BAD_CERT2);
- ADD(EX_EI_ED_BAD_SIG1);
- ADD(EX_EI_ED_BAD_SIG2);
ADD(EX_EI_ED_MISPLACED_CERT);
ADD(EX_EI_ED_MISPLACED_SIG);
@@ -1390,13 +1167,9 @@ test_dir_extrainfo_parsing(void *arg)
tt_ptr_op(ei->pending_sig, OP_EQ, NULL);
CHECK_OK(EX_EI_MAXIMAL);
tt_ptr_op(ei->pending_sig, OP_EQ, NULL);
- CHECK_OK(EX_EI_GOOD_ED_EI);
- tt_ptr_op(ei->pending_sig, OP_EQ, NULL);
CHECK_FAIL(EX_EI_BAD_SIG1,1);
- CHECK_FAIL(EX_EI_BAD_SIG2,1);
- CHECK_FAIL(EX_EI_BAD_SIG3,1);
- CHECK_FAIL(EX_EI_BAD_FP,0);
+ CHECK_FAIL(EX_EI_BAD_SIG2,0);
CHECK_FAIL(EX_EI_BAD_NICKNAME,0);
CHECK_FAIL(EX_EI_BAD_TOKENS,0);
CHECK_FAIL(EX_EI_BAD_START,0);
@@ -1406,8 +1179,6 @@ test_dir_extrainfo_parsing(void *arg)
CHECK_FAIL(EX_EI_ED_MISSING_CERT,0);
CHECK_FAIL(EX_EI_ED_BAD_CERT1,0);
CHECK_FAIL(EX_EI_ED_BAD_CERT2,0);
- CHECK_FAIL(EX_EI_ED_BAD_SIG1,0);
- CHECK_FAIL(EX_EI_ED_BAD_SIG2,0);
CHECK_FAIL(EX_EI_ED_MISPLACED_CERT,0);
CHECK_FAIL(EX_EI_ED_MISPLACED_SIG,0);
@@ -1464,11 +1235,14 @@ test_dir_parse_router_list(void *arg)
tt_mem_op(r->cache_info.signed_descriptor_body, OP_EQ,
EX_RI_MAXIMAL, strlen(EX_RI_MAXIMAL));
+ setup_ei_digests();
+
tt_int_op(2, OP_EQ, smartlist_len(invalid));
+
test_memeq_hex(smartlist_get(invalid, 0),
- "ab9eeaa95e7d45740185b4e519c76ead756277a9");
+ "10F951AF93AED0D3BC7FA5FFA232EB8C17747ACE");
test_memeq_hex(smartlist_get(invalid, 1),
- "9a651ee03b64325959e8f1b46f2b689b30750b4c");
+ "41D8723CDD4B1AADCCE538C28CDE7F69828C73D0");
/* Now tidy up */
SMARTLIST_FOREACH(dest, routerinfo_t *, rinfo, routerinfo_free(rinfo));
@@ -1483,6 +1257,7 @@ test_dir_parse_router_list(void *arg)
ADD(EX_EI_MAXIMAL);
ADD(EX_EI_BAD_NICKNAME);
ADD(EX_EI_BAD_PUBLISHED);
+ ADD(EX_EI_BAD_SIG2);
cp = list;
tt_int_op(0,OP_EQ,
router_parse_list_from_string(&cp, NULL, dest, SAVED_NOWHERE,
@@ -1495,11 +1270,16 @@ test_dir_parse_router_list(void *arg)
tt_mem_op(e->cache_info.signed_descriptor_body, OP_EQ,
EX_EI_MINIMAL, strlen(EX_EI_MINIMAL));
- tt_int_op(2, OP_EQ, smartlist_len(invalid));
- test_memeq_hex(smartlist_get(invalid, 0),
- "d5df4aa62ee9ffc9543d41150c9864908e0390af");
- test_memeq_hex(smartlist_get(invalid, 1),
- "f61efd2a7f4531f3687a9043e0de90a862ec64ba");
+ tt_int_op(3, OP_EQ, smartlist_len(invalid));
+ tt_mem_op(smartlist_get(invalid, 0),
+ OP_EQ,
+ digest_ei_bad_sig2, DIGEST_LEN);
+ tt_mem_op(smartlist_get(invalid, 1),
+ OP_EQ,
+ digest_ei_bad_nickname, DIGEST_LEN);
+ tt_mem_op(smartlist_get(invalid, 2),
+ OP_EQ,
+ digest_ei_bad_published, DIGEST_LEN);
done:
tor_free(list);
@@ -1526,10 +1306,34 @@ test_dir_parse_router_list(void *arg)
static download_status_t dls_minimal;
static download_status_t dls_maximal;
static download_status_t dls_bad_fingerprint;
-static download_status_t dls_bad_sig2;
+static download_status_t dls_bad_sig1;
static download_status_t dls_bad_ports;
static download_status_t dls_bad_tokens;
+static uint8_t digest_minimal[20];
+static uint8_t digest_maximal[20];
+static uint8_t digest_bad_fingerprint[20];
+static uint8_t digest_bad_sig1[20];
+static uint8_t digest_bad_ports[20];
+static uint8_t digest_bad_tokens[20];
+
+static void
+setup_dls_digests(void)
+{
+#define SETUP(string, name) \
+ do { \
+ router_get_router_hash(string, strlen(string), (char*)digest_##name); \
+ } while (0)
+
+ SETUP(EX_RI_MINIMAL, minimal);
+ SETUP(EX_RI_MAXIMAL, maximal);
+ SETUP(EX_RI_BAD_FINGERPRINT, bad_fingerprint);
+ SETUP(EX_RI_BAD_SIG1, bad_sig1);
+ SETUP(EX_RI_BAD_PORTS, bad_ports);
+ SETUP(EX_RI_BAD_TOKENS, bad_tokens);
+#undef SETUP
+}
+
static int mock_router_get_dl_status_unrecognized = 0;
static int mock_router_get_dl_status_calls = 0;
@@ -1537,24 +1341,22 @@ static download_status_t *
mock_router_get_dl_status(const char *d)
{
++mock_router_get_dl_status_calls;
- char hex[HEX_DIGEST_LEN+1];
- base16_encode(hex, sizeof(hex), d, DIGEST_LEN);
- if (!strcmp(hex, "3E31D19A69EB719C00B02EC60D13356E3F7A3452")) {
- return &dls_minimal;
- } else if (!strcmp(hex, "581D8A368A0FA854ECDBFAB841D88B3F1B004038")) {
- return &dls_maximal;
- } else if (!strcmp(hex, "2578AE227C6116CDE29B3F0E95709B9872DEE5F1")) {
- return &dls_bad_fingerprint;
- } else if (!strcmp(hex, "16D387D3A58F7DB3CF46638F8D0B90C45C7D769C")) {
- return &dls_bad_sig2;
- } else if (!strcmp(hex, "AB9EEAA95E7D45740185B4E519C76EAD756277A9")) {
- return &dls_bad_ports;
- } else if (!strcmp(hex, "A0CC2CEFAD59DBF19F468BFEE60E0868C804B422")) {
- return &dls_bad_tokens;
- } else {
- ++mock_router_get_dl_status_unrecognized;
- return NULL;
- }
+#define CHECK(name) \
+ do { \
+ if (fast_memeq(d, digest_##name, DIGEST_LEN)) \
+ return &dls_##name; \
+ } while (0)
+
+ CHECK(minimal);
+ CHECK(maximal);
+ CHECK(bad_fingerprint);
+ CHECK(bad_sig1);
+ CHECK(bad_ports);
+ CHECK(bad_tokens);
+
+ ++mock_router_get_dl_status_unrecognized;
+ return NULL;
+#undef CHECK
}
static void
@@ -1573,21 +1375,23 @@ test_dir_load_routers(void *arg)
smartlist_add_strdup(wanted, hex_str(buf, DIGEST_LEN)); \
} while (0)
+ setup_dls_digests();
+
MOCK(router_get_dl_status_by_descriptor_digest, mock_router_get_dl_status);
update_approx_time(1412510400);
smartlist_add_strdup(chunks, EX_RI_MINIMAL);
smartlist_add_strdup(chunks, EX_RI_BAD_FINGERPRINT);
- smartlist_add_strdup(chunks, EX_RI_BAD_SIG2);
+ smartlist_add_strdup(chunks, EX_RI_BAD_SIG1);
smartlist_add_strdup(chunks, EX_RI_MAXIMAL);
smartlist_add_strdup(chunks, EX_RI_BAD_PORTS);
smartlist_add_strdup(chunks, EX_RI_BAD_TOKENS);
- /* not ADDing MINIMIAL */
+ /* not ADDing MINIMAL */
ADD(EX_RI_MAXIMAL);
ADD(EX_RI_BAD_FINGERPRINT);
- ADD(EX_RI_BAD_SIG2);
+ ADD(EX_RI_BAD_SIG1);
/* Not ADDing BAD_PORTS */
ADD(EX_RI_BAD_TOKENS);
@@ -1601,7 +1405,7 @@ test_dir_load_routers(void *arg)
tt_int_op(smartlist_len(router_get_routerlist()->routers),OP_EQ,1);
routerinfo_t *r = smartlist_get(router_get_routerlist()->routers, 0);
test_memeq_hex(r->cache_info.signed_descriptor_digest,
- "581D8A368A0FA854ECDBFAB841D88B3F1B004038");
+ "1F437798ACD1FC9CBD1C3C04DBF80F7E9F819C3F");
tt_int_op(dls_minimal.n_download_failures, OP_EQ, 0);
tt_int_op(dls_maximal.n_download_failures, OP_EQ, 0);
@@ -1614,13 +1418,12 @@ test_dir_load_routers(void *arg)
/* bad_sig2 and bad ports" are retriable -- one since only the signature
* was bad, and one because we didn't ask for it. */
- tt_int_op(dls_bad_sig2.n_download_failures, OP_EQ, 0);
+ tt_int_op(dls_bad_sig1.n_download_failures, OP_EQ, 0);
tt_int_op(dls_bad_ports.n_download_failures, OP_EQ, 0);
- /* Wanted still contains "BAD_SIG2" */
tt_int_op(smartlist_len(wanted), OP_EQ, 1);
tt_str_op(smartlist_get(wanted, 0), OP_EQ,
- "E0A3753CEFD54128EAB239F294954121DB23D2EF");
+ "3BB7D03C1C4DBC1DDE840096FF3C330914757B77");
#undef ADD
@@ -1643,38 +1446,51 @@ static signed_descriptor_t sd_ei_maximal;
static signed_descriptor_t sd_ei_bad_tokens;
static signed_descriptor_t sd_ei_bad_sig2;
+static void
+setup_ei_digests(void)
+{
+#define SETUP(string, name) \
+ do { \
+ router_get_extrainfo_hash(string, strlen(string), \
+ (char*)digest_ei_##name); \
+ } while (0)
+
+ SETUP(EX_EI_MINIMAL, minimal);
+ SETUP(EX_EI_MAXIMAL, maximal);
+ SETUP(EX_EI_BAD_NICKNAME, bad_nickname);
+ SETUP(EX_EI_BAD_TOKENS, bad_tokens);
+ SETUP(EX_EI_BAD_SIG2, bad_sig2);
+ SETUP(EX_EI_BAD_PUBLISHED, bad_published);
+
+#undef SETUP
+}
+
static signed_descriptor_t *
mock_get_by_ei_desc_digest(const char *d)
{
-
++mock_get_by_ei_dd_calls;
- char hex[HEX_DIGEST_LEN+1];
- base16_encode(hex, sizeof(hex), d, DIGEST_LEN);
-
- if (!strcmp(hex, "11E0EDF526950739F7769810FCACAB8C882FAEEE")) {
- return &sd_ei_minimal;
- } else if (!strcmp(hex, "47803B02A0E70E9E8BDA226CB1D74DE354D67DFF")) {
- return &sd_ei_maximal;
- } else if (!strcmp(hex, "D5DF4AA62EE9FFC9543D41150C9864908E0390AF")) {
- return &sd_ei_bad_nickname;
- } else if (!strcmp(hex, "16D387D3A58F7DB3CF46638F8D0B90C45C7D769C")) {
- return &sd_ei_bad_sig2;
- } else if (!strcmp(hex, "9D90F8C42955BBC57D54FB05E54A3F083AF42E8B")) {
- return &sd_ei_bad_tokens;
- } else {
- ++mock_get_by_ei_dd_unrecognized;
- return NULL;
- }
+#define CHECK(name) \
+ do { \
+ if (fast_memeq(d, digest_ei_##name, DIGEST_LEN)) \
+ return &sd_ei_##name; \
+ } while (0)
+
+ CHECK(minimal);
+ CHECK(maximal);
+ CHECK(bad_nickname);
+ CHECK(bad_sig2);
+ CHECK(bad_tokens);
+ ++mock_get_by_ei_dd_unrecognized;
+ return NULL;
+#undef CHECK
}
static signed_descriptor_t *
mock_ei_get_by_ei_digest(const char *d)
{
- char hex[HEX_DIGEST_LEN+1];
- base16_encode(hex, sizeof(hex), d, DIGEST_LEN);
signed_descriptor_t *sd = &sd_ei_minimal;
- if (!strcmp(hex, "11E0EDF526950739F7769810FCACAB8C882FAEEE")) {
+ if (fast_memeq(d, digest_ei_minimal, DIGEST_LEN)) {
sd->signed_descriptor_body = (char *)EX_EI_MINIMAL;
sd->signed_descriptor_len = sizeof(EX_EI_MINIMAL);
sd->annotations_len = 0;
@@ -1710,6 +1526,7 @@ test_dir_load_extrainfo(void *arg)
smartlist_add_strdup(wanted, hex_str(buf, DIGEST_LEN)); \
} while (0)
+ setup_ei_digests();
mock_ei_insert_list = smartlist_new();
MOCK(router_get_by_extrainfo_digest, mock_get_by_ei_desc_digest);
MOCK(extrainfo_insert, mock_ei_insert);
@@ -1720,7 +1537,7 @@ test_dir_load_extrainfo(void *arg)
smartlist_add_strdup(chunks, EX_EI_BAD_PUBLISHED);
smartlist_add_strdup(chunks, EX_EI_BAD_TOKENS);
- /* not ADDing MINIMIAL */
+ /* not ADDing MINIMAL */
ADD(EX_EI_MAXIMAL);
ADD(EX_EI_BAD_NICKNAME);
/* Not ADDing BAD_PUBLISHED */
@@ -1736,12 +1553,12 @@ test_dir_load_extrainfo(void *arg)
tt_int_op(smartlist_len(mock_ei_insert_list),OP_EQ,2);
extrainfo_t *e = smartlist_get(mock_ei_insert_list, 0);
- test_memeq_hex(e->cache_info.signed_descriptor_digest,
- "11E0EDF526950739F7769810FCACAB8C882FAEEE");
+ tt_mem_op(e->cache_info.signed_descriptor_digest, OP_EQ,
+ digest_ei_minimal, DIGEST_LEN);
e = smartlist_get(mock_ei_insert_list, 1);
- test_memeq_hex(e->cache_info.signed_descriptor_digest,
- "47803B02A0E70E9E8BDA226CB1D74DE354D67DFF");
+ tt_mem_op(e->cache_info.signed_descriptor_digest, OP_EQ,
+ digest_ei_maximal, DIGEST_LEN);
tt_int_op(dls_minimal.n_download_failures, OP_EQ, 0);
tt_int_op(dls_maximal.n_download_failures, OP_EQ, 0);
@@ -1757,8 +1574,11 @@ test_dir_load_extrainfo(void *arg)
/* Wanted still contains "BAD_SIG2" */
tt_int_op(smartlist_len(wanted), OP_EQ, 1);
- tt_str_op(smartlist_get(wanted, 0), OP_EQ,
- "16D387D3A58F7DB3CF46638F8D0B90C45C7D769C");
+ const char *got_wanted =smartlist_get(wanted, 0);
+ tt_int_op(strlen(got_wanted), OP_EQ, HEX_DIGEST_LEN);
+ char d[DIGEST_LEN];
+ base16_decode(d, DIGEST_LEN, got_wanted, strlen(got_wanted));
+ tt_mem_op(d, OP_EQ, digest_ei_bad_sig2, DIGEST_LEN);
#undef ADD
@@ -1778,12 +1598,17 @@ test_dir_getinfo_extra(void *arg)
int r;
char *answer = NULL;
const char *errmsg = NULL;
-
+ char buf[128];
+ char hexdigest[HEX_DIGEST_LEN+1];
(void)arg;
+
+ setup_ei_digests();
+ base16_encode(hexdigest, sizeof(hexdigest),
+ (const char*)digest_ei_minimal, DIGEST_LEN);
+ tor_snprintf(buf, sizeof(buf), "extra-info/digest/%s", hexdigest);
+
MOCK(extrainfo_get_by_descriptor_digest, mock_ei_get_by_ei_digest);
- r = getinfo_helper_dir(NULL, "extra-info/digest/"
- "11E0EDF526950739F7769810FCACAB8C882FAEEE", &answer,
- &errmsg);
+ r = getinfo_helper_dir(NULL, buf, &answer, &errmsg);
tt_int_op(0, OP_EQ, r);
tt_ptr_op(NULL, OP_EQ, errmsg);
tt_str_op(answer, OP_EQ, EX_EI_MINIMAL);
@@ -3061,9 +2886,9 @@ test_same_voter(networkstatus_voter_info_t *v1,
tt_str_op(v1->nickname,OP_EQ, v2->nickname);
tt_mem_op(v1->identity_digest,OP_EQ, v2->identity_digest, DIGEST_LEN);
tt_str_op(v1->address,OP_EQ, v2->address);
- tt_int_op(v1->addr,OP_EQ, v2->addr);
- tt_int_op(v1->dir_port,OP_EQ, v2->dir_port);
- tt_int_op(v1->or_port,OP_EQ, v2->or_port);
+ tt_assert(tor_addr_eq(&v1->ipv4_addr, &v2->ipv4_addr));
+ tt_int_op(v1->ipv4_dirport,OP_EQ, v2->ipv4_dirport);
+ tt_int_op(v1->ipv4_orport,OP_EQ, v2->ipv4_orport);
tt_str_op(v1->contact,OP_EQ, v2->contact);
tt_mem_op(v1->vote_digest,OP_EQ, v2->vote_digest, DIGEST_LEN);
done:
@@ -3153,9 +2978,9 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now)
"\x3\x3\x3\x3",
DIGEST_LEN);
tt_mem_op(rs->descriptor_digest,OP_EQ, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN);
- tt_int_op(rs->addr,OP_EQ, 0x99008801);
- tt_int_op(rs->or_port,OP_EQ, 443);
- tt_int_op(rs->dir_port,OP_EQ, 8000);
+ tt_assert(tor_addr_eq_ipv4h(&rs->ipv4_addr, 0x99008801));
+ tt_int_op(rs->ipv4_orport,OP_EQ, 443);
+ tt_int_op(rs->ipv4_dirport,OP_EQ, 8000);
/* no flags except "running" (16) and "v2dir" (64) and "valid" (128) */
tt_u64_op(vrs->flags, OP_EQ, UINT64_C(0xd0));
} else if (tor_memeq(rs->identity_digest,
@@ -3175,9 +3000,9 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now)
tt_str_op(rs->nickname,OP_EQ, "router1");
}
tt_mem_op(rs->descriptor_digest,OP_EQ, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN);
- tt_int_op(rs->addr,OP_EQ, 0x99009901);
- tt_int_op(rs->or_port,OP_EQ, 443);
- tt_int_op(rs->dir_port,OP_EQ, 0);
+ tt_assert(tor_addr_eq_ipv4h(&rs->ipv4_addr, 0x99009901));
+ tt_int_op(rs->ipv4_orport,OP_EQ, 443);
+ tt_int_op(rs->ipv4_dirport,OP_EQ, 0);
tor_addr_parse(&addr_ipv6, "[1:2:3::4]");
tt_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6));
tt_int_op(rs->ipv6_orport,OP_EQ, 4711);
@@ -3269,9 +3094,9 @@ test_routerstatus_for_v3ns(routerstatus_t *rs, time_t now)
tt_str_op(rs->nickname,OP_EQ, "router1");
tt_mem_op(rs->descriptor_digest,OP_EQ, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN);
tt_int_op(rs->published_on,OP_EQ, now-1000);
- tt_int_op(rs->addr,OP_EQ, 0x99009901);
- tt_int_op(rs->or_port,OP_EQ, 443);
- tt_int_op(rs->dir_port,OP_EQ, 0);
+ tt_assert(tor_addr_eq_ipv4h(&rs->ipv4_addr, 0x99009901));
+ tt_int_op(rs->ipv4_orport,OP_EQ, 443);
+ tt_int_op(rs->ipv4_dirport,OP_EQ, 0);
tor_addr_parse(&addr_ipv6, "[1:2:3::4]");
tt_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6));
tt_int_op(rs->ipv6_orport,OP_EQ, 4711);
@@ -3643,9 +3468,9 @@ test_a_networkstatus(
voter = smartlist_get(v1->voters, 0);
tt_str_op(voter->nickname,OP_EQ, "Voter1");
tt_str_op(voter->address,OP_EQ, "1.2.3.4");
- tt_int_op(voter->addr,OP_EQ, 0x01020304);
- tt_int_op(voter->dir_port,OP_EQ, 80);
- tt_int_op(voter->or_port,OP_EQ, 9000);
+ tt_assert(tor_addr_eq_ipv4h(&voter->ipv4_addr, 0x01020304));
+ tt_int_op(voter->ipv4_dirport,OP_EQ, 80);
+ tt_int_op(voter->ipv4_orport,OP_EQ, 9000);
tt_str_op(voter->contact,OP_EQ, "voter@example.com");
tt_assert(v1->cert);
tt_assert(!crypto_pk_cmp_keys(sign_skey_1, v1->cert->signing_key));
@@ -4147,9 +3972,9 @@ gen_routerstatus_for_umbw(int idx, time_t now)
strlcpy(rs->nickname, "router2", sizeof(rs->nickname));
memset(rs->identity_digest, 3, DIGEST_LEN);
memset(rs->descriptor_digest, 78, DIGEST_LEN);
- rs->addr = 0x99008801;
- rs->or_port = 443;
- rs->dir_port = 8000;
+ tor_addr_from_ipv4h(&rs->ipv4_addr, 0x99008801);
+ rs->ipv4_orport = 443;
+ rs->ipv4_dirport = 8000;
/* all flags but running and valid cleared */
rs->is_flagged_running = 1;
rs->is_valid = 1;
@@ -4161,6 +3986,7 @@ gen_routerstatus_for_umbw(int idx, time_t now)
vrs->has_measured_bw = 1;
rs->has_bandwidth = 1;
vrs->measured_bw_kb = rs->bandwidth_kb = max_unmeasured_bw_kb / 2;
+ vrs->protocols = tor_strdup("Link=2 Wombat=40");
break;
case 1:
/* Generate the second routerstatus. */
@@ -4171,9 +3997,9 @@ gen_routerstatus_for_umbw(int idx, time_t now)
strlcpy(rs->nickname, "router1", sizeof(rs->nickname));
memset(rs->identity_digest, 5, DIGEST_LEN);
memset(rs->descriptor_digest, 77, DIGEST_LEN);
- rs->addr = 0x99009901;
- rs->or_port = 443;
- rs->dir_port = 0;
+ tor_addr_from_ipv4h(&rs->ipv4_addr, 0x99009901);
+ rs->ipv4_orport = 443;
+ rs->ipv4_dirport = 0;
tor_addr_parse(&addr_ipv6, "[1:2:3::4]");
tor_addr_copy(&rs->ipv6_addr, &addr_ipv6);
rs->ipv6_orport = 4711;
@@ -4187,6 +4013,7 @@ gen_routerstatus_for_umbw(int idx, time_t now)
vrs->has_measured_bw = 1;
rs->has_bandwidth = 1;
vrs->measured_bw_kb = rs->bandwidth_kb = 2 * max_unmeasured_bw_kb;
+ vrs->protocols = tor_strdup("Link=2 Wombat=40");
break;
case 2:
/* Generate the third routerstatus. */
@@ -4197,9 +4024,9 @@ gen_routerstatus_for_umbw(int idx, time_t now)
strlcpy(rs->nickname, "router3", sizeof(rs->nickname));
memset(rs->identity_digest, 0x33, DIGEST_LEN);
memset(rs->descriptor_digest, 79, DIGEST_LEN);
- rs->addr = 0xAA009901;
- rs->or_port = 400;
- rs->dir_port = 9999;
+ tor_addr_from_ipv4h(&rs->ipv4_addr, 0xAA009901);
+ rs->ipv4_orport = 400;
+ rs->ipv4_dirport = 9999;
rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
rs->is_flagged_running = rs->is_valid =
rs->is_possible_guard = 1;
@@ -4212,6 +4039,7 @@ gen_routerstatus_for_umbw(int idx, time_t now)
rs->has_bandwidth = 1;
vrs->measured_bw_kb = 0;
rs->bandwidth_kb = 2 * max_unmeasured_bw_kb;
+ vrs->protocols = tor_strdup("Link=2 Wombat=40");
break;
case 3:
/* Generate a fourth routerstatus that is not running. */
@@ -4222,9 +4050,9 @@ gen_routerstatus_for_umbw(int idx, time_t now)
strlcpy(rs->nickname, "router4", sizeof(rs->nickname));
memset(rs->identity_digest, 0x34, DIGEST_LEN);
memset(rs->descriptor_digest, 47, DIGEST_LEN);
- rs->addr = 0xC0000203;
- rs->or_port = 500;
- rs->dir_port = 1999;
+ tor_addr_from_ipv4h(&rs->ipv4_addr, 0xC0000203);
+ rs->ipv4_orport = 500;
+ rs->ipv4_dirport = 1999;
/* all flags but running and valid cleared */
rs->is_flagged_running = 1;
rs->is_valid = 1;
@@ -4237,6 +4065,7 @@ gen_routerstatus_for_umbw(int idx, time_t now)
rs->has_bandwidth = 1;
vrs->measured_bw_kb = 0;
rs->bandwidth_kb = max_unmeasured_bw_kb / 2;
+ vrs->protocols = tor_strdup("Link=2 Wombat=40");
break;
case 4:
/* No more for this test; return NULL */
@@ -4324,9 +4153,9 @@ test_vrs_for_umbw(vote_routerstatus_t *vrs, int voter, time_t now)
"\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3",
DIGEST_LEN);
tt_mem_op(rs->descriptor_digest,OP_EQ, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN);
- tt_int_op(rs->addr,OP_EQ, 0x99008801);
- tt_int_op(rs->or_port,OP_EQ, 443);
- tt_int_op(rs->dir_port,OP_EQ, 8000);
+ tt_assert(tor_addr_eq_ipv4h(&rs->ipv4_addr, 0x99008801));
+ tt_int_op(rs->ipv4_orport,OP_EQ, 443);
+ tt_int_op(rs->ipv4_dirport,OP_EQ, 8000);
tt_assert(rs->has_bandwidth);
tt_assert(vrs->has_measured_bw);
tt_int_op(rs->bandwidth_kb,OP_EQ, max_unmeasured_bw_kb / 2);
@@ -4348,9 +4177,9 @@ test_vrs_for_umbw(vote_routerstatus_t *vrs, int voter, time_t now)
"\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5",
DIGEST_LEN);
tt_mem_op(rs->descriptor_digest,OP_EQ, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN);
- tt_int_op(rs->addr,OP_EQ, 0x99009901);
- tt_int_op(rs->or_port,OP_EQ, 443);
- tt_int_op(rs->dir_port,OP_EQ, 0);
+ tt_assert(tor_addr_eq_ipv4h(&rs->ipv4_addr, 0x99009901));
+ tt_int_op(rs->ipv4_orport,OP_EQ, 443);
+ tt_int_op(rs->ipv4_dirport,OP_EQ, 0);
tor_addr_parse(&addr_ipv6, "[1:2:3::4]");
tt_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6));
tt_int_op(rs->ipv6_orport,OP_EQ, 4711);
@@ -4457,9 +4286,9 @@ test_routerstatus_for_umbw(routerstatus_t *rs, time_t now)
tt_str_op(rs->nickname,OP_EQ, "router1");
tt_mem_op(rs->descriptor_digest,OP_EQ, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN);
tt_int_op(rs->published_on,OP_EQ, now-1000);
- tt_int_op(rs->addr,OP_EQ, 0x99009901);
- tt_int_op(rs->or_port,OP_EQ, 443);
- tt_int_op(rs->dir_port,OP_EQ, 0);
+ tt_assert(tor_addr_eq_ipv4h(&rs->ipv4_addr, 0x99009901));
+ tt_int_op(rs->ipv4_orport,OP_EQ, 443);
+ tt_int_op(rs->ipv4_dirport,OP_EQ, 0);
tor_addr_parse(&addr_ipv6, "[1:2:3::4]");
tt_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6));
tt_int_op(rs->ipv6_orport,OP_EQ, 4711);
@@ -4560,9 +4389,9 @@ test_dir_fmt_control_ns(void *arg)
strlcpy(rs.nickname, "TetsuoMilk", sizeof(rs.nickname));
memcpy(rs.identity_digest, "Stately, plump Buck ", DIGEST_LEN);
memcpy(rs.descriptor_digest, "Mulligan came up fro", DIGEST_LEN);
- rs.addr = 0x20304050;
- rs.or_port = 9001;
- rs.dir_port = 9002;
+ tor_addr_from_ipv4h(&rs.ipv4_addr, 0x20304050);
+ rs.ipv4_orport = 9001;
+ rs.ipv4_dirport = 9002;
rs.is_exit = 1;
rs.is_fast = 1;
rs.is_flagged_running = 1;
@@ -4669,7 +4498,7 @@ reset_routerstatus(routerstatus_t *rs,
hex_identity_digest, HEX_DIGEST_LEN);
/* A zero address matches everything, so the address needs to be set.
* But the specific value is irrelevant. */
- rs->addr = ipv4_addr;
+ tor_addr_from_ipv4h(&rs->ipv4_addr, ipv4_addr);
}
#define ROUTER_A_ID_STR "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
@@ -6910,7 +6739,8 @@ test_dir_matching_flags(void *arg)
"r example hereiswhereyouridentitygoes 2015-08-30 12:00:00 "
"192.168.0.1 9001 0\n"
"m thisoneislongerbecauseitisa256bitmddigest33\n"
- "s\n";
+ "s\n"
+ "pr Link=4\n";
const char *cp = ex_noflags;
rs_noflags = routerstatus_parse_entry_from_string(
area, &cp,
@@ -6924,6 +6754,7 @@ test_dir_matching_flags(void *arg)
"r example hereiswhereyouridentitygoes 2015-08-30 12:00:00 " \
"192.168.0.1 9001 0\n" \
"m thisoneislongerbecauseitisa256bitmddigest33\n" \
+ "pr Link=4\n" \
"s %s\n", string); \
cp = s; \
rs = routerstatus_parse_entry_from_string( \
@@ -6981,7 +6812,8 @@ test_dir_assumed_flags(void *arg)
"r example hereiswhereyouridentitygoes 2015-08-30 12:00:00 "
"192.168.0.1 9001 0\n"
"m thisoneislongerbecauseitisa256bitmddigest33\n"
- "s Fast Guard Stable\n";
+ "s Fast Guard Stable\n"
+ "pr Link=4\n";
const char *eos = str1 + strlen(str1);
const char *cp = str1;
@@ -7212,7 +7044,7 @@ test_dir_dirserv_load_fingerprint_file(void *arg)
expect_log_msg_containing("Invalid fingerprint");
teardown_capture_of_logs();
- // Test: Formt string exploit
+ // Test: Format 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);
@@ -7277,8 +7109,8 @@ test_dir_dirserv_router_get_status(void *arg)
/* Set up the routerinfo */
ri = tor_malloc_zero(sizeof(routerinfo_t));
- ri->addr = 0xc0a80001u;
- ri->or_port = 9001;
+ tor_addr_from_ipv4h(&ri->ipv4_addr, 0xc0a80001u);
+ ri->ipv4_orport = 9001;
ri->platform = tor_strdup("0.4.0.1-alpha");
ri->nickname = tor_strdup("Jessica");
ri->identity_pkey = crypto_pk_dup_key(pk);
@@ -7294,7 +7126,7 @@ test_dir_dirserv_router_get_status(void *arg)
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,
+ ri->cache_info.signing_key_cert = tor_cert_create_ed25519(&kp1,
CERT_TYPE_ID_SIGNING,
&kp2.pubkey,
now, 86400,
@@ -7356,8 +7188,8 @@ test_dir_dirserv_would_reject_router(void *arg)
/* Set up the routerstatus */
memset(&rs, 0, sizeof(rs));
- rs.addr = 0xc0a80001u;
- rs.or_port = 9001;
+ tor_addr_from_ipv4h(&rs.ipv4_addr, 0xc0a80001u);
+ rs.ipv4_orport = 9001;
strlcpy(rs.nickname, "Nicole", sizeof(rs.nickname));
memcpy(rs.identity_digest, "Cloud nine is great ", DIGEST_LEN);
@@ -7443,20 +7275,14 @@ test_dir_dirserv_add_own_fingerprint(void *arg)
struct testcase_t dir_tests[] = {
DIR_LEGACY(nicknames),
/* extrainfo without any stats */
- DIR_ARG(formats_rsa, TT_FORK, ""),
DIR_ARG(formats_rsa_ed25519, TT_FORK, ""),
/* on a bridge */
- DIR_ARG(formats_rsa, TT_FORK, "b"),
DIR_ARG(formats_rsa_ed25519, TT_FORK, "b"),
/* extrainfo with basic stats */
- DIR_ARG(formats_rsa, TT_FORK, "e"),
DIR_ARG(formats_rsa_ed25519, TT_FORK, "e"),
- DIR_ARG(formats_rsa, TT_FORK, "be"),
DIR_ARG(formats_rsa_ed25519, TT_FORK, "be"),
/* extrainfo with all stats */
- DIR_ARG(formats_rsa, TT_FORK, "es"),
DIR_ARG(formats_rsa_ed25519, TT_FORK, "es"),
- DIR_ARG(formats_rsa, TT_FORK, "bes"),
DIR_ARG(formats_rsa_ed25519, TT_FORK, "bes"),
DIR(routerinfo_parsing, 0),
DIR(extrainfo_parsing, 0),
diff --git a/src/test/test_dir_common.c b/src/test/test_dir_common.c
index f2b4e8724b..77e3851183 100644
--- a/src/test/test_dir_common.c
+++ b/src/test/test_dir_common.c
@@ -97,13 +97,14 @@ dir_common_gen_routerstatus_for_v3ns(int idx, time_t now)
strlcpy(rs->nickname, "router2", sizeof(rs->nickname));
memset(rs->identity_digest, TEST_DIR_ROUTER_ID_1, DIGEST_LEN);
memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_1, DIGEST_LEN);
- rs->addr = 0x99008801;
- rs->or_port = 443;
- rs->dir_port = 8000;
+ tor_addr_from_ipv4h(&rs->ipv4_addr, 0x99008801);
+ rs->ipv4_orport = 443;
+ rs->ipv4_dirport = 8000;
/* all flags but running and v2dir cleared */
rs->is_flagged_running = 1;
rs->is_v2_dir = 1;
rs->is_valid = 1; /* xxxxx */
+ vrs->protocols = tor_strdup("Link=7 HSDir=3");
break;
case 1:
/* Generate the second routerstatus. */
@@ -114,14 +115,15 @@ dir_common_gen_routerstatus_for_v3ns(int idx, time_t now)
strlcpy(rs->nickname, "router1", sizeof(rs->nickname));
memset(rs->identity_digest, TEST_DIR_ROUTER_ID_2, DIGEST_LEN);
memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_2, DIGEST_LEN);
- rs->addr = 0x99009901;
- rs->or_port = 443;
- rs->dir_port = 0;
+ tor_addr_from_ipv4h(&rs->ipv4_addr, 0x99009901);
+ rs->ipv4_orport = 443;
+ rs->ipv4_dirport = 0;
tor_addr_parse(&addr_ipv6, "[1:2:3::4]");
tor_addr_copy(&rs->ipv6_addr, &addr_ipv6);
rs->ipv6_orport = 4711;
rs->is_exit = rs->is_stable = rs->is_fast = rs->is_flagged_running =
rs->is_valid = rs->is_possible_guard = rs->is_v2_dir = 1;
+ vrs->protocols = tor_strdup("Link=3,4 HSDir=2,3");
break;
case 2:
/* Generate the third routerstatus. */
@@ -132,12 +134,13 @@ dir_common_gen_routerstatus_for_v3ns(int idx, time_t now)
strlcpy(rs->nickname, "router3", sizeof(rs->nickname));
memset(rs->identity_digest, TEST_DIR_ROUTER_ID_3, DIGEST_LEN);
memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_3, DIGEST_LEN);
- rs->addr = 0xAA009901;
- rs->or_port = 400;
- rs->dir_port = 9999;
+ tor_addr_from_ipv4h(&rs->ipv4_addr, 0xAA009901);
+ rs->ipv4_orport = 400;
+ rs->ipv4_dirport = 9999;
rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
rs->is_flagged_running = rs->is_valid = rs->is_v2_dir =
rs->is_possible_guard = 1;
+ vrs->protocols = tor_strdup("Link=3,4 HSDir=2,3");
break;
case 3:
/* Generate a fourth routerstatus that is not running. */
@@ -148,10 +151,11 @@ dir_common_gen_routerstatus_for_v3ns(int idx, time_t now)
strlcpy(rs->nickname, "router4", sizeof(rs->nickname));
memset(rs->identity_digest, TEST_DIR_ROUTER_ID_4, DIGEST_LEN);
memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_4, DIGEST_LEN);
- rs->addr = 0xC0000203;
- rs->or_port = 500;
- rs->dir_port = 1999;
+ tor_addr_from_ipv4h(&rs->ipv4_addr, 0xC0000203);
+ rs->ipv4_orport = 500;
+ rs->ipv4_dirport = 1999;
rs->is_v2_dir = 1;
+ vrs->protocols = tor_strdup("Link=3,4 HSDir=3");
/* Running flag (and others) cleared */
break;
case 4:
@@ -313,9 +317,9 @@ dir_common_construct_vote_1(networkstatus_t **vote, authority_cert_t *cert,
voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
voter->nickname = tor_strdup("Voter1");
voter->address = tor_strdup("1.2.3.4");
- voter->addr = 0x01020304;
- voter->dir_port = 80;
- voter->or_port = 9000;
+ tor_addr_from_ipv4h(&voter->ipv4_addr, 0x01020304);
+ voter->ipv4_dirport = 80;
+ voter->ipv4_orport = 9000;
voter->contact = tor_strdup("voter@example.com");
crypto_pk_get_digest(cert->identity_key, voter->identity_digest);
/*
@@ -362,9 +366,9 @@ dir_common_construct_vote_2(networkstatus_t **vote, authority_cert_t *cert,
voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
voter->nickname = tor_strdup("Voter2");
voter->address = tor_strdup("2.3.4.5");
- voter->addr = 0x02030405;
- voter->dir_port = 80;
- voter->or_port = 9000;
+ tor_addr_from_ipv4h(&voter->ipv4_addr, 0x02030405);
+ voter->ipv4_dirport = 80;
+ voter->ipv4_orport = 9000;
voter->contact = tor_strdup("voter@example.com");
crypto_pk_get_digest(cert->identity_key, voter->identity_digest);
/*
@@ -412,9 +416,9 @@ dir_common_construct_vote_3(networkstatus_t **vote, authority_cert_t *cert,
voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
voter->nickname = tor_strdup("Voter2");
voter->address = tor_strdup("3.4.5.6");
- voter->addr = 0x03040506;
- voter->dir_port = 80;
- voter->or_port = 9000;
+ tor_addr_from_ipv4h(&voter->ipv4_addr, 0x03040506);
+ voter->ipv4_dirport = 80;
+ voter->ipv4_orport = 9000;
voter->contact = tor_strdup("voter@example.com");
crypto_pk_get_digest(cert->identity_key, voter->identity_digest);
memset(voter->legacy_id_digest, (int)'A', DIGEST_LEN);
diff --git a/src/test/test_dir_handle_get.c b/src/test/test_dir_handle_get.c
index f446bbb5eb..28f07efbe8 100644
--- a/src/test/test_dir_handle_get.c
+++ b/src/test/test_dir_handle_get.c
@@ -31,6 +31,7 @@
#include "feature/nodelist/nodelist.h"
#include "feature/client/entrynodes.h"
#include "feature/dirparse/authcert_parse.h"
+#include "feature/dirparse/sigcommon.h"
#include "feature/nodelist/networkstatus.h"
#include "core/proto/proto_http.h"
#include "lib/geoip/geoip.h"
@@ -73,6 +74,23 @@ ENABLE_GCC_WARNING("-Woverlength-strings")
#define consdiffmgr_add_consensus consdiffmgr_add_consensus_nulterm
+static int
+mock_ignore_signature_token(const char *digest,
+ ssize_t digest_len,
+ struct directory_token_t *tok,
+ crypto_pk_t *pkey,
+ int flags,
+ const char *doctype)
+{
+ (void)digest;
+ (void)digest_len;
+ (void)tok;
+ (void)pkey;
+ (void)flags;
+ (void)doctype;
+ return 0;
+}
+
static dir_connection_t *
new_dir_conn(void)
{
@@ -313,10 +331,10 @@ test_dir_handle_get_rendezvous2_on_encrypted_conn_not_well_formed(void *data)
TO_CONN(conn)->linked = 1;
tt_assert(connection_dir_is_encrypted(conn));
- //TODO: this cant be reached because rend_valid_descriptor_id() prevents this
- //case to happen. This test is the same as
- //test_dir_handle_get_rendezvous2_on_encrypted_conn_with_invalid_desc_id
- //We should refactor to remove the case from the switch.
+ //TODO: this can't be reached because rend_valid_descriptor_id() prevents
+ //this case to happen. This test is the same as
+ //test_dir_handle_get_rendezvous2_on_encrypted_conn_with_invalid_desc_id We
+ //should refactor to remove the case from the switch.
const char *req = RENDEZVOUS2_GET("1bababababababababababababababab");
tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
@@ -500,7 +518,8 @@ static const char microdesc[] =
"MIGJAoGBAMjlHH/daN43cSVRaHBwgUfnszzAhg98EvivJ9Qxfv51mvQUxPjQ07es\n"
"gV/3n8fyh3Kqr/ehi9jxkdgSRfSnmF7giaHL1SLZ29kA7KtST+pBvmTpDtHa3ykX\n"
"Xorc7hJvIyTZoc1HU+5XSynj3gsBE5IGK1ZRzrNS688LnuZMVp1tAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n";
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key QlrOXAa8j3LD31LESsPm/lIKFBwevk2oXdqJcd9SEUc=\n";
static void
test_dir_handle_get_micro_d(void *data)
@@ -1976,7 +1995,8 @@ test_dir_handle_get_status_vote_current_not_found(void* data)
tor_free(header);
}
-#define VOTE_DIGEST "312A4890D4D832597ABBD3089C782DBBFB81E48D"
+/* What vote do we ask for, to get the vote in vote_descriptors.inc ? */
+#define VOTE_DIGEST "78400095d8e834d87135cfc46235c909f0e99911"
static void
status_vote_current_d_test(char **header, char **body, size_t *body_l)
@@ -2058,6 +2078,7 @@ test_dir_handle_get_status_vote_d(void* data)
const char digest[DIGEST_LEN] = "";
(void) data;
+ MOCK(check_signature_token, mock_ignore_signature_token);
clear_dir_servers();
dirvote_free_all();
@@ -2084,7 +2105,7 @@ test_dir_handle_get_status_vote_d(void* data)
const char *msg_out = NULL;
int status_out = 0;
- struct pending_vote_t *pv = dirvote_add_vote(VOTE_BODY_V3, 0,
+ struct pending_vote_t *pv = dirvote_add_vote(VOTE_BODY_V3, 0, "foo",
&msg_out, &status_out);
tt_assert(pv);
@@ -2094,7 +2115,7 @@ test_dir_handle_get_status_vote_d(void* data)
tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
- tt_assert(strstr(header, "Content-Length: 4135\r\n"));
+ tt_assert(strstr(header, "Content-Length: 4403\r\n"));
tt_str_op(VOTE_BODY_V3, OP_EQ, body);
@@ -2107,11 +2128,12 @@ test_dir_handle_get_status_vote_d(void* data)
tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
- tt_assert(strstr(header, "Content-Length: 4135\r\n"));
+ tt_assert(strstr(header, "Content-Length: 4403\r\n"));
tt_str_op(VOTE_BODY_V3, OP_EQ, body);
done:
+ UNMOCK(check_signature_token);
tor_free(header);
tor_free(body);
or_options_free(mock_options); mock_options = NULL;
@@ -2188,6 +2210,7 @@ test_dir_handle_get_status_vote_current_authority_not_found(void* data)
(void) data;
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+ MOCK(check_signature_token, mock_ignore_signature_token);
conn = new_dir_conn();
tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
@@ -2199,6 +2222,7 @@ test_dir_handle_get_status_vote_current_authority_not_found(void* data)
tt_str_op(NOT_FOUND, OP_EQ, header);
done:
+ UNMOCK(check_signature_token);
UNMOCK(connection_write_to_buf_impl_);
connection_free_minimal(TO_CONN(conn));
tor_free(header);
@@ -2212,6 +2236,7 @@ test_dir_handle_get_status_vote_next_authority_not_found(void* data)
(void) data;
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+ MOCK(check_signature_token, mock_ignore_signature_token);
conn = new_dir_conn();
tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
@@ -2223,6 +2248,7 @@ test_dir_handle_get_status_vote_next_authority_not_found(void* data)
tt_str_op(NOT_FOUND, OP_EQ, header);
done:
+ UNMOCK(check_signature_token);
UNMOCK(connection_write_to_buf_impl_);
connection_free_minimal(TO_CONN(conn));
tor_free(header);
@@ -2236,7 +2262,7 @@ test_dir_handle_get_status_vote_next_bandwidth_not_found(void* data)
(void) data;
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
-
+ MOCK(check_signature_token, mock_ignore_signature_token);
conn = new_dir_conn();
tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
@@ -2248,6 +2274,7 @@ test_dir_handle_get_status_vote_next_bandwidth_not_found(void* data)
tt_str_op(NOT_FOUND, OP_EQ, header);
done:
+ UNMOCK(check_signature_token);
UNMOCK(connection_write_to_buf_impl_);
connection_free_minimal(TO_CONN(conn));
tor_free(header);
@@ -2428,6 +2455,7 @@ test_dir_handle_get_status_vote_next_authority(void* data)
const char digest[DIGEST_LEN] = "";
(void) data;
+ MOCK(check_signature_token, mock_ignore_signature_token);
clear_dir_servers();
routerlist_free_all();
dirvote_free_all();
@@ -2459,7 +2487,7 @@ test_dir_handle_get_status_vote_next_authority(void* data)
time_t now = 1441223455 -1;
dirauth_sched_recalculate_timing(mock_options, now);
- struct pending_vote_t *vote = dirvote_add_vote(VOTE_BODY_V3, 0,
+ struct pending_vote_t *vote = dirvote_add_vote(VOTE_BODY_V3, 0, "foo",
&msg_out, &status_out);
tt_assert(vote);
@@ -2477,11 +2505,12 @@ test_dir_handle_get_status_vote_next_authority(void* data)
tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
- tt_assert(strstr(header, "Content-Length: 4135\r\n"));
+ tt_assert(strstr(header, "Content-Length: 4403\r\n"));
tt_str_op(VOTE_BODY_V3, OP_EQ, body);
done:
+ UNMOCK(check_signature_token);
UNMOCK(connection_write_to_buf_impl_);
UNMOCK(get_my_v3_authority_cert);
connection_free_minimal(TO_CONN(conn));
@@ -2587,6 +2616,7 @@ test_dir_handle_get_status_vote_current_authority(void* data)
dir_server_t *ds = NULL;
(void) data;
+ MOCK(check_signature_token, mock_ignore_signature_token);
clear_dir_servers();
routerlist_free_all();
dirvote_free_all();
@@ -2619,7 +2649,7 @@ test_dir_handle_get_status_vote_current_authority(void* data)
time_t now = 1441223455;
dirauth_sched_recalculate_timing(mock_options, now-1);
- struct pending_vote_t *vote = dirvote_add_vote(VOTE_BODY_V3, 0,
+ struct pending_vote_t *vote = dirvote_add_vote(VOTE_BODY_V3, 0, "foo",
&msg_out, &status_out);
tt_assert(vote);
@@ -2640,11 +2670,12 @@ test_dir_handle_get_status_vote_current_authority(void* data)
tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
- tt_assert(strstr(header, "Content-Length: 4135\r\n"));
+ tt_assert(strstr(header, "Content-Length: 4403\r\n"));
tt_str_op(VOTE_BODY_V3, OP_EQ, body);
done:
+ UNMOCK(check_signature_token);
UNMOCK(connection_write_to_buf_impl_);
UNMOCK(get_my_v3_authority_cert);
connection_free_minimal(TO_CONN(conn));
@@ -2672,6 +2703,7 @@ test_dir_handle_get_status_vote_too_late(void* data)
dir_server_t *ds = NULL;
const char* mode = (const char *)data;
+ MOCK(check_signature_token, mock_ignore_signature_token);
clear_dir_servers();
routerlist_free_all();
dirvote_free_all();
@@ -2745,7 +2777,7 @@ test_dir_handle_get_status_vote_too_late(void* data)
/* Next voting interval */
vote = dirvote_add_vote(VOTE_BODY_V3,
- fetch_missing + vote_interval,
+ fetch_missing + vote_interval, "foo",
&msg_out, &status_out);
tt_assert(!vote);
tt_int_op(status_out, OP_EQ, 400);
@@ -2754,7 +2786,7 @@ test_dir_handle_get_status_vote_too_late(void* data)
/* Just after fetch missing */
vote = dirvote_add_vote(VOTE_BODY_V3,
- fetch_missing + 1,
+ fetch_missing + 1, "foo",
&msg_out, &status_out);
tt_assert(!vote);
tt_int_op(status_out, OP_EQ, 400);
@@ -2763,7 +2795,7 @@ test_dir_handle_get_status_vote_too_late(void* data)
/* On fetch missing */
vote = dirvote_add_vote(VOTE_BODY_V3,
- fetch_missing,
+ fetch_missing, "foo",
&msg_out, &status_out);
tt_assert(vote);
@@ -2774,7 +2806,7 @@ test_dir_handle_get_status_vote_too_late(void* data)
/* Between voting starts and fetch missing */
vote = dirvote_add_vote(VOTE_BODY_V3,
- voting_starts + 1,
+ voting_starts + 1, "foo",
&msg_out, &status_out);
tt_assert(vote);
@@ -2785,7 +2817,7 @@ test_dir_handle_get_status_vote_too_late(void* data)
/* On voting starts */
vote = dirvote_add_vote(VOTE_BODY_V3,
- voting_starts,
+ voting_starts, "foo",
&msg_out, &status_out);
tt_assert(vote);
@@ -2796,7 +2828,7 @@ test_dir_handle_get_status_vote_too_late(void* data)
/* Just before voting starts */
vote = dirvote_add_vote(VOTE_BODY_V3,
- voting_starts - 1,
+ voting_starts - 1, "foo",
&msg_out, &status_out);
tt_assert(vote);
@@ -2817,11 +2849,12 @@ test_dir_handle_get_status_vote_too_late(void* data)
tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
- tt_assert(strstr(header, "Content-Length: 4135\r\n"));
+ tt_assert(strstr(header, "Content-Length: 4403\r\n"));
tt_str_op(VOTE_BODY_V3, OP_EQ, body);
done:
+ UNMOCK(check_signature_token);
UNMOCK(connection_write_to_buf_impl_);
UNMOCK(get_my_v3_authority_cert);
connection_free_minimal(TO_CONN(conn));
diff --git a/src/test/test_dirvote.c b/src/test/test_dirvote.c
new file mode 100644
index 0000000000..b5e57ad071
--- /dev/null
+++ b/src/test/test_dirvote.c
@@ -0,0 +1,671 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file test_dirvote.c
+ * \brief Unit tests for dirvote related functions
+ */
+#define DIRVOTE_PRIVATE
+
+#include "core/or/or.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/nodelist/dirlist.h"
+#include "feature/nodelist/node_st.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/signed_descriptor_st.h"
+
+#include "test/test.h"
+
+/**
+ * This struct holds the various information that are needed for router
+ * comparison. Each router in the test function has one, and they are all
+ * put in a global digestmap, router_properties
+ */
+typedef struct router_values_t {
+ int is_running;
+ int is_auth;
+ int bw_kb;
+ char digest[DIGEST_LEN];
+} router_values_t;
+/**
+ * This typedef makes declaring digests easier and less verbose
+ */
+typedef char sha1_digest_t[DIGEST_LEN];
+
+// Use of global variable is justified because the functions that have to be
+// mocked take as arguments objects we have no control over
+static digestmap_t *router_properties = NULL;
+// Use of global variable is justified by its use in nodelist.c
+// and is necessary to avoid memory leaks when mocking the
+// function node_get_by_id
+static node_t *running_node;
+static node_t *non_running_node;
+
+/* Allocate memory to the global variables that represent a running
+ * and non-running node
+ */
+#define ALLOCATE_MOCK_NODES() \
+ running_node = tor_malloc(sizeof(node_t)); \
+ running_node->is_running = 1; \
+ non_running_node = tor_malloc(sizeof(node_t)); \
+ non_running_node->is_running = 0;
+
+/* Free the memory allocated to the mock nodes */
+#define FREE_MOCK_NODES() \
+ tor_free(running_node); \
+ tor_free(non_running_node);
+
+static int
+mock_router_digest_is_trusted(const char *digest, dirinfo_type_t type)
+{
+ (void)type;
+ router_values_t *mock_status;
+ mock_status = digestmap_get(router_properties, digest);
+ if (!mock_status) {
+ return -1;
+ }
+ return mock_status->is_auth;
+}
+
+static const node_t *
+mock_node_get_by_id(const char *identity_digest)
+{
+ router_values_t *status;
+ status = digestmap_get(router_properties, identity_digest);
+ if (!status) {
+ return NULL;
+ }
+ if (status->is_running)
+ return running_node;
+ else
+ return non_running_node;
+}
+
+static uint32_t
+mock_dirserv_get_bw(const routerinfo_t *ri)
+{
+ const char *digest = ri->cache_info.identity_digest;
+ router_values_t *status;
+ status = digestmap_get(router_properties, digest);
+ if (!status) {
+ return -1;
+ }
+ return status->bw_kb;
+}
+
+/** Generate a pointer to a router_values_t struct with the arguments as
+ * field values, and return it
+ * The returned pointer has to be freed by the caller.
+ */
+static router_values_t *
+router_values_new(int running, int auth, int bw, char *digest)
+{
+ router_values_t *status = tor_malloc(sizeof(router_values_t));
+ memcpy(status->digest, digest, sizeof(status->digest));
+ status->is_running = running;
+ status->bw_kb = bw;
+ status->is_auth = auth;
+ return status;
+}
+
+/** Given a router_values_t struct, generate a pointer to a routerinfo struct.
+ * In the cache_info member, put the identity digest, and depending on
+ * the family argument, fill the IPv4 or IPv6 address. Return the pointer.
+ * The returned pointer has to be freed by the caller.
+ */
+static routerinfo_t *
+routerinfo_new(router_values_t *status, int family, int addr)
+{
+ routerinfo_t *ri = tor_malloc(sizeof(routerinfo_t));
+ signed_descriptor_t cache_info;
+ memcpy(cache_info.identity_digest, status->digest,
+ sizeof(cache_info.identity_digest));
+ ri->cache_info = cache_info;
+ tor_addr_t ipv6, ipv4;
+ ipv6.family = family;
+ ipv4.family = family;
+ // Set the address of the other IP version to 0
+ if (family == AF_INET) {
+ ipv4.addr.in_addr.s_addr = addr;
+ for (size_t i = 0; i < 16; i++) {
+ ipv6.addr.in6_addr.s6_addr[i] = 0;
+ }
+ } else {
+ for (size_t i = 0; i < 16; i++) {
+ ipv6.addr.in6_addr.s6_addr[i] = addr;
+ }
+ ipv4.addr.in_addr.s_addr = 0;
+ }
+ ri->ipv6_addr = ipv6;
+ ri->ipv4_addr = ipv4;
+ return ri;
+}
+
+static void
+test_dirvote_compare_routerinfo_usefulness(void *arg)
+{
+ (void)arg;
+ MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted);
+ MOCK(node_get_by_id, mock_node_get_by_id);
+ MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw);
+ ALLOCATE_MOCK_NODES();
+ router_properties = digestmap_new();
+
+ // The router one is the "least useful" router, every router is compared to
+ // it
+ sha1_digest_t digest_one = "aaaa";
+ router_values_t *status_one = router_values_new(0, 0, 0, digest_one);
+ digestmap_set(router_properties, status_one->digest, status_one);
+ sha1_digest_t digest_two = "bbbb";
+ router_values_t *status_two = router_values_new(0, 1, 0, digest_two);
+ digestmap_set(router_properties, status_two->digest, status_two);
+ sha1_digest_t digest_three = "cccc";
+ router_values_t *status_three = router_values_new(1, 0, 0, digest_three);
+ digestmap_set(router_properties, status_three->digest, status_three);
+ sha1_digest_t digest_four = "dddd";
+ router_values_t *status_four = router_values_new(0, 0, 128, digest_four);
+ digestmap_set(router_properties, status_four->digest, status_four);
+ sha1_digest_t digest_five = "9999";
+ router_values_t *status_five = router_values_new(0, 0, 0, digest_five);
+ digestmap_set(router_properties, status_five->digest, status_five);
+
+ // A router that has auth status is more useful than a non-auth one
+ routerinfo_t *first = routerinfo_new(status_one, AF_INET, 0xf);
+ routerinfo_t *second = routerinfo_new(status_two, AF_INET, 0xf);
+ int a = compare_routerinfo_usefulness(first, second);
+ tt_assert(a == 1);
+ tor_free(second);
+
+ // A running router is more useful than a non running one
+ routerinfo_t *third = routerinfo_new(status_three, AF_INET, 0xf);
+ a = compare_routerinfo_usefulness(first, third);
+ tt_assert(a == 1);
+ tor_free(third);
+
+ // A higher bandwidth is more useful
+ routerinfo_t *fourth = routerinfo_new(status_four, AF_INET, 0xf);
+ a = compare_routerinfo_usefulness(first, fourth);
+ tt_assert(a == 1);
+ tor_free(fourth);
+
+ // In case of tie, the digests are compared
+ routerinfo_t *fifth = routerinfo_new(status_five, AF_INET, 0xf);
+ a = compare_routerinfo_usefulness(first, fifth);
+ tt_assert(a > 0);
+ tor_free(fifth);
+
+done:
+ UNMOCK(router_digest_is_trusted_dir_type);
+ UNMOCK(node_get_by_id);
+ UNMOCK(dirserv_get_bandwidth_for_router_kb);
+ FREE_MOCK_NODES();
+ digestmap_free(router_properties, NULL);
+ tor_free(status_one);
+ tor_free(status_two);
+ tor_free(status_three);
+ tor_free(status_four);
+ tor_free(status_five);
+ tor_free(first);
+}
+
+static void
+test_dirvote_compare_routerinfo_by_ipv4(void *arg)
+{
+ (void)arg;
+ MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted);
+ MOCK(node_get_by_id, mock_node_get_by_id);
+ MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw);
+
+ ALLOCATE_MOCK_NODES();
+ router_properties = digestmap_new();
+ sha1_digest_t digest_one = "aaaa";
+ router_values_t *status_one = router_values_new(0, 0, 0, digest_one);
+ digestmap_set(router_properties, status_one->digest, status_one);
+ sha1_digest_t digest_two = "bbbb";
+ router_values_t *status_two = router_values_new(0, 1, 0, digest_two);
+ digestmap_set(router_properties, status_two->digest, status_two);
+
+ // Both routers have an IPv4 address
+ routerinfo_t *first = routerinfo_new(status_one, AF_INET, 1);
+ routerinfo_t *second = routerinfo_new(status_two, AF_INET, 0xf);
+
+ // The first argument's address precedes the seconds' one
+ int a = compare_routerinfo_by_ipv4((const void **)&first,
+ (const void **)&second);
+ tt_assert(a < 0);
+ // The second argument's address precedes the first' one
+ a = compare_routerinfo_by_ipv4((const void **)&second,
+ (const void **)&first);
+ tt_assert(a > 0);
+ tor_addr_copy(&(second->ipv4_addr), &(first->ipv6_addr));
+ // The addresses are equal, they are compared by usefulness,
+ // and first is less useful than second
+ a = compare_routerinfo_by_ipv4((const void **)&first,
+ (const void **)&second);
+ tt_assert(a == 1);
+done:
+ UNMOCK(router_digest_is_trusted_dir_type);
+ UNMOCK(node_get_by_id);
+ UNMOCK(dirserv_get_bandwidth_for_router_kb);
+ FREE_MOCK_NODES();
+ digestmap_free(router_properties, NULL);
+ tor_free(status_one);
+ tor_free(status_two);
+ tor_free(first);
+ tor_free(second);
+}
+
+static void
+test_dirvote_compare_routerinfo_by_ipv6(void *arg)
+{
+ (void)arg;
+ MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted);
+ MOCK(node_get_by_id, mock_node_get_by_id);
+ MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw);
+
+ ALLOCATE_MOCK_NODES();
+ router_properties = digestmap_new();
+ char digest_one[DIGEST_LEN] = "aaaa";
+ router_values_t *status_one = router_values_new(0, 0, 0, digest_one);
+ digestmap_set(router_properties, status_one->digest, status_one);
+ char digest_two[DIGEST_LEN] = "bbbb";
+ router_values_t *status_two = router_values_new(0, 1, 0, digest_two);
+ digestmap_set(router_properties, status_two->digest, status_two);
+
+ // Both routers have an IPv6 address
+ routerinfo_t *first = routerinfo_new(status_one, AF_INET6, 1);
+ routerinfo_t *second = routerinfo_new(status_two, AF_INET6, 0xf);
+
+ // The first argument's address precedes the seconds' one
+ int a = compare_routerinfo_by_ipv6((const void **)&first,
+ (const void **)&second);
+ tt_assert(a < 0);
+ // The second argument's address precedes the first' one
+ a = compare_routerinfo_by_ipv6((const void **)&second,
+ (const void **)&first);
+ tt_assert(a > 0);
+ tor_addr_copy(&(first->ipv6_addr), &(second->ipv6_addr));
+ // The addresses are equal, they are compared by usefulness,
+ // and first is less useful than second
+ a = compare_routerinfo_by_ipv6((const void **)&first,
+ (const void **)&second);
+ tt_assert(a == 1);
+done:
+ UNMOCK(router_digest_is_trusted_dir_type);
+ UNMOCK(node_get_by_id);
+ UNMOCK(dirserv_get_bandwidth_for_router_kb);
+ FREE_MOCK_NODES();
+ digestmap_free(router_properties, NULL);
+ tor_free(status_one);
+ tor_free(status_two);
+ tor_free(first);
+ tor_free(second);
+}
+
+/** Create routers values and routerinfos that always have the same
+ * characteristics, and add them to the global digestmap. This macro is here to
+ * avoid duplicated code fragments.
+ * The created name##_val pointer should be freed by the caller (and cannot
+ * be freed in the macro as it causes a heap-after-free error)
+ */
+#define CREATE_ROUTER(digest, name, addr, ip_version) \
+ sha1_digest_t name##_digest = digest; \
+ name##_val = router_values_new(1, 1, 1, name##_digest); \
+ digestmap_set(router_properties, name##_digest, name##_val); \
+ name##_ri = routerinfo_new(name##_val, ip_version, addr);
+
+#define ROUTER_FREE(name) \
+ tor_free(name##_val); \
+ tor_free(name##_ri);
+
+/** Test to see if the returned routers are exactly the ones that should be
+ * flagged as sybils : we test for inclusion then for number of elements
+ */
+#define TEST_SYBIL(true_sybil, possible_sybil) \
+ DIGESTMAP_FOREACH (true_sybil, sybil_id, void *, ignore) { \
+ (void)ignore; \
+ tt_assert(digestmap_get(possible_sybil, sybil_id)); \
+ } \
+ DIGESTMAP_FOREACH_END; \
+ tt_assert(digestmap_size(true_sybil) == digestmap_size(possible_sybil));
+
+static void
+test_dirvote_get_sybil_by_ip_version_ipv4(void *arg)
+{
+ // It is assumed that global_dirauth_options.AuthDirMaxServersPerAddr == 2
+ (void)arg;
+ router_values_t *aaaa_val=NULL, *bbbb_val=NULL, *cccc_val=NULL,
+ *dddd_val=NULL, *eeee_val=NULL, *ffff_val=NULL, *gggg_val=NULL,
+ *hhhh_val=NULL;
+ routerinfo_t *aaaa_ri=NULL, *bbbb_ri=NULL, *cccc_ri=NULL,
+ *dddd_ri=NULL, *eeee_ri=NULL, *ffff_ri=NULL, *gggg_ri=NULL,
+ *hhhh_ri=NULL;
+
+ MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted);
+ MOCK(node_get_by_id, mock_node_get_by_id);
+ MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw);
+ ALLOCATE_MOCK_NODES();
+ router_properties = digestmap_new();
+ smartlist_t *routers_ipv4;
+ routers_ipv4 = smartlist_new();
+ digestmap_t *true_sybil_routers = NULL;
+ true_sybil_routers = digestmap_new();
+ digestmap_t *omit_as_sybil;
+
+ CREATE_ROUTER("aaaa", aaaa, 123, AF_INET);
+ smartlist_add(routers_ipv4, aaaa_ri);
+ CREATE_ROUTER("bbbb", bbbb, 123, AF_INET);
+ smartlist_add(routers_ipv4, bbbb_ri);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET);
+ tt_assert(digestmap_isempty(omit_as_sybil) == 1);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("cccc", cccc, 123, AF_INET);
+ smartlist_add(routers_ipv4, cccc_ri);
+ digestmap_set(true_sybil_routers, cccc_digest, cccc_digest);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("dddd", dddd, 123, AF_INET);
+ smartlist_add(routers_ipv4, dddd_ri);
+ digestmap_set(true_sybil_routers, dddd_digest, dddd_digest);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("eeee", eeee, 456, AF_INET);
+ smartlist_add(routers_ipv4, eeee_ri);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("ffff", ffff, 456, AF_INET);
+ smartlist_add(routers_ipv4, ffff_ri);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("gggg", gggg, 456, AF_INET);
+ smartlist_add(routers_ipv4, gggg_ri);
+ digestmap_set(true_sybil_routers, gggg_digest, gggg_digest);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("hhhh", hhhh, 456, AF_INET);
+ smartlist_add(routers_ipv4, hhhh_ri);
+ digestmap_set(true_sybil_routers, hhhh_digest, hhhh_digest);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+
+done:
+ UNMOCK(router_digest_is_trusted_dir_type);
+ UNMOCK(node_get_by_id);
+ UNMOCK(dirserv_get_bandwidth_for_router_kb);
+ FREE_MOCK_NODES();
+ digestmap_free(router_properties, NULL);
+ smartlist_free(routers_ipv4);
+ digestmap_free(omit_as_sybil, NULL);
+ digestmap_free(true_sybil_routers, NULL);
+ ROUTER_FREE(aaaa);
+ ROUTER_FREE(bbbb);
+ ROUTER_FREE(cccc);
+ ROUTER_FREE(dddd);
+ ROUTER_FREE(eeee);
+ ROUTER_FREE(ffff);
+ ROUTER_FREE(gggg);
+ ROUTER_FREE(hhhh);
+}
+
+static void
+test_dirvote_get_sybil_by_ip_version_ipv6(void *arg)
+{
+ router_values_t *aaaa_val=NULL, *bbbb_val=NULL, *cccc_val=NULL,
+ *dddd_val=NULL, *eeee_val=NULL, *ffff_val=NULL, *gggg_val=NULL,
+ *hhhh_val=NULL;
+ routerinfo_t *aaaa_ri=NULL, *bbbb_ri=NULL, *cccc_ri=NULL,
+ *dddd_ri=NULL, *eeee_ri=NULL, *ffff_ri=NULL, *gggg_ri=NULL,
+ *hhhh_ri=NULL;
+
+ // It is assumed that global_dirauth_options.AuthDirMaxServersPerAddr == 2
+ (void)arg;
+ MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted);
+ MOCK(node_get_by_id, mock_node_get_by_id);
+ MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw);
+ ALLOCATE_MOCK_NODES();
+ router_properties = digestmap_new();
+ smartlist_t *routers_ipv6;
+ routers_ipv6 = smartlist_new();
+ digestmap_t *true_sybil_routers = NULL;
+ true_sybil_routers = digestmap_new();
+ digestmap_t *omit_as_sybil;
+
+ CREATE_ROUTER("aaaa", aaaa, 123, AF_INET6);
+ smartlist_add(routers_ipv6, aaaa_ri);
+ CREATE_ROUTER("bbbb", bbbb, 123, AF_INET6);
+ smartlist_add(routers_ipv6, bbbb_ri);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("cccc", cccc, 123, AF_INET6);
+ smartlist_add(routers_ipv6, cccc_ri);
+ digestmap_set(true_sybil_routers, cccc_digest, cccc_digest);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("dddd", dddd, 123, AF_INET6);
+ smartlist_add(routers_ipv6, dddd_ri);
+ digestmap_set(true_sybil_routers, dddd_digest, dddd_digest);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("eeee", eeee, 456, AF_INET6);
+ smartlist_add(routers_ipv6, eeee_ri);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("ffff", ffff, 456, AF_INET6);
+ smartlist_add(routers_ipv6, ffff_ri);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("gggg", gggg, 456, AF_INET6);
+ smartlist_add(routers_ipv6, gggg_ri);
+ digestmap_set(true_sybil_routers, gggg_digest, gggg_digest);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("hhhh", hhhh, 456, AF_INET6);
+ smartlist_add(routers_ipv6, hhhh_ri);
+ digestmap_set(true_sybil_routers, hhhh_digest, hhhh_digest);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+done:
+ UNMOCK(router_digest_is_trusted_dir_type);
+ UNMOCK(node_get_by_id);
+ UNMOCK(dirserv_get_bandwidth_for_router_kb);
+ FREE_MOCK_NODES();
+ digestmap_free(router_properties, NULL);
+ digestmap_free(true_sybil_routers, NULL);
+ smartlist_free(routers_ipv6);
+ digestmap_free(omit_as_sybil, NULL);
+ ROUTER_FREE(aaaa);
+ ROUTER_FREE(bbbb);
+ ROUTER_FREE(cccc);
+ ROUTER_FREE(dddd);
+ ROUTER_FREE(eeee);
+ ROUTER_FREE(ffff);
+ ROUTER_FREE(gggg);
+ ROUTER_FREE(hhhh);
+}
+
+static void
+test_dirvote_get_all_possible_sybil(void *arg)
+{
+ router_values_t *aaaa_val=NULL, *bbbb_val=NULL, *cccc_val=NULL,
+ *dddd_val=NULL, *eeee_val=NULL, *ffff_val=NULL, *gggg_val=NULL,
+ *hhhh_val=NULL, *iiii_val=NULL, *jjjj_val=NULL, *kkkk_val=NULL,
+ *llll_val=NULL, *mmmm_val=NULL, *nnnn_val=NULL, *oooo_val=NULL,
+ *pppp_val=NULL;
+ routerinfo_t *aaaa_ri=NULL, *bbbb_ri=NULL, *cccc_ri=NULL,
+ *dddd_ri=NULL, *eeee_ri=NULL, *ffff_ri=NULL, *gggg_ri=NULL,
+ *hhhh_ri=NULL, *iiii_ri=NULL, *jjjj_ri=NULL, *kkkk_ri=NULL,
+ *llll_ri=NULL, *mmmm_ri=NULL, *nnnn_ri=NULL, *oooo_ri=NULL,
+ *pppp_ri=NULL;
+
+ // It is assumed that global_dirauth_options.AuthDirMaxServersPerAddr == 2
+ (void)arg;
+ MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted);
+ MOCK(node_get_by_id, mock_node_get_by_id);
+ MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw);
+ ALLOCATE_MOCK_NODES();
+ router_properties = digestmap_new();
+ smartlist_t *routers;
+ routers = smartlist_new();
+ digestmap_t *true_sybil_routers = NULL;
+ true_sybil_routers = digestmap_new();
+ digestmap_t *omit_as_sybil;
+
+ CREATE_ROUTER("aaaa", aaaa, 123, AF_INET);
+ smartlist_add(routers, aaaa_ri);
+ CREATE_ROUTER("bbbb", bbbb, 123, AF_INET);
+ smartlist_add(routers, bbbb_ri);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("cccc", cccc, 123, AF_INET);
+ smartlist_add(routers, cccc_ri);
+ digestmap_set(true_sybil_routers, cccc_digest, cccc_digest);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("dddd", dddd, 123, AF_INET);
+ smartlist_add(routers, dddd_ri);
+ digestmap_set(true_sybil_routers, dddd_digest, dddd_digest);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("eeee", eeee, 456, AF_INET);
+ smartlist_add(routers, eeee_ri);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("ffff", ffff, 456, AF_INET);
+ smartlist_add(routers, ffff_ri);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("gggg", gggg, 456, AF_INET);
+ smartlist_add(routers, gggg_ri);
+ digestmap_set(true_sybil_routers, gggg_digest, gggg_digest);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("hhhh", hhhh, 456, AF_INET);
+ smartlist_add(routers, hhhh_ri);
+ digestmap_set(true_sybil_routers, hhhh_digest, hhhh_digest);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("iiii", iiii, 123, AF_INET6);
+ smartlist_add(routers, iiii_ri);
+ CREATE_ROUTER("jjjj", jjjj, 123, AF_INET6);
+ smartlist_add(routers, jjjj_ri);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("kkkk", kkkk, 123, AF_INET6);
+ smartlist_add(routers, kkkk_ri);
+ digestmap_set(true_sybil_routers, kkkk_digest, kkkk_digest);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil,NULL);
+
+ CREATE_ROUTER("llll", llll, 123, AF_INET6);
+ smartlist_add(routers, llll_ri);
+ digestmap_set(true_sybil_routers, llll_digest, llll_digest);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil,NULL);
+
+ CREATE_ROUTER("mmmm", mmmm, 456, AF_INET6);
+ smartlist_add(routers, mmmm_ri);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("nnnn", nnnn, 456, AF_INET6);
+ smartlist_add(routers, nnnn_ri);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("oooo", oooo, 456, AF_INET6);
+ smartlist_add(routers, oooo_ri);
+ digestmap_set(true_sybil_routers, oooo_digest, oooo_digest);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("pppp", pppp, 456, AF_INET6);
+ smartlist_add(routers, pppp_ri);
+ digestmap_set(true_sybil_routers, pppp_digest, pppp_digest);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+
+done:
+ UNMOCK(router_digest_is_trusted_dir_type);
+ UNMOCK(node_get_by_id);
+ UNMOCK(dirserv_get_bandwidth_for_router_kb);
+ FREE_MOCK_NODES();
+ digestmap_free(router_properties, NULL);
+ smartlist_free(routers);
+ digestmap_free(omit_as_sybil, NULL);
+ digestmap_free(true_sybil_routers, NULL);
+ ROUTER_FREE(aaaa);
+ ROUTER_FREE(bbbb);
+ ROUTER_FREE(cccc);
+ ROUTER_FREE(dddd);
+ ROUTER_FREE(eeee);
+ ROUTER_FREE(ffff);
+ ROUTER_FREE(gggg);
+ ROUTER_FREE(hhhh);
+ ROUTER_FREE(iiii);
+ ROUTER_FREE(jjjj);
+ ROUTER_FREE(kkkk);
+ ROUTER_FREE(llll);
+ ROUTER_FREE(mmmm);
+ ROUTER_FREE(nnnn);
+ ROUTER_FREE(oooo);
+ ROUTER_FREE(pppp);
+}
+
+#define NODE(name, flags) \
+ { \
+ #name, test_dirvote_##name, (flags), NULL, NULL \
+ }
+
+struct testcase_t dirvote_tests[] = {
+ NODE(compare_routerinfo_usefulness, TT_FORK),
+ NODE(compare_routerinfo_by_ipv6, TT_FORK),
+ NODE(compare_routerinfo_by_ipv4, TT_FORK),
+ NODE(get_sybil_by_ip_version_ipv4, TT_FORK),
+ NODE(get_sybil_by_ip_version_ipv6, TT_FORK),
+ NODE(get_all_possible_sybil, TT_FORK),
+ END_OF_TESTCASES};
diff --git a/src/test/test_dispatch.c b/src/test/test_dispatch.c
index 77f33e4b15..f7f8ecdc03 100644
--- a/src/test/test_dispatch.c
+++ b/src/test/test_dispatch.c
@@ -135,7 +135,7 @@ test_dispatch_simple(void *arg)
tor_free(recv2_received);
}
-/* Construct a dispatch_t with a message and no reciever; make sure that it
+/* Construct a dispatch_t with a message and no receiver; make sure that it
* gets dropped properly. */
static void
test_dispatch_no_recipient(void *arg)
diff --git a/src/test/test_dos.c b/src/test/test_dos.c
index 527e5bbe7f..850bbef59b 100644
--- a/src/test/test_dos.c
+++ b/src/test/test_dos.c
@@ -66,9 +66,9 @@ test_dos_conn_creation(void *arg)
/* Initialize test data */
or_connection_t or_conn;
time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
- tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.real_addr,
+ tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&TO_CONN(&or_conn)->addr,
"18.0.0.1"));
- tor_addr_t *addr = &or_conn.real_addr;
+ tor_addr_t *addr = &TO_CONN(&or_conn)->addr;
/* Get DoS subsystem limits */
dos_init();
@@ -108,7 +108,7 @@ test_dos_conn_creation(void *arg)
/** Helper mock: Place a fake IP addr for this channel in <b>addr_out</b> */
static int
-mock_channel_get_addr_if_possible(channel_t *chan, tor_addr_t *addr_out)
+mock_channel_get_addr_if_possible(const channel_t *chan, tor_addr_t *addr_out)
{
(void)chan;
tt_int_op(AF_INET,OP_EQ, tor_addr_parse(addr_out, "18.0.0.1"));
@@ -139,9 +139,9 @@ test_dos_circuit_creation(void *arg)
/* Initialize test data */
or_connection_t or_conn;
time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
- tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.real_addr,
+ tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&TO_CONN(&or_conn)->addr,
"18.0.0.1"));
- tor_addr_t *addr = &or_conn.real_addr;
+ tor_addr_t *addr = &TO_CONN(&or_conn)->addr;
/* Get DoS subsystem limits */
dos_init();
@@ -202,9 +202,9 @@ test_dos_bucket_refill(void *arg)
channel_init(chan);
chan->is_client = 1;
or_connection_t or_conn;
- tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.real_addr,
+ tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&TO_CONN(&or_conn)->addr,
"18.0.0.1"));
- tor_addr_t *addr = &or_conn.real_addr;
+ tor_addr_t *addr = &TO_CONN(&or_conn)->addr;
/* Initialize DoS subsystem and get relevant limits */
dos_init();
@@ -443,10 +443,10 @@ test_known_relay(void *arg)
/* Setup an OR conn so we can pass it to the DoS subsystem. */
or_connection_t or_conn;
- tor_addr_parse(&or_conn.real_addr, "42.42.42.42");
+ tor_addr_parse(&TO_CONN(&or_conn)->addr, "42.42.42.42");
rs = tor_malloc_zero(sizeof(*rs));
- rs->addr = tor_addr_to_ipv4h(&or_conn.real_addr);
+ tor_addr_copy(&rs->ipv4_addr, &TO_CONN(&or_conn)->addr);
crypto_rand(rs->identity_digest, sizeof(rs->identity_digest));
smartlist_add(dummy_ns->routerstatus_list, rs);
@@ -457,7 +457,8 @@ test_known_relay(void *arg)
/* We have now a node in our list so we'll make sure we don't count it as a
* client connection. */
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &or_conn.real_addr, NULL, 0);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &TO_CONN(&or_conn)->addr,
+ NULL, 0);
/* Suppose we have 5 connections in rapid succession, the counter should
* always be 0 because we should ignore this. */
dos_new_client_conn(&or_conn, NULL);
@@ -465,18 +466,21 @@ test_known_relay(void *arg)
dos_new_client_conn(&or_conn, NULL);
dos_new_client_conn(&or_conn, NULL);
dos_new_client_conn(&or_conn, NULL);
- entry = geoip_lookup_client(&or_conn.real_addr, NULL, GEOIP_CLIENT_CONNECT);
+ entry = geoip_lookup_client(&TO_CONN(&or_conn)->addr, NULL,
+ GEOIP_CLIENT_CONNECT);
tt_assert(entry);
/* We should have a count of 0. */
tt_uint_op(entry->dos_stats.concurrent_count, OP_EQ, 0);
/* To make sure that his is working properly, make a unknown client
* connection and see if we do get it. */
- tor_addr_parse(&or_conn.real_addr, "42.42.42.43");
- geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &or_conn.real_addr, NULL, 0);
+ tor_addr_parse(&TO_CONN(&or_conn)->addr, "42.42.42.43");
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &TO_CONN(&or_conn)->addr,
+ NULL, 0);
dos_new_client_conn(&or_conn, NULL);
dos_new_client_conn(&or_conn, NULL);
- entry = geoip_lookup_client(&or_conn.real_addr, NULL, GEOIP_CLIENT_CONNECT);
+ entry = geoip_lookup_client(&TO_CONN(&or_conn)->addr, NULL,
+ GEOIP_CLIENT_CONNECT);
tt_assert(entry);
/* We should have a count of 2. */
tt_uint_op(entry->dos_stats.concurrent_count, OP_EQ, 2);
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index 5ddd1a3db0..589876db2a 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -171,8 +171,8 @@ big_fake_network_setup(const struct testcase_t *testcase)
/* Note: all these guards have the same address, so you'll need to
* disable EnforceDistinctSubnets when a restriction is applied. */
- n->rs->addr = 0x04020202;
- n->rs->or_port = 1234;
+ tor_addr_from_ipv4h(&n->rs->ipv4_addr, 0x04020202);
+ n->rs->ipv4_orport = 1234;
n->rs->is_v2_dir = 1;
n->rs->has_bandwidth = 1;
n->rs->bandwidth_kb = 30;
@@ -272,8 +272,8 @@ test_node_preferred_orport(void *arg)
/* Setup node_ri */
memset(&node_ri, 0, sizeof(node_ri));
- node_ri.addr = tor_addr_to_ipv4h(&ipv4_addr);
- node_ri.or_port = ipv4_port;
+ tor_addr_copy(&node_ri.ipv4_addr, &ipv4_addr);
+ node_ri.ipv4_orport = ipv4_port;
tor_addr_copy(&node_ri.ipv6_addr, &ipv6_addr);
node_ri.ipv6_orport = ipv6_port;
@@ -322,7 +322,7 @@ test_node_preferred_orport(void *arg)
* ClientUseIPv4 is 0 */
mocked_options->ClientUseIPv4 = 0;
mocked_options->ClientUseIPv6 = 1;
- node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(mocked_options);
+ node.ipv6_preferred = reachable_addr_prefer_ipv6_orport(mocked_options);
node_get_pref_orport(&node, &ap);
tt_assert(tor_addr_eq(&ap.addr, &ipv6_addr));
tt_assert(ap.port == ipv6_port);
@@ -1002,10 +1002,10 @@ test_entry_guard_node_filter(void *arg)
g[1]->pb.path_bias_disabled = 1;
/* 2: Unreachable address. */
- n[2]->rs->addr = 0;
+ tor_addr_make_unspec(&n[2]->rs->ipv4_addr);
/* 3: ExcludeNodes */
- n[3]->rs->addr = 0x90902020;
+ tor_addr_from_ipv4h(&n[3]->rs->ipv4_addr, 0x90902020);
routerset_free(get_options_mutable()->ExcludeNodes);
get_options_mutable()->ExcludeNodes = routerset_new();
routerset_parse(get_options_mutable()->ExcludeNodes, "144.144.0.0/16", "");
@@ -1014,8 +1014,8 @@ test_entry_guard_node_filter(void *arg)
get_options_mutable()->UseBridges = 1;
sweep_bridge_list();
bl = tor_malloc_zero(sizeof(bridge_line_t));
- tor_addr_from_ipv4h(&bl->addr, n[4]->rs->addr);
- bl->port = n[4]->rs->or_port;
+ tor_addr_copy(&bl->addr, &n[4]->rs->ipv4_addr);
+ bl->port = n[4]->rs->ipv4_orport;
memcpy(bl->digest, n[4]->identity, 20);
bridge_add_from_config(bl);
bl = NULL; // prevent free.
@@ -1124,7 +1124,7 @@ test_entry_guard_expand_sample(void *arg)
routerset_parse(get_options_mutable()->ExcludeNodes, "144.144.0.0/16", "");
SMARTLIST_FOREACH(big_fake_net_nodes, node_t *, n, {
if (n_sl_idx % 64 != 0) {
- n->rs->addr = 0x90903030;
+ tor_addr_from_ipv4h(&n->rs->ipv4_addr, 0x90903030);
}
});
entry_guards_update_filtered_sets(gs);
@@ -1162,7 +1162,7 @@ test_entry_guard_expand_sample_small_net(void *arg)
test_node_free(n);
SMARTLIST_DEL_CURRENT(big_fake_net_nodes, n);
} else {
- n->rs->addr = 0; // make the filter reject this.
+ tor_addr_make_unspec(&n->rs->ipv4_addr); // make the filter reject this.
}
});
diff --git a/src/test/test_geoip.c b/src/test/test_geoip.c
index bf9932c169..95afe4d6c4 100644
--- a/src/test/test_geoip.c
+++ b/src/test/test_geoip.c
@@ -402,7 +402,7 @@ test_geoip_load_file(void *arg)
char *contents = NULL;
char *dhex = NULL;
- /* A nonexistant filename should fail. */
+ /* A nonexistent filename should fail. */
tt_int_op(-1, OP_EQ,
geoip_load_file(AF_INET, "/you/did/not/put/a/file/here/I/hope",
LOG_INFO));
@@ -412,7 +412,7 @@ test_geoip_load_file(void *arg)
tt_str_op("??", OP_EQ, geoip_get_country_name(0));
/* Any lookup attempt should say "-1" because we have no info */
tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv4(0x01020304));
- /* There should be no 'digest' for a nonexistant file */
+ /* There should be no 'digest' for a nonexistent file */
tt_str_op("0000000000000000000000000000000000000000", OP_EQ,
geoip_db_digest(AF_INET));
@@ -467,7 +467,7 @@ test_geoip6_load_file(void *arg)
char *contents = NULL;
char *dhex = NULL;
- /* A nonexistant filename should fail. */
+ /* A nonexistent filename should fail. */
tt_int_op(-1, OP_EQ,
geoip_load_file(AF_INET6, "/you/did/not/put/a/file/here/I/hope",
LOG_INFO));
diff --git a/src/test/test_guardfraction.c b/src/test/test_guardfraction.c
index 00c200e0fd..6019dfc2b1 100644
--- a/src/test/test_guardfraction.c
+++ b/src/test/test_guardfraction.c
@@ -51,9 +51,9 @@ gen_vote_routerstatus_for_tests(const char *digest_in_hex, int is_guard)
vrs->version = tor_strdup("0.1.2.14");
strlcpy(rs->nickname, "router2", sizeof(rs->nickname));
memset(rs->descriptor_digest, 78, DIGEST_LEN);
- rs->addr = 0x99008801;
- rs->or_port = 443;
- rs->dir_port = 8000;
+ tor_addr_from_ipv4h(&rs->ipv4_addr, 0x99008801);
+ rs->ipv4_orport = 443;
+ rs->ipv4_dirport = 8000;
/* all flags but running cleared */
rs->is_flagged_running = 1;
vrs->has_measured_bw = 1;
diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c
index f31c28b24d..20d4582e74 100644
--- a/src/test/test_helpers.c
+++ b/src/test/test_helpers.c
@@ -16,30 +16,48 @@
#include "core/or/or.h"
#include "lib/buf/buffers.h"
-#include "app/config/config.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"
-#include "core/or/relay.h"
-#include "feature/nodelist/routerlist.h"
#include "lib/dispatch/dispatch.h"
#include "lib/dispatch/dispatch_naming.h"
-#include "lib/pubsub/pubsub_build.h"
-#include "lib/pubsub/pubsub_connect.h"
#include "lib/encoding/confline.h"
#include "lib/net/resolve.h"
+#include "lib/pubsub/pubsub_build.h"
+#include "lib/pubsub/pubsub_connect.h"
+
+#include "core/mainloop/connection.h"
+#include "core/mainloop/mainloop.h"
+#include "core/or/connection_or.h"
+#include "core/or/crypt_path.h"
+#include "core/or/relay.h"
+
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerlist.h"
+
+#include "app/config/config.h"
+#include "app/main/subsysmgr.h"
#include "core/or/cell_st.h"
#include "core/or/connection_st.h"
+#include "core/or/cpath_build_state_st.h"
+#include "core/or/crypt_path_st.h"
+#include "core/or/origin_circuit_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"
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef _WIN32
+/* For mkdir() */
+#include <direct.h>
+#else
+#include <dirent.h>
+#endif /* defined(_WIN32) */
+
#include "test/test.h"
#include "test/test_helpers.h"
#include "test/test_connection.h"
@@ -95,12 +113,17 @@ helper_setup_fake_routerlist(void)
MOCK(router_descriptor_is_older_than,
router_descriptor_is_older_than_replacement);
+ // Pick a time when these descriptors' certificates were valid.
+ update_approx_time(1603981036);
+
/* Load all the test descriptors to the routerlist. */
retval = router_load_routers_from_string(TEST_DESCRIPTORS,
NULL, SAVED_IN_JOURNAL,
NULL, 0, NULL);
tt_int_op(retval, OP_EQ, HELPER_NUMBER_OF_DESCRIPTORS);
+ update_approx_time(0); // this restores the regular approx_time behavior
+
/* Sanity checking of routerlist and nodelist. */
our_routerlist = router_get_routerlist();
tt_int_op(smartlist_len(our_routerlist->routers), OP_EQ,
@@ -187,6 +210,78 @@ mock_tor_addr_lookup__fail_on_bad_addrs(const char *name,
return tor_addr_lookup__real(name, family, out);
}
+static char *
+create_directory(const char *parent_dir, const char *name)
+{
+ char *dir = NULL;
+ tor_asprintf(&dir, "%s"PATH_SEPARATOR"%s", parent_dir, name);
+#ifdef _WIN32
+ tt_int_op(mkdir(dir), OP_EQ, 0);
+#else
+ tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
+#endif
+ return dir;
+
+ done:
+ tor_free(dir);
+ return NULL;
+}
+
+static char *
+create_file(const char *parent_dir, const char *name, const char *contents)
+{
+ char *path = NULL;
+ tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", parent_dir, name);
+ contents = contents == NULL ? "" : contents;
+ tt_int_op(write_str_to_file(path, contents, 0), OP_EQ, 0);
+ return path;
+
+ done:
+ tor_free(path);
+ return NULL;
+}
+
+int
+create_test_directory_structure(const char *parent_dir)
+{
+ int ret = -1;
+ char *dir1 = NULL;
+ char *dir2 = NULL;
+ char *file1 = NULL;
+ char *file2 = NULL;
+ char *dot = NULL;
+ char *empty = NULL;
+ char *forbidden = NULL;
+
+ dir1 = create_directory(parent_dir, "dir1");
+ tt_assert(dir1);
+ dir2 = create_directory(parent_dir, "dir2");
+ tt_assert(dir2);
+ file1 = create_file(parent_dir, "file1", "Test 1");
+ tt_assert(file1);
+ file2 = create_file(parent_dir, "file2", "Test 2");
+ tt_assert(file2);
+ dot = create_file(parent_dir, ".test-hidden", "Test .");
+ tt_assert(dot);
+ empty = create_file(parent_dir, "empty", NULL);
+ tt_assert(empty);
+ forbidden = create_directory(parent_dir, "forbidden");
+ tt_assert(forbidden);
+#ifndef _WIN32
+ tt_int_op(chmod(forbidden, 0), OP_EQ, 0);
+#endif
+ ret = 0;
+ done:
+ tor_free(dir1);
+ tor_free(dir2);
+ tor_free(file1);
+ tor_free(file2);
+ tor_free(dot);
+ tor_free(empty);
+ tor_free(forbidden);
+ return ret;
+}
+
/*********** Helper funcs for making new connections/streams *****************/
/* Helper for test_conn_get_connection() */
@@ -441,3 +536,36 @@ helper_cleanup_pubsub(const struct testcase_t *testcase, void *dispatcher_)
const struct testcase_setup_t helper_pubsub_setup = {
helper_setup_pubsub, helper_cleanup_pubsub
};
+
+origin_circuit_t *
+new_test_origin_circuit(bool has_opened,
+ struct timeval circ_start_time,
+ int path_len,
+ extend_info_t **ei_list)
+{
+ origin_circuit_t *origin_circ = origin_circuit_new();
+
+ TO_CIRCUIT(origin_circ)->purpose = CIRCUIT_PURPOSE_C_GENERAL;
+
+ origin_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
+ origin_circ->build_state->desired_path_len = path_len;
+
+ if (ei_list) {
+ for (int i = 0; i < path_len; i++) {
+ extend_info_t *ei = ei_list[i];
+ cpath_append_hop(&origin_circ->cpath, ei);
+ }
+ }
+
+ if (has_opened) {
+ origin_circ->has_opened = 1;
+ TO_CIRCUIT(origin_circ)->state = CIRCUIT_STATE_OPEN;
+ origin_circ->cpath->state = CPATH_STATE_OPEN;
+ } else {
+ TO_CIRCUIT(origin_circ)->timestamp_began = circ_start_time;
+ TO_CIRCUIT(origin_circ)->timestamp_created = circ_start_time;
+ origin_circ->cpath->state = CPATH_STATE_CLOSED;
+ }
+
+ return origin_circ;
+}
diff --git a/src/test/test_helpers.h b/src/test/test_helpers.h
index eaf18e19e2..f02ecbb0ac 100644
--- a/src/test/test_helpers.h
+++ b/src/test/test_helpers.h
@@ -33,6 +33,8 @@ connection_t *test_conn_get_connection(uint8_t state,
uint8_t type, uint8_t purpose);
or_options_t *helper_parse_options(const char *conf);
+int create_test_directory_structure(const char *parent_dir);
+
extern const char TEST_DESCRIPTORS[];
void *helper_setup_pubsub(const struct testcase_t *);
@@ -40,5 +42,10 @@ int helper_cleanup_pubsub(const struct testcase_t *, void *);
extern const struct testcase_setup_t helper_pubsub_setup;
+origin_circuit_t *new_test_origin_circuit(bool has_opened,
+ struct timeval circ_start_time,
+ int path_len,
+ extend_info_t **ei_list);
+
#endif /* !defined(TOR_TEST_HELPERS_H) */
diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c
index 0cd7d81eea..f59b3a59cd 100644
--- a/src/test/test_hs_client.c
+++ b/src/test/test_hs_client.c
@@ -41,6 +41,7 @@
#include "feature/rend/rendcache.h"
#include "core/or/circuitlist.h"
#include "core/or/circuitbuild.h"
+#include "core/or/extendinfo.h"
#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "feature/nodelist/networkstatus.h"
@@ -531,7 +532,7 @@ test_client_pick_intro(void *arg)
get_options_mutable()->ClientUseIPv6 = 1;
intro_ei = hs_get_extend_info_from_lspecs(ip->link_specifiers,
&ip->onion_key, 1);
- tt_assert(tor_addr_family(&intro_ei->addr) == AF_INET6);
+ tt_assert(tor_addr_family(&intro_ei->orports[0].addr) == AF_INET6);
}
tt_assert(intro_ei);
if (intro_ei) {
@@ -539,7 +540,8 @@ test_client_pick_intro(void *arg)
char ip_addr[TOR_ADDR_BUF_LEN];
/* We need to decorate in case it is an IPv6 else routerset_parse()
* doesn't like it. */
- ptr = tor_addr_to_str(ip_addr, &intro_ei->addr, sizeof(ip_addr), 1);
+ ptr = tor_addr_to_str(ip_addr, &intro_ei->orports[0].addr,
+ sizeof(ip_addr), 1);
tt_assert(ptr == ip_addr);
ret = routerset_parse(get_options_mutable()->ExcludeNodes,
ip_addr, "");
@@ -1486,7 +1488,7 @@ test_purge_ephemeral_client_auth(void *arg)
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
+ /* Bogus 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");
diff --git a/src/test/test_hs_common.c b/src/test/test_hs_common.c
index e3d130fb32..5032a82b9c 100644
--- a/src/test/test_hs_common.c
+++ b/src/test/test_hs_common.c
@@ -293,7 +293,6 @@ helper_add_hsdir_to_networkstatus(networkstatus_t *ns,
routerstatus_t *rs = tor_malloc_zero(sizeof(routerstatus_t));
routerinfo_t *ri = tor_malloc_zero(sizeof(routerinfo_t));
uint8_t identity[DIGEST_LEN];
- tor_addr_t ipv4_addr;
node_t *node = NULL;
memset(identity, identity_idx, sizeof(identity));
@@ -302,9 +301,8 @@ helper_add_hsdir_to_networkstatus(networkstatus_t *ns,
rs->is_hs_dir = is_hsdir;
rs->pv.supports_v3_hsdir = 1;
strlcpy(rs->nickname, nickname, sizeof(rs->nickname));
- tor_addr_parse(&ipv4_addr, "1.2.3.4");
- ri->addr = tor_addr_to_ipv4h(&ipv4_addr);
- rs->addr = tor_addr_to_ipv4h(&ipv4_addr);
+ tor_addr_parse(&ri->ipv4_addr, "1.2.3.4");
+ tor_addr_parse(&rs->ipv4_addr, "1.2.3.4");
ri->nickname = tor_strdup(nickname);
ri->protocol_list = tor_strdup("HSDir=1-2 LinkAuth=3");
memcpy(ri->cache_info.identity_digest, identity, DIGEST_LEN);
@@ -491,7 +489,7 @@ test_desc_reupload_logic(void *arg)
* 1) Upload descriptor to HSDirs
* CHECK that previous_hsdirs list was populated.
* 2) Then call router_dir_info_changed() without an HSDir set change.
- * CHECK that no reuplod occurs.
+ * CHECK that no reupload occurs.
* 3) Now change the HSDir set, and call dir_info_changed() again.
* CHECK that reupload occurs.
* 4) Finally call service_desc_schedule_upload().
diff --git a/src/test/test_hs_control.c b/src/test/test_hs_control.c
index 80bbf547dc..6e41c4994f 100644
--- a/src/test/test_hs_control.c
+++ b/src/test/test_hs_control.c
@@ -619,7 +619,7 @@ test_hs_control_store_permanent_creds(void *arg)
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 */
+ /* base32 representation of the base64 iJ1t... key above */
"x25519:rcow3dfavmyanyqvhwnvnmfdqw34ydtrgv7jnelmqs4wi4uuxrca");
tor_free(args);
@@ -643,7 +643,7 @@ test_hs_control_store_permanent_creds(void *arg)
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 */
+ /* base32 representation of the base64 UDRv... key above */
"x25519:ka2g6zf33qti2ecexpbx4stan3nsu3sijbiqm4t2rwctigxajnpq");
/* Now for our next act!!! Actually get the HS client subsystem to parse the
diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c
index 782b78306c..b6e13c79a8 100644
--- a/src/test/test_hs_descriptor.c
+++ b/src/test/test_hs_descriptor.c
@@ -56,7 +56,7 @@ test_cert_encoding(void *arg)
ret = ed25519_public_key_generate(&signed_key, &secret_key);
tt_int_op(ret, == , 0);
- cert = tor_cert_create(&kp, CERT_TYPE_SIGNING_AUTH, &signed_key,
+ cert = tor_cert_create_ed25519(&kp, CERT_TYPE_SIGNING_AUTH, &signed_key,
now, 3600 * 2, CERT_FLAG_INCLUDE_SIGNING_KEY);
tt_assert(cert);
@@ -706,7 +706,7 @@ test_validate_cert(void *arg)
tt_int_op(ret, OP_EQ, 0);
/* Cert of type CERT_TYPE_AUTH_HS_IP_KEY. */
- cert = tor_cert_create(&kp, CERT_TYPE_AUTH_HS_IP_KEY,
+ cert = tor_cert_create_ed25519(&kp, CERT_TYPE_AUTH_HS_IP_KEY,
&kp.pubkey, now, 3600,
CERT_FLAG_INCLUDE_SIGNING_KEY);
tt_assert(cert);
@@ -726,8 +726,9 @@ test_validate_cert(void *arg)
tor_cert_free(cert);
/* Try a cert without including the signing key. */
- cert = tor_cert_create(&kp, CERT_TYPE_AUTH_HS_IP_KEY, &kp.pubkey, now,
- 3600, 0);
+ cert = tor_cert_create_ed25519(&kp, CERT_TYPE_AUTH_HS_IP_KEY,
+ &kp.pubkey, now, 3600, 0);
+
tt_assert(cert);
/* Test with a bad type. */
ret = cert_is_valid(cert, CERT_TYPE_AUTH_HS_IP_KEY, "unicorn");
diff --git a/src/test/test_hs_metrics.c b/src/test/test_hs_metrics.c
new file mode 100644
index 0000000000..326212ae1d
--- /dev/null
+++ b/src/test/test_hs_metrics.c
@@ -0,0 +1,68 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file test_hs_metrics.c
+ * \brief Test hidden service metrics.
+ */
+
+#define HS_SERVICE_PRIVATE
+
+#include "test/test.h"
+#include "test/test_helpers.h"
+#include "test/log_test_helpers.h"
+
+#include "app/config/config.h"
+
+#include "feature/hs/hs_metrics.h"
+#include "feature/hs/hs_service.h"
+
+#include "lib/crypt_ops/crypto_ed25519.h"
+
+static void
+test_metrics(void *arg)
+{
+ hs_service_t *service = NULL;
+
+ (void) arg;
+
+ hs_init();
+
+ service = hs_service_new(get_options());
+ tt_assert(service);
+ service->config.version = HS_VERSION_THREE;
+ ed25519_secret_key_generate(&service->keys.identity_sk, 0);
+ ed25519_public_key_generate(&service->keys.identity_pk,
+ &service->keys.identity_sk);
+ register_service(get_hs_service_map(), service);
+
+ tt_assert(service->metrics.store);
+
+ /* Update entry by identifier. */
+ hs_metrics_update_by_ident(HS_METRICS_NUM_INTRODUCTIONS,
+ &service->keys.identity_pk, 0, 42);
+
+ /* Confirm the entry value. */
+ const smartlist_t *entries = metrics_store_get_all(service->metrics.store,
+ "tor_hs_intro_num_total");
+ tt_assert(entries);
+ tt_int_op(smartlist_len(entries), OP_EQ, 1);
+ const metrics_store_entry_t *entry = smartlist_get(entries, 0);
+ tt_assert(entry);
+ tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 42);
+
+ /* Update entry by service now. */
+ hs_metrics_update_by_service(HS_METRICS_NUM_INTRODUCTIONS,
+ service, 0, 42);
+ tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 84);
+
+ done:
+ hs_free_all();
+}
+
+struct testcase_t hs_metrics_tests[] = {
+
+ { "metrics", test_metrics, TT_FORK, NULL, NULL },
+
+ END_OF_TESTCASES
+};
diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c
index 8b94bb6cf1..66e8e2f473 100644
--- a/src/test/test_hs_service.c
+++ b/src/test/test_hs_service.c
@@ -54,6 +54,7 @@
#include "feature/hs/hs_ob.h"
#include "feature/hs/hs_cell.h"
#include "feature/hs/hs_intropoint.h"
+#include "feature/hs/hs_metrics.h"
#include "feature/hs/hs_service.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
@@ -160,7 +161,7 @@ mock_router_have_minimum_dir_info_false(void)
}
/* Helper: from a set of options in conf, configure a service which will add
- * it to the staging list of the HS subsytem. */
+ * it to the staging list of the HS subsystem. */
static int
helper_config_service(const char *conf)
{
@@ -666,6 +667,7 @@ test_access_service(void *arg)
tt_mem_op(query, OP_EQ, s, sizeof(hs_service_t));
/* Remove service, check if it actually works and then put it back. */
remove_service(global_map, s);
+ hs_metrics_service_free(s);
tt_int_op(get_hs_service_map_size(), OP_EQ, 0);
query = find_service(global_map, &s->keys.identity_pk);
tt_ptr_op(query, OP_EQ, NULL);
@@ -675,6 +677,7 @@ test_access_service(void *arg)
tt_int_op(ret, OP_EQ, 0);
tt_int_op(get_hs_service_map_size(), OP_EQ, 1);
/* Twice should fail. */
+ hs_metrics_service_free(s); /* Avoid BUG() on metrics init. */
ret = register_service(global_map, s);
tt_int_op(ret, OP_EQ, -1);
/* Remove service from map so we don't double free on cleanup. */
@@ -777,7 +780,7 @@ mock_node_get_by_id(const char *digest)
{
(void) digest;
memset(mock_node.identity, 'A', DIGEST_LEN);
- /* Only return the matchin identity of As */
+ /* Only return the matching identity of As */
if (!tor_memcmp(mock_node.identity, digest, DIGEST_LEN)) {
return &mock_node;
}
@@ -1547,14 +1550,12 @@ test_build_update_descriptors(void *arg)
/* Now, we'll setup a node_t. */
{
- tor_addr_t ipv4_addr;
curve25519_secret_key_t curve25519_secret_key;
memset(&ri, 0, sizeof(routerinfo_t));
- tor_addr_parse(&ipv4_addr, "127.0.0.1");
- ri.addr = tor_addr_to_ipv4h(&ipv4_addr);
- ri.or_port = 1337;
+ tor_addr_parse(&ri.ipv4_addr, "127.0.0.1");
+ ri.ipv4_orport = 1337;
ri.purpose = ROUTER_PURPOSE_GENERAL;
/* Ugly yes but we never free the "ri" object so this just makes things
* easier. */
@@ -1621,7 +1622,7 @@ test_build_update_descriptors(void *arg)
/* We won't test the service IP object because there is a specific test
* already for this but we'll make sure that the state is coherent.*/
- /* Three link specifiers are mandatoy so make sure we do have them. */
+ /* Three link specifiers are mandatory so make sure we do have them. */
tt_int_op(smartlist_len(ip_cur->base.link_specifiers), OP_EQ, 3);
/* Make sure we have a valid encryption keypair generated when we pick an
* intro point in the update process. */
diff --git a/src/test/test_include.py b/src/test/test_include.py
new file mode 100644
index 0000000000..ec261da86c
--- /dev/null
+++ b/src/test/test_include.py
@@ -0,0 +1,196 @@
+# 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
+import os
+import random
+import socket
+import subprocess
+import sys
+import time
+import re
+
+CONTROL_SOCK_TIMEOUT = 10.0
+LOG_TIMEOUT = 60.0
+LOG_WAIT = 0.1
+
+def fail(msg):
+ logging.error('FAIL')
+ sys.exit(msg)
+
+def skip(msg):
+ logging.warning('SKIP: {}'.format(msg))
+ sys.exit(77)
+
+def wait_for_log(s):
+ cutoff = time.time() + LOG_TIMEOUT
+ while time.time() < cutoff:
+ l = tor_process.stdout.readline()
+ l = l.decode('utf8', 'backslashreplace')
+ if s in l:
+ logging.info('Tor logged: "{}"'.format(l.strip()))
+ return
+ # readline() returns a blank string when there is no output
+ # avoid busy-waiting
+ if len(l) == 0:
+ logging.debug('Tor has not logged anything, waiting for "{}"'.format(s))
+ time.sleep(LOG_WAIT)
+ else:
+ logging.info('Tor logged: "{}", waiting for "{}"'.format(l.strip(), s))
+ fail('Could not find "{}" in logs after {} seconds'.format(s, LOG_TIMEOUT))
+
+def pick_random_port():
+ port = 0
+ random.seed()
+
+ for i in range(8):
+ port = random.randint(10000, 60000)
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ if s.connect_ex(('127.0.0.1', port)) == 0:
+ s.close()
+ else:
+ break
+
+ if port == 0:
+ fail('Could not find a random free port between 10000 and 60000')
+
+ return port
+
+def check_control_list(control_out_file, expected, value_name):
+ received_count = 0
+ for e in expected:
+ received = control_out_file.readline().strip()
+ received_count += 1
+ parts = re.split('[ =-]', received.strip())
+ if len(parts) != 3 or parts[0] != '250' or parts[1] != value_name or parts[2] != e:
+ fail('Unexpected value in response line "{}". Expected {} for value {}'.format(received, e, value_name))
+ if received.startswith('250 '):
+ break
+
+ if received_count != len(expected):
+ fail('Expected response with {} lines but received {} lines'.format(len(expected), received_count))
+
+
+logging.basicConfig(level=logging.DEBUG,
+ format='%(asctime)s.%(msecs)03d %(message)s',
+ datefmt='%Y-%m-%d %H:%M:%S')
+
+if sys.hexversion < 0x02070000:
+ fail("ERROR: unsupported Python version (should be >= 2.7)")
+
+if sys.hexversion > 0x03000000 and sys.hexversion < 0x03010000:
+ fail("ERROR: unsupported Python3 version (should be >= 3.1)")
+
+if 'TOR_SKIP_TEST_INCLUDE' in os.environ:
+ skip('$TOR_SKIP_TEST_INCLUDE is set')
+
+control_port = pick_random_port()
+
+assert control_port != 0
+
+if len(sys.argv) < 4:
+ fail('Usage: %s <path-to-tor> <data-dir> <torrc>' % sys.argv[0])
+
+if not os.path.exists(sys.argv[1]):
+ fail('ERROR: cannot find tor at %s' % sys.argv[1])
+if not os.path.exists(sys.argv[2]):
+ fail('ERROR: cannot find datadir at %s' % sys.argv[2])
+if not os.path.exists(sys.argv[3]):
+ fail('ERROR: cannot find torrcdir at %s' % sys.argv[3])
+
+tor_path = sys.argv[1]
+data_dir = sys.argv[2]
+torrc_dir = sys.argv[3]
+
+empty_torrc_path = os.path.join(data_dir, 'empty_torrc')
+open(empty_torrc_path, 'w').close()
+empty_defaults_torrc_path = os.path.join(data_dir, 'empty_defaults_torrc')
+open(empty_defaults_torrc_path, 'w').close()
+torrc = os.path.join(torrc_dir, 'torrc')
+
+tor_process = subprocess.Popen([tor_path,
+ '-DataDirectory', data_dir,
+ '-ControlPort', '127.0.0.1:{}'.format(control_port),
+ '-Log', 'info stdout',
+ '-LogTimeGranularity', '1',
+ '-FetchServerDescriptors', '0',
+ '-DisableNetwork', '1',
+ '-f', torrc,
+ '--defaults-torrc', empty_defaults_torrc_path,
+ ],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+if tor_process == None:
+ fail('ERROR: running tor failed')
+
+wait_for_log('Opened Control listener')
+
+control_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+if control_socket.connect_ex(('127.0.0.1', control_port)):
+ tor_process.terminate()
+ fail('Cannot connect to ControlPort')
+control_socket.settimeout(CONTROL_SOCK_TIMEOUT)
+control_out_file = control_socket.makefile('r')
+
+control_socket.sendall('AUTHENTICATE \r\n'.encode('ascii'))
+res = control_out_file.readline().strip()
+if res != '250 OK':
+ tor_process.terminate()
+ fail('Cannot authenticate. Response was: {}'.format(res))
+
+# test configuration file values and order
+control_socket.sendall('GETCONF NodeFamily\r\n'.encode('ascii'))
+check_control_list(control_out_file, ['1', '2', '3', '4', '5', '6', '4' , '5'], 'NodeFamily')
+
+# test reloading the configuration file with seccomp sandbox enabled
+foo_path = os.path.join(torrc_dir, 'torrc.d', 'foo')
+with open(foo_path, 'a') as foo:
+ foo.write('NodeFamily 7')
+
+control_socket.sendall('SIGNAL RELOAD\r\n'.encode('ascii'))
+wait_for_log('Reloading config and resetting internal state.')
+res = control_out_file.readline().strip()
+if res != '250 OK':
+ tor_process.terminate()
+ fail('Cannot reload configuration. Response was: {}'.format(res))
+
+
+control_socket.sendall('GETCONF NodeFamily\r\n'.encode('ascii'))
+check_control_list(control_out_file, ['1', '2', '3', '4', '5', '6', '7', '4' , '5'], 'NodeFamily')
+
+# test that config-can-saveconf is 0 because we have a %include
+control_socket.sendall('getinfo config-can-saveconf\r\n'.encode('ascii'))
+res = control_out_file.readline().strip()
+if res != '250-config-can-saveconf=0':
+ tor_process.terminate()
+ fail('getinfo config-can-saveconf returned wrong response: {}'.format(res))
+else:
+ res = control_out_file.readline().strip()
+ if res != '250 OK':
+ tor_process.terminate()
+ fail('getinfo failed. Response was: {}'.format(res))
+
+# test that saveconf returns error because we have a %include
+control_socket.sendall('SAVECONF\r\n'.encode('ascii'))
+res = control_out_file.readline().strip()
+if res != '551 Unable to write configuration to disk.':
+ tor_process.terminate()
+ fail('SAVECONF returned wrong response. Response was: {}'.format(res))
+
+control_socket.sendall('SIGNAL HALT\r\n'.encode('ascii'))
+
+wait_for_log('exiting cleanly')
+logging.info('OK')
+
+try:
+ tor_process.terminate()
+except OSError as e:
+ if e.errno == errno.ESRCH: # errno 3: No such process
+ # assume tor has already exited due to SIGNAL HALT
+ logging.warn("Tor has already exited")
+ else:
+ raise
diff --git a/src/test/test_include.sh b/src/test/test_include.sh
new file mode 100755
index 0000000000..6cf695fe44
--- /dev/null
+++ b/src/test/test_include.sh
@@ -0,0 +1,111 @@
+#!/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' || \
+ test "$UNAME_OS" = 'MINGW' || \
+ test "$UNAME_OS" = 'MINGW32' || \
+ test "$UNAME_OS" = 'MINGW64'; then
+ if test "$APPVEYOR" = 'True'; then
+ echo "This test is disabled on Windows CI, as it requires firewall exemptions. Skipping." >&2
+ exit 77
+ 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
+ rm -rf "$tmpdir"
+ fi
+}
+
+trap clean EXIT HUP INT TERM
+
+tmpdir="$(mktemp -d -t tor_include_test.XXXXXX)"
+if [ -z "$tmpdir" ]; then
+ echo >&2 mktemp failed
+ exit 2
+elif [ ! -d "$tmpdir" ]; then
+ echo >&2 mktemp failed to make a directory
+ exit 3
+fi
+
+datadir="$tmpdir/data"
+mkdir "$datadir"
+
+configdir="$tmpdir/config"
+mkdir "$configdir"
+
+# translate paths to windows format
+if test "$UNAME_OS" = 'CYGWIN' || \
+ test "$UNAME_OS" = 'MSYS' || \
+ test "$UNAME_OS" = 'MINGW' || \
+ test "$UNAME_OS" = 'MINGW32' || \
+ test "$UNAME_OS" = 'MINGW64'; then
+ datadir=$(cygpath --windows "$datadir")
+ configdir=$(cygpath --windows "$configdir")
+fi
+
+# create test folder structure in configdir
+torrcd="$configdir/torrc.d"
+mkdir "$torrcd"
+mkdir "$torrcd/folder"
+mkdir "$torrcd/empty_folder"
+echo "NodeFamily 1" > "$torrcd/01_one.conf"
+echo "NodeFamily 2" > "$torrcd/02_two.conf"
+echo "NodeFamily 3" > "$torrcd/aa_three.conf"
+echo "NodeFamily 42" > "$torrcd/.hidden.conf"
+echo "NodeFamily 6" > "$torrcd/foo"
+touch "$torrcd/empty.conf"
+echo "# comment" > "$torrcd/comment.conf"
+echo "NodeFamily 4" > "$torrcd/folder/04_four.conf"
+echo "NodeFamily 5" > "$torrcd/folder/05_five.conf"
+torrc="$configdir/torrc"
+echo "Sandbox 1" > "$torrc"
+echo "
+%include $torrcd/*.conf
+%include $torrcd/f*
+%include $torrcd/*/*
+%include $torrcd/empty_folder
+%include $torrcd/empty.conf
+%include $torrcd/comment.conf
+" >> "$torrc"
+
+"${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/test_include.py" "${TOR_BINARY}" "$datadir" "$configdir"
+
+exit $?
diff --git a/src/test/test_key_expiration.sh b/src/test/test_key_expiration.sh
index 2238f7aa78..1ba8179aa1 100755
--- a/src/test/test_key_expiration.sh
+++ b/src/test/test_key_expiration.sh
@@ -61,6 +61,11 @@ fi
CASE1=$dflt
CASE2=$dflt
CASE3=$dflt
+CASE4=$dflt
+CASE5=$dflt
+CASE6=$dflt
+CASE7=$dflt
+CASE8=$dflt
if [ $# -ge 1 ]; then
eval "CASE${1}"=1
@@ -125,16 +130,17 @@ if [ "$CASE1" = 1 ]; then
${TOR} ${QUIETLY} --key-expiration 2>"$FN" || true
grep "No valid argument to --key-expiration found!" "$FN" >/dev/null || \
- die "Tor didn't mention supported --key-expiration argmuents"
+ die "Tor didn't mention supported --key-expiration arguments"
echo "==== Case 1: ok"
fi
if [ "$CASE2" = 1 ]; then
- echo "==== Case 2: Start Tor with --key-expiration 'sign' and make sure it prints an expiration."
+ echo "==== Case 2: Start Tor with --key-expiration 'sign' and make sure it"
+ echo " prints an expiration using ISO8601 date format."
${TOR} ${QUIETLY} --key-expiration sign 2>"$FN"
- grep "signing-cert-expiry:" "$FN" >/dev/null || \
+ grep "signing-cert-expiry: [0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\} [0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}" "$FN" >/dev/null || \
die "Tor didn't print an expiration"
echo "==== Case 2: ok"
@@ -160,3 +166,61 @@ if [ "$CASE3" = 1 ]; then
echo "==== Case 3: ok"
fi
+
+if [ "$CASE4" = 1 ]; then
+ echo "==== Case 4: Start Tor with --format iso8601 and make sure it prints an"
+ echo " error message due to missing --key-expiration argument."
+
+ ${TOR} --format iso8601 > "$FN" 2>&1 || true
+ grep -- "--format specified without --key-expiration!" "$FN" >/dev/null || \
+ die "Tor didn't print a missing --key-expiration error message"
+
+ echo "==== Case 4: ok"
+fi
+
+if [ "$CASE5" = 1 ]; then
+ echo "==== Case 5: Start Tor with --key-expiration 'sign' --format '' and"
+ echo " make sure it prints an error message due to missing value."
+
+ ${TOR} --key-expiration sign --format > "$FN" 2>&1 || true
+ grep "Command-line option '--format' with no value. Failing." "$FN" >/dev/null || \
+ die "Tor didn't print a missing format value error message"
+
+ echo "==== Case 5: ok"
+fi
+
+if [ "$CASE6" = 1 ]; then
+ echo "==== Case 6: Start Tor with --key-expiration 'sign' --format 'invalid'"
+ echo " and make sure it prints an error message due to invalid"
+ echo " value."
+
+ ${TOR} --key-expiration sign --format invalid > "$FN" 2>&1 || true
+ grep "Invalid --format value" "$FN" >/dev/null || \
+ die "Tor didn't print an invalid format value error message"
+
+ echo "==== Case 6: ok"
+fi
+
+if [ "$CASE7" = 1 ]; then
+ echo "==== Case 7: Start Tor with --key-expiration 'sign' --format 'iso8601'"
+ echo " and make sure it prints an expiration using ISO8601 date"
+ echo " format."
+
+ ${TOR} ${QUIETLY} --key-expiration sign --format iso8601 2>"$FN"
+ grep "signing-cert-expiry: [0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\} [0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}" "$FN" >/dev/null || \
+ die "Tor didn't print an expiration"
+
+ echo "==== Case 7: ok"
+fi
+
+if [ "$CASE8" = 1 ]; then
+ echo "==== Case 8: Start Tor with --key-expiration 'sign' --format 'timestamp'"
+ echo " and make sure it prints an expiration using timestamp date"
+ echo " format."
+
+ ${TOR} ${QUIETLY} --key-expiration sign --format timestamp 2>"$FN"
+ grep "signing-cert-expiry: [0-9]\{5,\}" "$FN" >/dev/null || \
+ die "Tor didn't print an expiration"
+
+ echo "==== Case 8: ok"
+fi
diff --git a/src/test/test_link_handshake.c b/src/test/test_link_handshake.c
index 1566b349ed..06af299056 100644
--- a/src/test/test_link_handshake.c
+++ b/src/test/test_link_handshake.c
@@ -710,7 +710,7 @@ CERTS_FAIL(missing_signing_key, /* ed25519 */
* signing key. */
const ed25519_keypair_t *mk = get_master_identity_keypair();
const ed25519_keypair_t *sk = get_master_signing_keypair();
- tor_cert_t *bad_cert = tor_cert_create(mk, CERT_TYPE_ID_SIGNING,
+ tor_cert_t *bad_cert = tor_cert_create_ed25519(mk, CERT_TYPE_ID_SIGNING,
&sk->pubkey, time(NULL), 86400,
0 /* don't include signer */);
certs_cell_cert_setlen_body(cert, bad_cert->encoded_len);
diff --git a/src/test/test_logging.c b/src/test/test_logging.c
index e09f7a21cd..58d0f24bd3 100644
--- a/src/test/test_logging.c
+++ b/src/test/test_logging.c
@@ -160,6 +160,7 @@ test_ratelim(void *arg)
tor_free(msg);
int i;
+ time_t first_suppressed_at = now + 60;
for (i = 0; i < 9; ++i) {
now += 60; /* one minute has passed. */
msg = rate_limit_log(&ten_min, now);
@@ -167,12 +168,15 @@ test_ratelim(void *arg)
tt_int_op(ten_min.last_allowed, OP_EQ, start);
tt_int_op(ten_min.n_calls_since_last_time, OP_EQ, i + 1);
}
+ tt_i64_op(ten_min.started_limiting, OP_EQ, first_suppressed_at);
now += 240; /* Okay, we can be done. */
msg = rate_limit_log(&ten_min, now);
tt_ptr_op(msg, OP_NE, NULL);
tt_str_op(msg, OP_EQ,
- " [9 similar message(s) suppressed in last 600 seconds]");
+ " [9 similar message(s) suppressed in last 720 seconds]");
+ tt_i64_op(now, OP_EQ, first_suppressed_at + 720);
+
done:
tor_free(msg);
}
diff --git a/src/test/test_metrics.c b/src/test/test_metrics.c
new file mode 100644
index 0000000000..152dd99d23
--- /dev/null
+++ b/src/test/test_metrics.c
@@ -0,0 +1,277 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file test_metrics.c
+ * \brief Test lib/metrics and feature/metrics functionalities
+ */
+
+#define CONFIG_PRIVATE
+#define CONNECTION_PRIVATE
+#define MAINLOOP_PRIVATE
+#define METRICS_STORE_ENTRY_PRIVATE
+
+#include "test/test.h"
+#include "test/test_helpers.h"
+#include "test/log_test_helpers.h"
+
+#include "app/config/config.h"
+
+#include "core/mainloop/connection.h"
+#include "core/mainloop/mainloop.h"
+#include "core/or/connection_st.h"
+#include "core/or/policies.h"
+#include "core/or/port_cfg_st.h"
+
+#include "feature/metrics/metrics.h"
+
+#include "lib/encoding/confline.h"
+#include "lib/metrics/metrics_store.h"
+
+#define TEST_METRICS_ENTRY_NAME "entryA"
+#define TEST_METRICS_ENTRY_HELP "Description of entryA"
+#define TEST_METRICS_ENTRY_LABEL_1 "label=farfadet"
+#define TEST_METRICS_ENTRY_LABEL_2 "label=ponki"
+
+static void
+set_metrics_port(or_options_t *options)
+{
+ const char *port = "MetricsPort 9035"; /* Default to 127.0.0.1 */
+ const char *policy = "MetricsPortPolicy accept 1.2.3.4";
+
+ config_get_lines(port, &options->MetricsPort_lines, 0);
+ config_get_lines(policy, &options->MetricsPortPolicy, 0);
+
+ /* Parse and validate policy. */
+ policies_parse_from_options(options);
+}
+
+static void
+test_config(void *arg)
+{
+ char *err_msg = NULL;
+ tor_addr_t addr;
+ smartlist_t *ports = smartlist_new();
+ or_options_t *options = get_options_mutable();
+
+ (void) arg;
+
+ set_metrics_port(options);
+
+ int ret = metrics_parse_ports(options, ports, &err_msg);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(smartlist_len(ports), OP_EQ, 1);
+
+ /* Validate the configured port. */
+ const port_cfg_t *cfg = smartlist_get(ports, 0);
+ tt_assert(tor_addr_eq_ipv4h(&cfg->addr, 0x7f000001));
+ tt_int_op(cfg->port, OP_EQ, 9035);
+ tt_int_op(cfg->type, OP_EQ, CONN_TYPE_METRICS_LISTENER);
+
+ /* Address of the policy should be permitted. */
+ tor_addr_from_ipv4h(&addr, 0x01020304); /* 1.2.3.4 */
+ ret = metrics_policy_permits_address(&addr);
+ tt_int_op(ret, OP_EQ, true);
+
+ /* Anything else, should not. */
+ tor_addr_from_ipv4h(&addr, 0x01020305); /* 1.2.3.5 */
+ ret = metrics_policy_permits_address(&addr);
+ tt_int_op(ret, OP_EQ, false);
+
+ done:
+ SMARTLIST_FOREACH(ports, port_cfg_t *, c, port_cfg_free(c));
+ smartlist_free(ports);
+ or_options_free(options);
+ tor_free(err_msg);
+}
+
+static char _c_buf[256];
+#define CONTAINS(conn, msg) \
+ do { \
+ tt_int_op(buf_datalen(conn->outbuf), OP_EQ, (strlen(msg))); \
+ memset(_c_buf, 0, sizeof(_c_buf)); \
+ buf_get_bytes(conn->outbuf, _c_buf, (strlen(msg))); \
+ tt_str_op(_c_buf, OP_EQ, (msg)); \
+ tt_int_op(buf_datalen(conn->outbuf), OP_EQ, 0); \
+ } while (0)
+
+#define WRITE(conn, msg) \
+ buf_add(conn->inbuf, (msg), (strlen(msg)));
+
+/* Free the previous conn object if any and allocate a new connection. In
+ * order to be allowed, set its address to 1.2.3.4 as per the policy. */
+#define NEW_ALLOWED_CONN() \
+ do { \
+ close_closeable_connections(); \
+ conn = connection_new(CONN_TYPE_METRICS, AF_INET); \
+ tor_addr_from_ipv4h(&conn->addr, 0x01020304); \
+ } while (0)
+
+static void
+test_connection(void *arg)
+{
+ int ret;
+ connection_t *conn = NULL;
+ or_options_t *options = get_options_mutable();
+
+ (void) arg;
+
+ /* Notice that in this test, we will allocate a new connection at every test
+ * case. This is because the metrics_connection_process_inbuf() marks for
+ * close the connection in case of an error and thus we can't call again an
+ * inbuf process function on a marked for close connection. */
+
+ tor_init_connection_lists();
+
+ /* Setup policy. */
+ set_metrics_port(options);
+
+ /* Set 1.2.3.5 IP, we should get rejected. */
+ NEW_ALLOWED_CONN();
+ tor_addr_from_ipv4h(&conn->addr, 0x01020305);
+ ret = metrics_connection_process_inbuf(conn);
+ tt_int_op(ret, OP_EQ, -1);
+
+ /* No HTTP request yet. */
+ NEW_ALLOWED_CONN();
+ ret = metrics_connection_process_inbuf(conn);
+ tt_int_op(ret, OP_EQ, 0);
+ connection_free_minimal(conn);
+
+ /* Bad request. */
+ NEW_ALLOWED_CONN();
+ WRITE(conn, "HTTP 4.7\r\n\r\n");
+ ret = metrics_connection_process_inbuf(conn);
+ tt_int_op(ret, OP_EQ, -1);
+ CONTAINS(conn, "HTTP/1.0 400 Bad Request\r\n\r\n");
+
+ /* Path not found. */
+ NEW_ALLOWED_CONN();
+ WRITE(conn, "GET /badpath HTTP/1.0\r\n\r\n");
+ ret = metrics_connection_process_inbuf(conn);
+ tt_int_op(ret, OP_EQ, -1);
+ CONTAINS(conn, "HTTP/1.0 404 Not Found\r\n\r\n");
+
+ /* Method not allowed. */
+ NEW_ALLOWED_CONN();
+ WRITE(conn, "POST /something HTTP/1.0\r\n\r\n");
+ ret = metrics_connection_process_inbuf(conn);
+ tt_int_op(ret, OP_EQ, -1);
+ CONTAINS(conn, "HTTP/1.0 405 Method Not Allowed\r\n\r\n");
+
+ /* Ask for metrics. The content should be above 0. We don't test the
+ * validity of the returned content but it is certainly not an error. */
+ NEW_ALLOWED_CONN();
+ WRITE(conn, "GET /metrics HTTP/1.0\r\n\r\n");
+ ret = metrics_connection_process_inbuf(conn);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(buf_datalen(conn->outbuf), OP_GT, 0);
+
+ done:
+ or_options_free(options);
+ connection_free_minimal(conn);
+}
+
+static void
+test_prometheus(void *arg)
+{
+ metrics_store_t *store = NULL;
+ metrics_store_entry_t *entry = NULL;
+ buf_t *buf = buf_new();
+ char *output = NULL;
+
+ (void) arg;
+
+ /* Fresh new store. No entries. */
+ store = metrics_store_new();
+ tt_assert(store);
+
+ /* Add entry and validate its content. */
+ entry = metrics_store_add(store, METRICS_TYPE_COUNTER,
+ TEST_METRICS_ENTRY_NAME,
+ TEST_METRICS_ENTRY_HELP);
+ tt_assert(entry);
+ metrics_store_entry_add_label(entry, TEST_METRICS_ENTRY_LABEL_1);
+
+ static const char *expected =
+ "# HELP " TEST_METRICS_ENTRY_NAME " " TEST_METRICS_ENTRY_HELP "\n"
+ "# TYPE " TEST_METRICS_ENTRY_NAME " counter\n"
+ TEST_METRICS_ENTRY_NAME "{" TEST_METRICS_ENTRY_LABEL_1 "} 0\n";
+
+ metrics_store_get_output(METRICS_FORMAT_PROMETHEUS, store, buf);
+ output = buf_extract(buf, NULL);
+ tt_str_op(expected, OP_EQ, output);
+
+ done:
+ buf_free(buf);
+ tor_free(output);
+ metrics_store_free(store);
+}
+
+static void
+test_store(void *arg)
+{
+ metrics_store_t *store = NULL;
+ metrics_store_entry_t *entry = NULL;
+
+ (void) arg;
+
+ /* Fresh new store. No entries. */
+ store = metrics_store_new();
+ tt_assert(store);
+ tt_assert(!metrics_store_get_all(store, TEST_METRICS_ENTRY_NAME));
+
+ /* Add entry and validate its content. */
+ entry = metrics_store_add(store, METRICS_TYPE_COUNTER,
+ TEST_METRICS_ENTRY_NAME,
+ TEST_METRICS_ENTRY_HELP);
+ tt_assert(entry);
+ tt_int_op(entry->type, OP_EQ, METRICS_TYPE_COUNTER);
+ tt_str_op(entry->name, OP_EQ, TEST_METRICS_ENTRY_NAME);
+ tt_str_op(entry->help, OP_EQ, TEST_METRICS_ENTRY_HELP);
+ tt_uint_op(entry->u.counter.value, OP_EQ, 0);
+
+ /* Access the entry. */
+ tt_assert(metrics_store_get_all(store, TEST_METRICS_ENTRY_NAME));
+
+ /* Add a label to the entry to make it unique. */
+ metrics_store_entry_add_label(entry, TEST_METRICS_ENTRY_LABEL_1);
+ tt_int_op(metrics_store_entry_has_label(entry, TEST_METRICS_ENTRY_LABEL_1),
+ OP_EQ, true);
+
+ /* Update entry's value. */
+ metrics_store_entry_update(entry, 42);
+ tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 42);
+ metrics_store_entry_update(entry, 42);
+ tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 84);
+ metrics_store_entry_reset(entry);
+ tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 0);
+
+ /* Add a new entry of same name but different label. */
+ /* Add entry and validate its content. */
+ entry = metrics_store_add(store, METRICS_TYPE_COUNTER,
+ TEST_METRICS_ENTRY_NAME,
+ TEST_METRICS_ENTRY_HELP);
+ tt_assert(entry);
+ metrics_store_entry_add_label(entry, TEST_METRICS_ENTRY_LABEL_2);
+
+ /* Make sure _both_ entries are there. */
+ const smartlist_t *entries =
+ metrics_store_get_all(store, TEST_METRICS_ENTRY_NAME);
+ tt_assert(entries);
+ tt_int_op(smartlist_len(entries), OP_EQ, 2);
+
+ done:
+ metrics_store_free(store);
+}
+
+struct testcase_t metrics_tests[] = {
+
+ { "config", test_config, TT_FORK, NULL, NULL },
+ { "connection", test_connection, TT_FORK, NULL, NULL },
+ { "prometheus", test_prometheus, TT_FORK, NULL, NULL },
+ { "store", test_store, TT_FORK, NULL, NULL },
+
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c
index f89025aa6c..6bd1f56859 100644
--- a/src/test/test_microdesc.c
+++ b/src/test/test_microdesc.c
@@ -40,7 +40,8 @@ static const char test_md1[] =
"MIGJAoGBAMjlHH/daN43cSVRaHBwgUfnszzAhg98EvivJ9Qxfv51mvQUxPjQ07es\n"
"gV/3n8fyh3Kqr/ehi9jxkdgSRfSnmF7giaHL1SLZ29kA7KtST+pBvmTpDtHa3ykX\n"
"Xorc7hJvIyTZoc1HU+5XSynj3gsBE5IGK1ZRzrNS688LnuZMVp1tAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n";
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n";
static const char test_md2[] =
"onion-key\n"
@@ -48,7 +49,8 @@ static const char test_md2[] =
"MIGJAoGBAMIixIowh2DyPmDNMDwBX2DHcYcqdcH1zdIQJZkyV6c6rQHnvbcaDoSg\n"
"jgFSLJKpnGmh71FVRqep+yVB0zI1JY43kuEnXry2HbZCD9UDo3d3n7t015X5S7ON\n"
"bSSYtQGPwOr6Epf96IF6DoQxy4iDnPUAlejuhAG51s1y6/rZQ3zxAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n";
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n";
static const char test_md3[] =
"@last-listed 2009-06-22\n"
@@ -58,6 +60,7 @@ static const char test_md3[] =
"qj2fRZzfxlc88G/tmiaHshmdtEpklZ740OFqaaJVj4LjPMKFNE+J7Xc1142BE9Ci\n"
"KgsbjGYe2RY261aADRWLetJ8T9QDMm+JngL4288hc8pq1uB/3TAbAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n"
"p accept 1-700,800-1000\n"
"family nodeX nodeY nodeZ\n";
@@ -309,140 +312,94 @@ test_md_cache_broken(void *data)
/* Generated by chutney. */
static const char test_ri[] =
"router test005r 127.0.0.1 5005 0 7005\n"
- "platform Tor 0.2.5.4-alpha-dev on Linux\n"
- "protocols Link 1 2 Circuit 1\n"
- "published 2014-05-06 22:57:55\n"
- "fingerprint 09DE 3BA2 48C2 1C3F 3760 6CD3 8460 43A6 D5EC F59E\n"
- "uptime 0\n"
- "bandwidth 1073741824 1073741824 0\n"
- "extra-info-digest 361F9428F9FA4DD854C03DDBCC159D0D9FA996C9\n"
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n"
- "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n"
- "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "signing-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANbGUC4802Ke6C3nOVxN0U0HhIRrs32cQFEL4v+UUMJPgjbistHBvOax\n"
- "CWVR/sMXM2kKJeGThJ9ZUs2p9dDG4WHPUXgkMqzTTEeeFa7pQKU0brgbmLaJq0Pi\n"
- "mxmqC5RkTHa5bQvq6QlSFprAEoovV27cWqBM9jVdV9hyc//6kwPzAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "hidden-service-dir\n"
- "ntor-onion-key Gg73xH7+kTfT6bi1uNVx9gwQdQas9pROIfmc4NpAdC4=\n"
- "reject *:25\n"
- "reject *:119\n"
- "reject *:135-139\n"
- "reject *:445\n"
- "reject *:563\n"
- "reject *:1214\n"
- "reject *:4661-4666\n"
- "reject *:6346-6429\n"
- "reject *:6699\n"
- "reject *:6881-6999\n"
- "accept *:*\n"
- "router-signature\n"
- "-----BEGIN SIGNATURE-----\n"
- "ImzX5PF2vRCrG1YzGToyjoxYhgh1vtHEDjmP+tIS/iil1DSnHZNpHSuHp0L1jE9S\n"
- "yZyrtKaqpBE/aecAM3j4CWCn/ipnAAQkHcyRLin1bYvqBtRzyopVCRlUhF+uWrLq\n"
- "t0xkIE39ss/EwmQr7iIgkdVH4oRIMsjYnFFJBG26nYY=\n"
- "-----END SIGNATURE-----\n";
-
-static const char test_ri2[] =
- "router test001a 127.0.0.1 5001 0 7001\n"
"identity-ed25519\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQQABf/FAf5iDuKCZP2VxnAaQWdklilAh6kaEeFX4z8261Yx2T1/AQAgBADCp8vO\n"
- "B8K1F9g2DzwuwvVCnPFLSK1qknVqPpNucHLH9DY7fuIYogBAdz4zHv1qC7RKaMNG\n"
- "Jux/tMO2tzPcm62Ky5PjClMQplKUOnZNQ+RIpA3wYCIfUDy/cQnY7XWgNQ0=\n"
+ "AQQABs1eAfTuBhu6ypB5/9avDiY3qBzulkCvfYqbFN/ABk/o4xFcAQAgBAAnmWRG\n"
+ "rIvqpb4Kk3cThEiWAll4uDCO2Y46uNm9WG7AtPt4LG+XfktG3GAxv6aVQimwlyHc\n"
+ "1x2Lfm9KG3mWWj+hxnum4Z7873OE0B9l2Hg0YQZCW/PuHSWN0rspTvY5SgA=\n"
"-----END ED25519 CERT-----\n"
- "platform Tor 0.2.6.0-alpha-dev on Darwin\n"
- "protocols Link 1 2 Circuit 1\n"
- "published 2014-10-08 12:58:04\n"
- "fingerprint B7E2 7F10 4213 C36F 13E7 E982 9182 845E 4959 97A0\n"
- "uptime 0\n"
- "bandwidth 1073741824 1073741824 0\n"
- "extra-info-digest 568F27331B6D8C73E7024F1EF5D097B90DFC7CDB\n"
- "caches-extra-info\n"
+ "master-key-ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n"
+ "or-address [::]:5005\n"
+ "platform Tor 0.4.5.0-alpha-dev on Linux\n"
+ "proto Cons=1-2 Desc=1-2 DirCache=1-2 FlowCtrl=1 HSDir=1-2 HSIntro=3-5 "
+ "HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Padding=2 Relay=1-3\n"
+ "published 2020-10-13 13:27:34\n"
+ "fingerprint D219 590A C951 3BCD EBBA 9AB7 2100 7A4C C01B BAE3\n"
+ "uptime 324451\n"
+ "bandwidth 1073741824 1073741824 637796\n"
+ "extra-info-digest 78E6D382BC826B95B4111554EEE7D541A32AAAA3 "
+ "c61Onjpq+1S0TrdvoaOvGAxew6yfO+uHNhipbemQmgA\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAL2R8EfubUcahxha4u02P4VAR0llQIMwFAmrHPjzcK7apcQgDOf2ovOA\n"
- "+YQnJFxlpBmCoCZC6ssCi+9G0mqo650lFuTMP5I90BdtjotfzESfTykHLiChyvhd\n"
- "l0dlqclb2SU/GKem/fLRXH16aNi72CdSUu/1slKs/70ILi34QixRAgMBAAE=\n"
+ "MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n"
+ "83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n"
+ "nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAN8+78KUVlgHXdMMkYJxcwh1Zv2y+Gb5eWUyltUaQRajhrT9ij2T5JZs\n"
- "M0g85xTcuM3jNVVpV79+33hiTohdC6UZ+Bk4USQ7WBFzRbVFSXoVKLBJFkCOIexg\n"
- "SMGNd5WEDtHWrXl58mizmPFu1eG6ZxHzt7RuLSol5cwBvawXPNkFAgMBAAE=\n"
+ "MIGJAoGBANBzejGAwyPTPq2Gm03wpg3qICo0uDQau8opude2mW3eyxAqOqHzC8De\n"
+ "gRgbmn040vqe9gwvH4iaHpVeTxyDwQefbfULdq6bETmX3aSUj6LKBCqqcyuOJFQu\n"
+ "7M2QfNSfHtldUABpIaqFvEA3AV8qjOoUtauoFNJKMy7Wj2//S70VAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key-crosscert\n"
"-----BEGIN CROSSCERT-----\n"
- "ETFDzU49bvNfoZnKK1j6JeBP2gDirgj6bBCgWpUYs663OO9ypbZRO0JwWANssKl6\n"
- "oaq9vKTsKGRsaNnqnz/JGMhehymakjjNtqg7crWwsahe8+7Pw9GKmW+YjFtcOkUf\n"
- "KfOn2bmKBa1FoJb4yW3oXzHcdlLSRuCciKqPn+Hky5o=\n"
+ "pD3Nkkunt8zP6PO6H3uHT0t7xnorC7cY/KfF75mFB+90pHCD9f0Xdu3Pjrur/q23\n"
+ "PIKV3hdtdsODoJuoh8LPGNAjS5rO6HMCtHNDNunNOs69bvfaO0jThnurXmOpY0sW\n"
+ "eRfBeYN2KNgrN0B1eDejfPSr03dkFY48yoUDROv9EJQ=\n"
"-----END CROSSCERT-----\n"
"ntor-onion-key-crosscert 0\n"
"-----BEGIN ED25519 CERT-----\n"
- "AQoABf2dAcKny84HwrUX2DYPPC7C9UKc8UtIrWqSdWo+k25wcsf0AFohutG+xI06\n"
- "Ef21c5Zl1j8Hw6DzHDjYyJevXLFuOneaL3zcH2Ldn4sjrG3kc5UuVvRfTvV120UO\n"
- "xk4f5s5LGwY=\n"
+ "AQoABs2OASeZZEasi+qlvgqTdxOESJYCWXi4MI7Zjjq42b1YbsC0AKc5y5qYUYvw\n"
+ "VATtWkV9DVIZbZSb9mQP5pmNaqmX+DbmINCYt8j7l+U7g3ftUyh0Wlrgevx0pFUI\n"
+ "RcIU0HKHZQA=\n"
"-----END ED25519 CERT-----\n"
"hidden-service-dir\n"
- "contact auth1@test.test\n"
- "ntor-onion-key hbxdRnfVUJJY7+KcT4E3Rs7/zuClbN3hJrjSBiEGMgI=\n"
- "reject *:*\n"
- "router-sig-ed25519 5aQXyTif7PExIuL2di37UvktmJECKnils2OWz2vDi"
- "hFxi+5TTAAPxYkS5clhc/Pjvw34itfjGmTKFic/8httAQ\n"
+ "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA\n"
+ "accept *:*\n"
+ "tunnelled-dir-server\n"
+ "router-sig-ed25519 Xm56dYbo/hCHWyzcdUPmfTeZ4qly2TYf1/2Q1lXKQDMJyBti"
+ "8ZE8R2TTYsYimr+UtAapbzBItccZLze505nhBw\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "BaUB+aFPQbb3BwtdzKsKqV3+6cRlSqJF5bI3UTmwRoJk+Z5Pz+W5NWokNI0xArHM\n"
- "T4T5FZCCP9350jXsUCIvzyIyktU6aVRCGFt76rFlo1OETpN8GWkMnQU0w18cxvgS\n"
- "cf34GXHv61XReJF3AlzNHFpbrPOYmowmhrTULKyMqow=\n"
+ "bbeN0lq6nCfJQXGcKa1M9TQ6b2upig7clrlVXuzKeR0JhGwnDCXUAFxDtrw3vkVo\n"
+ "ExBXXvJeBPyustFOQkdiAEWHHSW5CwEgeVCBYZeEnaiySIgDVKuu+9B53ezFdC0Y\n"
+ "iFJkKxxDx7ksxX0zdl7aPT4ORFEuRhCYS6el7YJmoyg=\n"
"-----END SIGNATURE-----\n";
-static const char test_md_18[] =
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n"
- "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n"
- "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key Gg73xH7+kTfT6bi1uNVx9gwQdQas9pROIfmc4NpAdC4=\n"
- "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"
- "id rsa1024 Cd47okjCHD83YGzThGBDptXs9Z4\n";
-
-static const char test_md2_21[] =
+static const char test_md2_25[] =
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAL2R8EfubUcahxha4u02P4VAR0llQIMwFAmrHPjzcK7apcQgDOf2ovOA\n"
- "+YQnJFxlpBmCoCZC6ssCi+9G0mqo650lFuTMP5I90BdtjotfzESfTykHLiChyvhd\n"
- "l0dlqclb2SU/GKem/fLRXH16aNi72CdSUu/1slKs/70ILi34QixRAgMBAAE=\n"
+ "MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n"
+ "83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n"
+ "nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key hbxdRnfVUJJY7+KcT4E3Rs7/zuClbN3hJrjSBiEGMgI=\n"
- "id ed25519 wqfLzgfCtRfYNg88LsL1QpzxS0itapJ1aj6TbnByx/Q\n";
+ "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA=\n"
+ "p accept 1-65535\n"
+ "id ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n";
static const char test_md2_withfamily_28[] =
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAL2R8EfubUcahxha4u02P4VAR0llQIMwFAmrHPjzcK7apcQgDOf2ovOA\n"
- "+YQnJFxlpBmCoCZC6ssCi+9G0mqo650lFuTMP5I90BdtjotfzESfTykHLiChyvhd\n"
- "l0dlqclb2SU/GKem/fLRXH16aNi72CdSUu/1slKs/70ILi34QixRAgMBAAE=\n"
+ "MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n"
+ "83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n"
+ "nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key hbxdRnfVUJJY7+KcT4E3Rs7/zuClbN3hJrjSBiEGMgI=\n"
+ "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA=\n"
"family OtherNode !Strange\n"
- "id ed25519 wqfLzgfCtRfYNg88LsL1QpzxS0itapJ1aj6TbnByx/Q\n";
+ "p accept 1-65535\n"
+ "id ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n";
static const char test_md2_withfamily_29[] =
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAL2R8EfubUcahxha4u02P4VAR0llQIMwFAmrHPjzcK7apcQgDOf2ovOA\n"
- "+YQnJFxlpBmCoCZC6ssCi+9G0mqo650lFuTMP5I90BdtjotfzESfTykHLiChyvhd\n"
- "l0dlqclb2SU/GKem/fLRXH16aNi72CdSUu/1slKs/70ILi34QixRAgMBAAE=\n"
+ "MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n"
+ "83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n"
+ "nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key hbxdRnfVUJJY7+KcT4E3Rs7/zuClbN3hJrjSBiEGMgI=\n"
- "family !Strange $B7E27F104213C36F13E7E9829182845E495997A0 othernode\n"
- "id ed25519 wqfLzgfCtRfYNg88LsL1QpzxS0itapJ1aj6TbnByx/Q\n";
+ "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA=\n"
+ "family !Strange $D219590AC9513BCDEBBA9AB721007A4CC01BBAE3 othernode\n"
+ "p accept 1-65535\n"
+ "id ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n";
static void
test_md_generate(void *arg)
@@ -454,23 +411,8 @@ test_md_generate(void *arg)
ri = router_parse_entry_from_string(test_ri, NULL, 0, 0, NULL, NULL);
tt_assert(ri);
- microdesc_free(md);
- md = NULL;
- md = dirvote_create_microdescriptor(ri, 18);
- tt_str_op(md->body, OP_EQ, test_md_18);
-
- microdesc_free(md);
- md = NULL;
- md = dirvote_create_microdescriptor(ri, 21);
- tt_str_op(md->body, OP_EQ, test_md_18);
-
- routerinfo_free(ri);
- ri = router_parse_entry_from_string(test_ri2, NULL, 0, 0, NULL, NULL);
-
- microdesc_free(md);
- md = NULL;
- md = dirvote_create_microdescriptor(ri, 21);
- tt_str_op(md->body, OP_EQ, test_md2_21);
+ md = dirvote_create_microdescriptor(ri, 25);
+ tt_str_op(md->body, OP_EQ, test_md2_25);
tt_assert(ed25519_pubkey_eq(md->ed25519_identity_pkey,
&ri->cache_info.signing_key_cert->signing_key));
@@ -505,6 +447,7 @@ static const char MD_PARSE_TEST_DATA[] =
"DBr/ij6+JqgVFeriuiMzHKREytzjdaTuKsKBFFpLwb+Ppcjr5nMIH/AR6/aHO8hW\n"
"T3B9lx5T6Kl7CqZ4yqXxYRHzn50EPTIZuz0y9se4J4gi9mLmL+pHAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n"
"p accept 20-23,43,53,79-81,88,110,143,194,220,443,464,531,543-544\n"
"id rsa1024 GEo59/iR1GWSIWZDzXTd5QxtqnU\n"
/* Bad 0: I've messed with the onion-key in the second one. */
@@ -564,6 +507,7 @@ static const char MD_PARSE_TEST_DATA[] =
"h8G5OJZHRarJQyCIf7vpZQAi0oP0OkGGaCaDQsM+D8TnqhnU++RWGnMqY/cXxPrL\n"
"MEq+n6aGiLmzkO7ah8yorZpoREk4GqLUIN89/tHHGOhJL3c4CPGjAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n"
"p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"
"id rsa1234 jlqAKFD2E7uMKv+8TmKSeo7NBho\n"
/* Good 5: Extra id type. */
@@ -785,6 +729,7 @@ test_md_parse_id_ed25519(void *arg)
"sgdN1wJpWpTQMXJ2DssfSgmOVXETP7qJuZyRprxalQhaEATMDNJA/66Ml1jSO9mZ\n"
"+8Xb7m/4q778lNtkSbsvMaYD2Dq6k2QQ3kMhr9z8oUtX0XA23+pfAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n"
"id ed25519 VGhpcyBpc24ndCBhY3R1YWxseSBhIHB1YmxpYyBrZXk\n"
"id wumpus dodecahedron\n";
@@ -809,6 +754,7 @@ test_md_parse_id_ed25519(void *arg)
"sgdN1wJpWpTQMXJ2DssfSgmOVXETP7qJuZyRprxalQhaEATMDNJA/66Ml1jSO9mZ\n"
"+8Xb7m/4q778lNtkSbsvMaYD2Dq6k2QQ3kMhr9z8oUtX0XA23+pfAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs\n"
"id ed25519 VGhpcyBpc24ndCBhY3R1YWxseSBhIHB1YmxpYyBrZXk\n"
"id ed25519 VGhpcyBpc24ndCBhY3R1YWxseSBhIHB1YmxpYyBrZXk\n";
@@ -829,6 +775,7 @@ test_md_parse_id_ed25519(void *arg)
"sgdN1wJpWpTQMXJ2DssfSgmOVXETP7qJuZyRprxalQhaEATMDNJA/66Ml1jSO9mZ\n"
"+8Xb7m/4q778lNtkSbsvMaYD2Dq6k2QQ3kMhr9z8oUtX0XA23+pfAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs\n"
"id ed25519 VGhpcyBpc24ndCBhY3R1YWxseSBhIHB1YmxpYyZZZZZZZZZZZ\n";
mds = microdescs_parse_from_string(BOGUS_KEY,
diff --git a/src/test/test_nodelist.c b/src/test/test_nodelist.c
index fbbbf0a99f..96fb5a65ad 100644
--- a/src/test/test_nodelist.c
+++ b/src/test/test_nodelist.c
@@ -11,6 +11,7 @@
#include "core/or/or.h"
#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_format.h"
#include "feature/nodelist/describe.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodefamily.h"
@@ -104,7 +105,7 @@ test_nodelist_node_is_dir(void *arg)
tt_assert(node_is_dir(&node));
rs.is_v2_dir = 0;
- rs.dir_port = 1;
+ rs.ipv4_dirport = 1;
tt_assert(! node_is_dir(&node));
node.rs = NULL;
@@ -113,7 +114,7 @@ test_nodelist_node_is_dir(void *arg)
ri.supports_tunnelled_dir_requests = 1;
tt_assert(node_is_dir(&node));
ri.supports_tunnelled_dir_requests = 0;
- ri.dir_port = 1;
+ ri.ipv4_dirport = 1;
tt_assert(! node_is_dir(&node));
done:
@@ -657,6 +658,7 @@ test_nodelist_format_node_description(void *arg)
tor_addr_t mock_null_ip;
tor_addr_t mock_ipv4;
tor_addr_t mock_ipv6;
+ ed25519_public_key_t ed_id;
char ndesc[NODE_DESC_BUF_LEN];
const char *rv = NULL;
@@ -685,16 +687,18 @@ test_nodelist_format_node_description(void *arg)
mock_digest,
NULL,
NULL,
- 0);
+ NULL,
+ NULL);
tt_ptr_op(rv, OP_EQ, ndesc);
tt_str_op(ndesc, OP_EQ, "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
/* format node description should use ~ because named is deprecated */
rv = format_node_description(ndesc,
mock_digest,
+ NULL,
mock_nickname,
NULL,
- 0);
+ NULL);
tt_ptr_op(rv, OP_EQ, ndesc);
tt_str_op(ndesc, OP_EQ,
"$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~""TestOR7890123456789");
@@ -702,9 +706,10 @@ test_nodelist_format_node_description(void *arg)
/* Try a null IP address, rather than NULL */
rv = format_node_description(ndesc,
mock_digest,
+ NULL,
mock_nickname,
- &mock_null_ip,
- 0);
+ NULL,
+ &mock_null_ip);
tt_ptr_op(rv, OP_EQ, ndesc);
tt_str_op(ndesc, OP_EQ,
"$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789");
@@ -713,17 +718,19 @@ test_nodelist_format_node_description(void *arg)
rv = format_node_description(ndesc,
mock_digest,
NULL,
+ NULL,
&mock_ipv4,
- 0);
+ NULL);
tt_ptr_op(rv, OP_EQ, ndesc);
tt_str_op(ndesc, OP_EQ,
"$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA at 111.222.233.244");
rv = format_node_description(ndesc,
mock_digest,
+ NULL,
mock_nickname,
- &mock_ipv6,
- 0);
+ NULL,
+ &mock_ipv6);
tt_ptr_op(rv, OP_EQ, ndesc);
tt_str_op(ndesc, OP_EQ,
"$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
@@ -731,19 +738,35 @@ test_nodelist_format_node_description(void *arg)
rv = format_node_description(ndesc,
mock_digest,
+ NULL,
mock_nickname,
- &mock_ipv6,
- tor_addr_to_ipv4h(&mock_ipv4));
+ &mock_ipv4,
+ &mock_ipv6);
tt_ptr_op(rv, OP_EQ, ndesc);
tt_str_op(ndesc, OP_EQ,
"$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
"111.222.233.244 and [1111:2222:3333:4444:5555:6666:7777:8888]");
+ /* Try some ed25519 keys. */
+ int n = ed25519_public_from_base64(&ed_id,
+ "+wBP6WVZzqKK+eTdwU7Hhb80xEm40FSZDBMNozTJpDE");
+ tt_int_op(n,OP_EQ,0);
+ rv = format_node_description(ndesc,
+ mock_digest,
+ &ed_id,
+ mock_nickname,
+ &mock_ipv4,
+ &mock_ipv6);
+ tt_str_op(ndesc, OP_EQ,
+ "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 "
+ "[+wBP6WVZzqKK+eTdwU7Hhb80xEm40FSZDBMNozTJpDE] at "
+ "111.222.233.244 and [1111:2222:3333:4444:5555:6666:7777:8888]");
+
/* test NULL handling */
- rv = format_node_description(NULL, NULL, NULL, NULL, 0);
+ rv = format_node_description(NULL, NULL, NULL, NULL, NULL, NULL);
tt_str_op(rv, OP_EQ, "<NULL BUFFER>");
- rv = format_node_description(ndesc, NULL, NULL, NULL, 0);
+ rv = format_node_description(ndesc, NULL, NULL, NULL, NULL, NULL);
tt_ptr_op(rv, OP_EQ, ndesc);
tt_str_op(rv, OP_EQ, "<NULL ID DIGEST>");
@@ -761,7 +784,6 @@ static void
test_nodelist_router_describe(void *arg)
{
char mock_nickname[MAX_NICKNAME_LEN+1];
- tor_addr_t mock_ipv4;
routerinfo_t mock_ri_ipv4;
routerinfo_t mock_ri_ipv6;
routerinfo_t mock_ri_dual;
@@ -772,7 +794,6 @@ test_nodelist_router_describe(void *arg)
/* Clear variables */
memset(mock_nickname, 0, sizeof(mock_nickname));
- memset(&mock_ipv4, 0, sizeof(mock_ipv4));
memset(&mock_ri_ipv4, 0, sizeof(mock_ri_ipv4));
memset(&mock_ri_ipv6, 0, sizeof(mock_ri_ipv6));
memset(&mock_ri_dual, 0, sizeof(mock_ri_dual));
@@ -784,8 +805,7 @@ test_nodelist_router_describe(void *arg)
sizeof(mock_ri_dual.cache_info.identity_digest));
strlcpy(mock_nickname, "TestOR7890123456789", sizeof(mock_nickname));
mock_ri_dual.nickname = mock_nickname;
- tor_addr_parse(&mock_ipv4, "111.222.233.244");
- mock_ri_dual.addr = tor_addr_to_ipv4h(&mock_ipv4);
+ tor_addr_parse(&mock_ri_dual.ipv4_addr, "111.222.233.244");
tor_addr_parse(&mock_ri_dual.ipv6_addr,
"[1111:2222:3333:4444:5555:6666:7777:8888]");
@@ -796,7 +816,7 @@ test_nodelist_router_describe(void *arg)
memcpy(&mock_ri_ipv6, &mock_ri_dual, sizeof(mock_ri_ipv6));
/* Clear the unnecessary addresses */
memset(&mock_ri_ipv4.ipv6_addr, 0, sizeof(mock_ri_ipv4.ipv6_addr));
- mock_ri_ipv6.addr = 0;
+ tor_addr_make_unspec(&mock_ri_ipv6.ipv4_addr);
/* We don't test the no-nickname and no-IP cases, because they're covered by
* format_node_description(), and we don't expect to see them in Tor code. */
@@ -863,7 +883,6 @@ static void
test_nodelist_node_describe(void *arg)
{
char mock_nickname[MAX_NICKNAME_LEN+1];
- tor_addr_t mock_ipv4;
const char *rv = NULL;
@@ -874,7 +893,6 @@ test_nodelist_node_describe(void *arg)
/* Clear variables */
memset(mock_nickname, 0, sizeof(mock_nickname));
- memset(&mock_ipv4, 0, sizeof(mock_ipv4));
memset(&mock_ri_dual, 0, sizeof(mock_ri_dual));
/* Set up the dual-stack routerinfo */
@@ -884,8 +902,7 @@ test_nodelist_node_describe(void *arg)
sizeof(mock_ri_dual.cache_info.identity_digest));
strlcpy(mock_nickname, "TestOR7890123456789", sizeof(mock_nickname));
mock_ri_dual.nickname = mock_nickname;
- tor_addr_parse(&mock_ipv4, "111.222.233.244");
- mock_ri_dual.addr = tor_addr_to_ipv4h(&mock_ipv4);
+ tor_addr_parse(&mock_ri_dual.ipv4_addr, "111.222.233.244");
tor_addr_parse(&mock_ri_dual.ipv6_addr,
"[1111:2222:3333:4444:5555:6666:7777:8888]");
@@ -894,7 +911,6 @@ test_nodelist_node_describe(void *arg)
routerstatus_t mock_rs_dual;
/* Clear variables */
- memset(&mock_ipv4, 0, sizeof(mock_ipv4));
memset(&mock_rs_ipv4, 0, sizeof(mock_rs_ipv4));
memset(&mock_rs_dual, 0, sizeof(mock_rs_dual));
@@ -905,8 +921,7 @@ test_nodelist_node_describe(void *arg)
sizeof(mock_rs_dual.identity_digest));
strlcpy(mock_rs_dual.nickname, "Bbb",
sizeof(mock_rs_dual.nickname));
- tor_addr_parse(&mock_ipv4, "2.2.2.2");
- mock_rs_dual.addr = tor_addr_to_ipv4h(&mock_ipv4);
+ tor_addr_parse(&mock_rs_dual.ipv4_addr, "2.2.2.2");
tor_addr_parse(&mock_rs_dual.ipv6_addr,
"[bbbb::bbbb]");
@@ -1070,7 +1085,6 @@ test_nodelist_node_describe(void *arg)
static void
test_nodelist_routerstatus_describe(void *arg)
{
- tor_addr_t mock_ipv4;
routerstatus_t mock_rs_ipv4;
routerstatus_t mock_rs_ipv6;
routerstatus_t mock_rs_dual;
@@ -1080,7 +1094,6 @@ test_nodelist_routerstatus_describe(void *arg)
(void) arg;
/* Clear variables */
- memset(&mock_ipv4, 0, sizeof(mock_ipv4));
memset(&mock_rs_ipv4, 0, sizeof(mock_rs_ipv4));
memset(&mock_rs_ipv6, 0, sizeof(mock_rs_ipv6));
memset(&mock_rs_dual, 0, sizeof(mock_rs_dual));
@@ -1092,8 +1105,7 @@ test_nodelist_routerstatus_describe(void *arg)
sizeof(mock_rs_dual.identity_digest));
strlcpy(mock_rs_dual.nickname, "TestOR7890123456789",
sizeof(mock_rs_dual.nickname));
- tor_addr_parse(&mock_ipv4, "111.222.233.244");
- mock_rs_dual.addr = tor_addr_to_ipv4h(&mock_ipv4);
+ tor_addr_parse(&mock_rs_dual.ipv4_addr, "111.222.233.244");
tor_addr_parse(&mock_rs_dual.ipv6_addr,
"[1111:2222:3333:4444:5555:6666:7777:8888]");
@@ -1102,7 +1114,7 @@ test_nodelist_routerstatus_describe(void *arg)
memcpy(&mock_rs_ipv6, &mock_rs_dual, sizeof(mock_rs_ipv6));
/* Clear the unnecessary addresses */
memset(&mock_rs_ipv4.ipv6_addr, 0, sizeof(mock_rs_ipv4.ipv6_addr));
- mock_rs_ipv6.addr = 0;
+ tor_addr_make_unspec(&mock_rs_ipv6.ipv4_addr);
/* We don't test the no-nickname and no-IP cases, because they're covered by
* format_node_description(), and we don't expect to see them in Tor code. */
@@ -1182,11 +1194,11 @@ test_nodelist_extend_info_describe(void *arg)
sizeof(mock_ei_ipv4.identity_digest));
strlcpy(mock_ei_ipv4.nickname, "TestOR7890123456789",
sizeof(mock_ei_ipv4.nickname));
- tor_addr_parse(&mock_ei_ipv4.addr, "111.222.233.244");
+ tor_addr_parse(&mock_ei_ipv4.orports[0].addr, "111.222.233.244");
/* Create and modify the other extend info. */
memcpy(&mock_ei_ipv6, &mock_ei_ipv4, sizeof(mock_ei_ipv6));
- tor_addr_parse(&mock_ei_ipv6.addr,
+ tor_addr_parse(&mock_ei_ipv6.orports[0].addr,
"[1111:2222:3333:4444:5555:6666:7777:8888]");
/* We don't test the no-nickname and no-IP cases, because they're covered by
@@ -1259,8 +1271,8 @@ test_nodelist_routerstatus_has_visibly_changed(void *arg)
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;
+ tor_addr_from_ipv4h(&rs_orig.ipv4_addr, 0x7f000001);
+ rs_orig.ipv4_orport = 3;
rs_orig.published_on = time(NULL);
rs_orig.has_bandwidth = 1;
rs_orig.bandwidth_kb = 20;
@@ -1301,7 +1313,7 @@ test_nodelist_routerstatus_has_visibly_changed(void *arg)
COPY();
ASSERT_SAME();
- rs.addr = 0x7f000002;
+ tor_addr_from_ipv4h(&rs.ipv4_addr, 0x7f000002);
ASSERT_CHANGED();
strlcpy(rs.descriptor_digest, "hello world", sizeof(rs.descriptor_digest));
@@ -1313,10 +1325,10 @@ test_nodelist_routerstatus_has_visibly_changed(void *arg)
rs.published_on += 3600;
ASSERT_CHANGED();
- rs.or_port = 55;
+ rs.ipv4_orport = 55;
ASSERT_CHANGED();
- rs.dir_port = 9999;
+ rs.ipv4_dirport = 9999;
ASSERT_CHANGED();
tor_addr_parse(&rs.ipv6_addr, "1234::56");
diff --git a/src/test/test_options.c b/src/test/test_options.c
index 8e0d19f126..714ee4767f 100644
--- a/src/test/test_options.c
+++ b/src/test/test_options.c
@@ -1013,7 +1013,7 @@ test_options_validate__relay_with_hidden_services(void *ignored)
"Tor is currently configured as a relay and a hidden service. "
"That's not very secure: you should probably run your hidden servi"
"ce in a separate Tor process, at least -- see "
- "https://trac.torproject.org/8742\n");
+ "https://bugs.torproject.org/tpo/core/tor/8742.\n");
done:
teardown_capture_of_logs();
diff --git a/src/test/test_parseconf.sh b/src/test/test_parseconf.sh
index 4fe27d9f5d..c02b8b23c0 100755
--- a/src/test/test_parseconf.sh
+++ b/src/test/test_parseconf.sh
@@ -202,7 +202,7 @@ STANDARD_LIBS="libevent\\|openssl\\|zlib"
# 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' \
+ | sed -n 's/.* Tor .* running on .* with\(.*\) and .* .* as libc\./\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/' \
diff --git a/src/test/test_periodic_event.c b/src/test/test_periodic_event.c
index b7f1785805..d3bc89673b 100644
--- a/src/test/test_periodic_event.c
+++ b/src/test/test_periodic_event.c
@@ -17,6 +17,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
#include "feature/hibernate/hibernate.h"
+#include "feature/hs/hs_metrics.h"
#include "feature/hs/hs_service.h"
#include "core/mainloop/mainloop.h"
#include "core/mainloop/netstatus.h"
@@ -100,7 +101,7 @@ test_pe_launch(void *arg)
periodic_events_on_new_options(options);
#if 0
- /* Lets make sure that before intialization, we can't scan the periodic
+ /* Lets make sure that before initialization, we can't scan the periodic
* events list and launch them. Lets try by being a Client. */
/* XXXX We make sure these events are initialized now way earlier than we
* did before. */
@@ -187,6 +188,7 @@ test_pe_launch(void *arg)
done:
if (to_remove) {
+ hs_metrics_service_free(&service);
remove_service(get_hs_service_map(), to_remove);
}
hs_free_all();
@@ -279,6 +281,7 @@ test_pe_get_roles(void *arg)
roles = get_my_roles(options);
/* Remove it now so the hs_free_all() doesn't try to free stack memory. */
remove_service(get_hs_service_map(), &service);
+ hs_metrics_service_free(&service);
tt_int_op(roles, OP_EQ,
(PERIODIC_EVENT_ROLE_BRIDGEAUTH | PERIODIC_EVENT_ROLE_RELAY |
PERIODIC_EVENT_ROLE_HS_SERVICE | PERIODIC_EVENT_ROLE_DIRSERVER |
@@ -332,6 +335,7 @@ test_pe_hs_service(void *arg)
/* Remove the service from the global map, it should trigger a rescan and
* disable the HS service events. */
remove_service(get_hs_service_map(), &service);
+ hs_metrics_service_free(&service);
for (int i = 0; mainloop_periodic_events[i].name; ++i) {
periodic_event_item_t *item = &mainloop_periodic_events[i];
if (item->roles & PERIODIC_EVENT_ROLE_HS_SERVICE) {
@@ -341,6 +345,7 @@ test_pe_hs_service(void *arg)
done:
if (to_remove) {
+ hs_metrics_service_free(&service);
remove_service(get_hs_service_map(), to_remove);
}
hs_free_all();
diff --git a/src/test/test_policy.c b/src/test/test_policy.c
index 7949e90e9e..0a0548d161 100644
--- a/src/test/test_policy.c
+++ b/src/test/test_policy.c
@@ -8,6 +8,7 @@
#include "app/config/config.h"
#include "core/or/circuitbuild.h"
#include "core/or/policies.h"
+#include "core/or/extendinfo.h"
#include "feature/dirparse/policy_parse.h"
#include "feature/hs/hs_common.h"
#include "feature/hs/hs_descriptor.h"
@@ -1124,7 +1125,7 @@ test_policy_has_address_helper(const smartlist_t *policy_list,
return 0;
}
-#define TEST_IPV4_ADDR (0x01020304)
+#define TEST_IPV4_ADDR ("1.2.3.4")
#define TEST_IPV6_ADDR ("2002::abcd")
/** Run unit tests for rejecting the configured addresses on this exit relay
@@ -1137,7 +1138,7 @@ test_policies_reject_exit_address(void *arg)
smartlist_t *ipv4_list, *ipv6_list, *both_list, *dupl_list;
(void)arg;
- tor_addr_from_ipv4h(&ipv4_addr, TEST_IPV4_ADDR);
+ tor_addr_parse(&ipv4_addr, TEST_IPV4_ADDR);
tor_addr_parse(&ipv6_addr, TEST_IPV6_ADDR);
ipv4_list = smartlist_new();
@@ -1255,7 +1256,7 @@ test_policies_reject_port_address(void *arg)
test_configured_ports = smartlist_new();
ipv4_port = port_cfg_new(0);
- tor_addr_from_ipv4h(&ipv4_port->addr, TEST_IPV4_ADDR);
+ tor_addr_parse(&ipv4_port->addr, TEST_IPV4_ADDR);
smartlist_add(test_configured_ports, ipv4_port);
ipv6_port = port_cfg_new(0);
@@ -1373,7 +1374,7 @@ test_policies_reject_interface_address(void *arg)
}
/* Now do it all again, but mocked */
- tor_addr_from_ipv4h(&ipv4_addr, TEST_IPV4_ADDR);
+ tor_addr_parse(&ipv4_addr, TEST_IPV4_ADDR);
mock_ipv4_addrs = smartlist_new();
smartlist_add(mock_ipv4_addrs, (void *)&ipv4_addr);
@@ -1528,7 +1529,7 @@ mock_router_get_my_routerinfo_with_err(int *err)
}
#define DEFAULT_POLICY_STRING "reject *:*"
-#define TEST_IPV4_ADDR (0x02040608)
+#define TEST_IPV4_ADDR ("2.4.6.8")
#define TEST_IPV6_ADDR ("2003::ef01")
static or_options_t mock_options;
@@ -1607,13 +1608,13 @@ test_policies_getinfo_helper_policies(void *arg)
tt_assert(strlen(answer) == 0 || !strcasecmp(answer, DEFAULT_POLICY_STRING));
tor_free(answer);
- mock_my_routerinfo.addr = TEST_IPV4_ADDR;
+ tor_addr_parse(&mock_my_routerinfo.ipv4_addr, TEST_IPV4_ADDR);
tor_addr_parse(&mock_my_routerinfo.ipv6_addr, TEST_IPV6_ADDR);
append_exit_policy_string(&mock_my_routerinfo.exit_policy, "accept *4:*");
append_exit_policy_string(&mock_my_routerinfo.exit_policy, "reject *6:*");
mock_options.IPv6Exit = 1;
- tor_addr_from_ipv4h(
+ tor_addr_parse(
&mock_options.OutboundBindAddresses[OUTBOUND_ADDR_EXIT][0],
TEST_IPV4_ADDR);
tor_addr_parse(
@@ -1752,7 +1753,7 @@ test_policies_getinfo_helper_policies(void *arg)
#define OTHER_IPV4_ADDR_STR "6.7.8.9"
#define OTHER_IPV6_ADDR_STR "[afff::]"
-/** Run unit tests for fascist_firewall_allows_address */
+/** Run unit tests for reachable_addr_allows */
static void
test_policies_fascist_firewall_allows_address(void *arg)
{
@@ -1821,33 +1822,33 @@ test_policies_fascist_firewall_allows_address(void *arg)
mock_options.ClientUseIPv6 = 1;
mock_options.UseBridges = 0;
- tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv4_addr, port, policy, 0, 0),
OP_EQ, 1);
- tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv6_addr, port, policy, 0, 0),
OP_EQ, 1);
- tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&r_ipv4_addr, port, policy, 0, 0),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&r_ipv6_addr, port, policy, 0, 0),
OP_EQ, 0);
/* Preferring IPv4 */
- tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 1, 0),
+ tt_int_op(reachable_addr_allows(&ipv4_addr, port, policy, 1, 0),
OP_EQ, 1);
- tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 1, 0),
+ tt_int_op(reachable_addr_allows(&ipv6_addr, port, policy, 1, 0),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 1, 0),
+ tt_int_op(reachable_addr_allows(&r_ipv4_addr, port, policy, 1, 0),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 1, 0),
+ tt_int_op(reachable_addr_allows(&r_ipv6_addr, port, policy, 1, 0),
OP_EQ, 0);
/* Preferring IPv6 */
- tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 1, 1),
+ tt_int_op(reachable_addr_allows(&ipv4_addr, port, policy, 1, 1),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 1, 1),
+ tt_int_op(reachable_addr_allows(&ipv6_addr, port, policy, 1, 1),
OP_EQ, 1);
- tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 1, 1),
+ tt_int_op(reachable_addr_allows(&r_ipv4_addr, port, policy, 1, 1),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 1, 1),
+ tt_int_op(reachable_addr_allows(&r_ipv6_addr, port, policy, 1, 1),
OP_EQ, 0);
/* Test the function's address matching with UseBridges on */
@@ -1856,45 +1857,45 @@ test_policies_fascist_firewall_allows_address(void *arg)
mock_options.ClientUseIPv6 = 1;
mock_options.UseBridges = 1;
- tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv4_addr, port, policy, 0, 0),
OP_EQ, 1);
- tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv6_addr, port, policy, 0, 0),
OP_EQ, 1);
- tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&r_ipv4_addr, port, policy, 0, 0),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&r_ipv6_addr, port, policy, 0, 0),
OP_EQ, 0);
/* Preferring IPv4 */
- tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 1, 0),
+ tt_int_op(reachable_addr_allows(&ipv4_addr, port, policy, 1, 0),
OP_EQ, 1);
- tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 1, 0),
+ tt_int_op(reachable_addr_allows(&ipv6_addr, port, policy, 1, 0),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 1, 0),
+ tt_int_op(reachable_addr_allows(&r_ipv4_addr, port, policy, 1, 0),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 1, 0),
+ tt_int_op(reachable_addr_allows(&r_ipv6_addr, port, policy, 1, 0),
OP_EQ, 0);
/* Preferring IPv6 */
- tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 1, 1),
+ tt_int_op(reachable_addr_allows(&ipv4_addr, port, policy, 1, 1),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 1, 1),
+ tt_int_op(reachable_addr_allows(&ipv6_addr, port, policy, 1, 1),
OP_EQ, 1);
- tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 1, 1),
+ tt_int_op(reachable_addr_allows(&r_ipv4_addr, port, policy, 1, 1),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 1, 1),
+ tt_int_op(reachable_addr_allows(&r_ipv6_addr, port, policy, 1, 1),
OP_EQ, 0);
/* bridge clients always use IPv6, regardless of ClientUseIPv6 */
mock_options.ClientUseIPv4 = 1;
mock_options.ClientUseIPv6 = 0;
- tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv4_addr, port, policy, 0, 0),
OP_EQ, 1);
- tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv6_addr, port, policy, 0, 0),
OP_EQ, 1);
- tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&r_ipv4_addr, port, policy, 0, 0),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&r_ipv6_addr, port, policy, 0, 0),
OP_EQ, 0);
/* Test the function's address matching with IPv4 on */
@@ -1903,13 +1904,13 @@ test_policies_fascist_firewall_allows_address(void *arg)
mock_options.ClientUseIPv6 = 0;
mock_options.UseBridges = 0;
- tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv4_addr, port, policy, 0, 0),
OP_EQ, 1);
- tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv6_addr, port, policy, 0, 0),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&r_ipv4_addr, port, policy, 0, 0),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&r_ipv6_addr, port, policy, 0, 0),
OP_EQ, 0);
/* Test the function's address matching with IPv6 on */
@@ -1918,13 +1919,13 @@ test_policies_fascist_firewall_allows_address(void *arg)
mock_options.ClientUseIPv6 = 1;
mock_options.UseBridges = 0;
- tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv4_addr, port, policy, 0, 0),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv6_addr, port, policy, 0, 0),
OP_EQ, 1);
- tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&r_ipv4_addr, port, policy, 0, 0),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&r_ipv6_addr, port, policy, 0, 0),
OP_EQ, 0);
/* Test the function's address matching with ClientUseIPv4 0.
@@ -1934,13 +1935,13 @@ test_policies_fascist_firewall_allows_address(void *arg)
mock_options.ClientUseIPv6 = 0;
mock_options.UseBridges = 0;
- tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv4_addr, port, policy, 0, 0),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv6_addr, port, policy, 0, 0),
OP_EQ, 1);
- tt_int_op(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&r_ipv4_addr, port, policy, 0, 0),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&r_ipv6_addr, port, policy, 0, 0),
OP_EQ, 0);
/* Test the function's address matching for unusual inputs */
@@ -1950,27 +1951,27 @@ test_policies_fascist_firewall_allows_address(void *arg)
mock_options.UseBridges = 1;
/* NULL and tor_addr_is_null addresses are rejected */
- tt_int_op(fascist_firewall_allows_address(NULL, port, policy, 0, 0), OP_EQ,
+ tt_int_op(reachable_addr_allows(NULL, port, policy, 0, 0), OP_EQ,
0);
- tt_int_op(fascist_firewall_allows_address(&n_ipv4_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&n_ipv4_addr, port, policy, 0, 0),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&n_ipv6_addr, port, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&n_ipv6_addr, port, policy, 0, 0),
OP_EQ, 0);
/* zero ports are rejected */
- tt_int_op(fascist_firewall_allows_address(&ipv4_addr, 0, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv4_addr, 0, policy, 0, 0),
OP_EQ, 0);
- tt_int_op(fascist_firewall_allows_address(&ipv6_addr, 0, policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv6_addr, 0, policy, 0, 0),
OP_EQ, 0);
/* NULL and empty policies accept everything */
- tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, NULL, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv4_addr, port, NULL, 0, 0),
OP_EQ, 1);
- tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, NULL, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv6_addr, port, NULL, 0, 0),
OP_EQ, 1);
- tt_int_op(fascist_firewall_allows_address(&ipv4_addr, port, e_policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv4_addr, port, e_policy, 0, 0),
OP_EQ, 1);
- tt_int_op(fascist_firewall_allows_address(&ipv6_addr, port, e_policy, 0, 0),
+ tt_int_op(reachable_addr_allows(&ipv6_addr, port, e_policy, 0, 0),
OP_EQ, 1);
done:
@@ -1990,7 +1991,7 @@ test_policies_fascist_firewall_allows_address(void *arg)
#define TEST_IPV6_OR_PORT 61234
#define TEST_IPV6_DIR_PORT 62345
-/* Check that fascist_firewall_choose_address_rs() returns the expected
+/* Check that reachable_addr_choose_from_rs() returns the expected
* results. */
#define CHECK_CHOSEN_ADDR_RS(fake_rs, fw_connection, pref_only, expect_rv, \
expect_ap) \
@@ -1998,13 +1999,13 @@ test_policies_fascist_firewall_allows_address(void *arg)
tor_addr_port_t chosen_rs_ap; \
tor_addr_make_null(&chosen_rs_ap.addr, AF_INET); \
chosen_rs_ap.port = 0; \
- fascist_firewall_choose_address_rs(&(fake_rs), (fw_connection), \
+ reachable_addr_choose_from_rs(&(fake_rs), (fw_connection), \
(pref_only), &chosen_rs_ap); \
tt_assert(tor_addr_eq(&(expect_ap).addr, &chosen_rs_ap.addr)); \
tt_int_op((expect_ap).port, OP_EQ, chosen_rs_ap.port); \
STMT_END
-/* Check that fascist_firewall_choose_address_node() returns the expected
+/* Check that reachable_addr_choose_from_node() returns the expected
* results. */
#define CHECK_CHOSEN_ADDR_NODE(fake_node, fw_connection, pref_only, \
expect_rv, expect_ap) \
@@ -2012,14 +2013,14 @@ test_policies_fascist_firewall_allows_address(void *arg)
tor_addr_port_t chosen_node_ap; \
tor_addr_make_null(&chosen_node_ap.addr, AF_INET); \
chosen_node_ap.port = 0; \
- fascist_firewall_choose_address_node(&(fake_node),(fw_connection), \
+ reachable_addr_choose_from_node(&(fake_node),(fw_connection), \
(pref_only), &chosen_node_ap); \
tt_assert(tor_addr_eq(&(expect_ap).addr, &chosen_node_ap.addr)); \
tt_int_op((expect_ap).port, OP_EQ, chosen_node_ap.port); \
STMT_END
-/* Check that fascist_firewall_choose_address_rs and
- * fascist_firewall_choose_address_node() both return the expected results. */
+/* Check that reachable_addr_choose_from_rs and
+ * reachable_addr_choose_from_node() both return the expected results. */
#define CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, fw_connection, pref_only, \
expect_rv, expect_ap) \
STMT_BEGIN \
@@ -2029,7 +2030,7 @@ test_policies_fascist_firewall_allows_address(void *arg)
expect_ap); \
STMT_END
-/* Check that fascist_firewall_choose_address_ls() returns the expected
+/* Check that reachable_addr_choose_from_ls() returns the expected
* results. */
#define CHECK_CHOSEN_ADDR_NULL_LS() \
STMT_BEGIN \
@@ -2037,7 +2038,7 @@ test_policies_fascist_firewall_allows_address(void *arg)
tor_addr_make_null(&chosen_ls_ap.addr, AF_UNSPEC); \
chosen_ls_ap.port = 0; \
setup_full_capture_of_logs(LOG_WARN); \
- fascist_firewall_choose_address_ls(NULL, 1, &chosen_ls_ap); \
+ reachable_addr_choose_from_ls(NULL, 1, &chosen_ls_ap); \
expect_single_log_msg("Unknown or missing link specifiers"); \
teardown_capture_of_logs(); \
STMT_END
@@ -2048,7 +2049,7 @@ test_policies_fascist_firewall_allows_address(void *arg)
tor_addr_make_null(&chosen_ls_ap.addr, AF_UNSPEC); \
chosen_ls_ap.port = 0; \
setup_full_capture_of_logs(LOG_WARN); \
- fascist_firewall_choose_address_ls(fake_ls, pref_only, &chosen_ls_ap); \
+ reachable_addr_choose_from_ls(fake_ls, pref_only, &chosen_ls_ap); \
if (smartlist_len(fake_ls) == 0) { \
expect_single_log_msg("Link specifiers are empty"); \
} else { \
@@ -2065,7 +2066,7 @@ test_policies_fascist_firewall_allows_address(void *arg)
tor_addr_make_null(&chosen_ls_ap.addr, AF_UNSPEC); \
chosen_ls_ap.port = 0; \
setup_full_capture_of_logs(LOG_WARN); \
- fascist_firewall_choose_address_ls(fake_ls, 0, &chosen_ls_ap); \
+ reachable_addr_choose_from_ls(fake_ls, 0, &chosen_ls_ap); \
expect_single_log_msg("None of our link specifiers have IPv4 or IPv6"); \
teardown_capture_of_logs(); \
STMT_END
@@ -2084,8 +2085,8 @@ test_policies_fascist_firewall_allows_address(void *arg)
expect_single_log_msg("Specified link specifiers is null"); \
} else { \
expect_no_log_entry(); \
- tt_assert(tor_addr_eq(&(expect_ap).addr, &ei->addr)); \
- tt_int_op((expect_ap).port, OP_EQ, ei->port); \
+ tt_assert(tor_addr_eq(&(expect_ap).addr, &ei->orports[0].addr)); \
+ tt_int_op((expect_ap).port, OP_EQ, ei->orports[0].port); \
extend_info_free(ei); \
} \
teardown_capture_of_logs(); \
@@ -2124,7 +2125,7 @@ test_policies_fascist_firewall_allows_address(void *arg)
teardown_capture_of_logs(); \
STMT_END
-/** Run unit tests for fascist_firewall_choose_address */
+/** Run unit tests for reachable_addr_choose */
static void
test_policies_fascist_firewall_choose_address(void *arg)
{
@@ -2152,87 +2153,87 @@ test_policies_fascist_firewall_choose_address(void *arg)
tor_addr_make_null(&n_ipv6_ap.addr, AF_INET6);
n_ipv6_ap.port = 0;
- /* Sanity check fascist_firewall_choose_address with IPv4 and IPv6 on */
+ /* Sanity check reachable_addr_choose with IPv4 and IPv6 on */
memset(&mock_options, 0, sizeof(or_options_t));
mock_options.ClientUseIPv4 = 1;
mock_options.ClientUseIPv6 = 1;
mock_options.UseBridges = 0;
/* Prefer IPv4 */
- tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 1,
+ tt_assert(reachable_addr_choose(&ipv4_or_ap, &ipv6_or_ap, 1,
FIREWALL_OR_CONNECTION, 0, 0)
== &ipv4_or_ap);
- tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 1,
+ tt_assert(reachable_addr_choose(&ipv4_or_ap, &ipv6_or_ap, 1,
FIREWALL_OR_CONNECTION, 1, 0)
== &ipv4_or_ap);
- tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 1,
+ tt_assert(reachable_addr_choose(&ipv4_dir_ap, &ipv6_dir_ap, 1,
FIREWALL_DIR_CONNECTION, 0, 0)
== &ipv4_dir_ap);
- tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 1,
+ tt_assert(reachable_addr_choose(&ipv4_dir_ap, &ipv6_dir_ap, 1,
FIREWALL_DIR_CONNECTION, 1, 0)
== &ipv4_dir_ap);
/* Prefer IPv6 */
- tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
+ tt_assert(reachable_addr_choose(&ipv4_or_ap, &ipv6_or_ap, 0,
FIREWALL_OR_CONNECTION, 0, 1)
== &ipv6_or_ap);
- tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
+ tt_assert(reachable_addr_choose(&ipv4_or_ap, &ipv6_or_ap, 0,
FIREWALL_OR_CONNECTION, 1, 1)
== &ipv6_or_ap);
- tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
+ tt_assert(reachable_addr_choose(&ipv4_dir_ap, &ipv6_dir_ap, 0,
FIREWALL_DIR_CONNECTION, 0, 1)
== &ipv6_dir_ap);
- tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
+ tt_assert(reachable_addr_choose(&ipv4_dir_ap, &ipv6_dir_ap, 0,
FIREWALL_DIR_CONNECTION, 1, 1)
== &ipv6_dir_ap);
/* Unusual inputs */
/* null preferred OR addresses */
- tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &n_ipv6_ap, 0,
+ tt_assert(reachable_addr_choose(&ipv4_or_ap, &n_ipv6_ap, 0,
FIREWALL_OR_CONNECTION, 0, 1)
== &ipv4_or_ap);
- tt_assert(fascist_firewall_choose_address(&n_ipv4_ap, &ipv6_or_ap, 1,
+ tt_assert(reachable_addr_choose(&n_ipv4_ap, &ipv6_or_ap, 1,
FIREWALL_OR_CONNECTION, 0, 0)
== &ipv6_or_ap);
/* null both OR addresses */
- tt_ptr_op(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 0,
+ tt_ptr_op(reachable_addr_choose(&n_ipv4_ap, &n_ipv6_ap, 0,
FIREWALL_OR_CONNECTION, 0, 1),
OP_EQ, NULL);
- tt_ptr_op(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 1,
+ tt_ptr_op(reachable_addr_choose(&n_ipv4_ap, &n_ipv6_ap, 1,
FIREWALL_OR_CONNECTION, 0, 0),
OP_EQ, NULL);
/* null preferred Dir addresses */
- tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &n_ipv6_ap, 0,
+ tt_assert(reachable_addr_choose(&ipv4_dir_ap, &n_ipv6_ap, 0,
FIREWALL_DIR_CONNECTION, 0, 1)
== &ipv4_dir_ap);
- tt_assert(fascist_firewall_choose_address(&n_ipv4_ap, &ipv6_dir_ap, 1,
+ tt_assert(reachable_addr_choose(&n_ipv4_ap, &ipv6_dir_ap, 1,
FIREWALL_DIR_CONNECTION, 0, 0)
== &ipv6_dir_ap);
/* null both Dir addresses */
- tt_ptr_op(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 0,
+ tt_ptr_op(reachable_addr_choose(&n_ipv4_ap, &n_ipv6_ap, 0,
FIREWALL_DIR_CONNECTION, 0, 1),
OP_EQ, NULL);
- tt_ptr_op(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 1,
+ tt_ptr_op(reachable_addr_choose(&n_ipv4_ap, &n_ipv6_ap, 1,
FIREWALL_DIR_CONNECTION, 0, 0),
OP_EQ, NULL);
/* Prefer IPv4 but want IPv6 (contradictory) */
- tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
+ tt_assert(reachable_addr_choose(&ipv4_or_ap, &ipv6_or_ap, 0,
FIREWALL_OR_CONNECTION, 0, 0)
== &ipv4_or_ap);
- tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
+ tt_assert(reachable_addr_choose(&ipv4_or_ap, &ipv6_or_ap, 0,
FIREWALL_OR_CONNECTION, 1, 0)
== &ipv4_or_ap);
/* Prefer IPv6 but want IPv4 (contradictory) */
- tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 1,
+ tt_assert(reachable_addr_choose(&ipv4_or_ap, &ipv6_or_ap, 1,
FIREWALL_OR_CONNECTION, 0, 1)
== &ipv6_or_ap);
- tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 1,
+ tt_assert(reachable_addr_choose(&ipv4_or_ap, &ipv6_or_ap, 1,
FIREWALL_OR_CONNECTION, 1, 1)
== &ipv6_or_ap);
@@ -2242,9 +2243,9 @@ test_policies_fascist_firewall_choose_address(void *arg)
routerstatus_t fake_rs;
memset(&fake_rs, 0, sizeof(routerstatus_t));
/* In a routerstatus, the OR and Dir addresses are the same */
- fake_rs.addr = tor_addr_to_ipv4h(&ipv4_or_ap.addr);
- fake_rs.or_port = ipv4_or_ap.port;
- fake_rs.dir_port = ipv4_dir_ap.port;
+ tor_addr_copy(&fake_rs.ipv4_addr, &ipv4_or_ap.addr);
+ fake_rs.ipv4_orport = ipv4_or_ap.port;
+ fake_rs.ipv4_dirport = ipv4_dir_ap.port;
tor_addr_copy(&fake_rs.ipv6_addr, &ipv6_or_ap.addr);
fake_rs.ipv6_orport = ipv6_or_ap.port;
@@ -2267,7 +2268,7 @@ test_policies_fascist_firewall_choose_address(void *arg)
mock_options.ClientPreferIPv6ORPort = 0;
mock_options.ClientPreferIPv6DirPort = 0;
/* Simulate the initialisation of fake_node.ipv6_preferred */
- fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
+ fake_node.ipv6_preferred = reachable_addr_prefer_ipv6_orport(
&mock_options);
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
@@ -2283,7 +2284,7 @@ test_policies_fascist_firewall_choose_address(void *arg)
mock_options.ClientPreferIPv6ORPort = -1;
mock_options.ClientPreferIPv6DirPort = -1;
/* Simulate the initialisation of fake_node.ipv6_preferred */
- fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
+ fake_node.ipv6_preferred = reachable_addr_prefer_ipv6_orport(
&mock_options);
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
@@ -2299,7 +2300,7 @@ test_policies_fascist_firewall_choose_address(void *arg)
mock_options.ClientPreferIPv6ORPort = 1;
mock_options.ClientPreferIPv6DirPort = 1;
/* Simulate the initialisation of fake_node.ipv6_preferred */
- fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
+ fake_node.ipv6_preferred = reachable_addr_prefer_ipv6_orport(
&mock_options);
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
@@ -2315,7 +2316,7 @@ test_policies_fascist_firewall_choose_address(void *arg)
mock_options.ClientPreferIPv6ORPort = 0;
mock_options.ClientPreferIPv6DirPort = 1;
/* Simulate the initialisation of fake_node.ipv6_preferred */
- fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
+ fake_node.ipv6_preferred = reachable_addr_prefer_ipv6_orport(
&mock_options);
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
@@ -2331,7 +2332,7 @@ test_policies_fascist_firewall_choose_address(void *arg)
mock_options.ClientPreferIPv6ORPort = 1;
mock_options.ClientPreferIPv6DirPort = 0;
/* Simulate the initialisation of fake_node.ipv6_preferred */
- fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
+ fake_node.ipv6_preferred = reachable_addr_prefer_ipv6_orport(
&mock_options);
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
@@ -2353,7 +2354,7 @@ test_policies_fascist_firewall_choose_address(void *arg)
mock_options.ClientPreferIPv6ORPort = 0;
mock_options.ClientPreferIPv6DirPort = 0;
/* Simulate the initialisation of fake_node.ipv6_preferred */
- fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
+ fake_node.ipv6_preferred = reachable_addr_prefer_ipv6_orport(
&mock_options);
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
@@ -2404,7 +2405,7 @@ test_policies_fascist_firewall_choose_address(void *arg)
mock_options.ClientPreferIPv6ORPort = 1;
mock_options.ClientPreferIPv6DirPort = 1;
/* Simulate the initialisation of fake_node.ipv6_preferred */
- fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
+ fake_node.ipv6_preferred = reachable_addr_prefer_ipv6_orport(
&mock_options);
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
@@ -2453,7 +2454,7 @@ test_policies_fascist_firewall_choose_address(void *arg)
mock_options.ClientUseIPv4 = 1;
mock_options.ClientUseIPv6 = 0;
/* Simulate the initialisation of fake_node.ipv6_preferred */
- fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
+ fake_node.ipv6_preferred = reachable_addr_prefer_ipv6_orport(
&mock_options);
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
@@ -2470,7 +2471,7 @@ test_policies_fascist_firewall_choose_address(void *arg)
mock_options.ClientUseIPv4 = 0;
mock_options.ClientUseIPv6 = 1;
/* Simulate the initialisation of fake_node.ipv6_preferred */
- fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
+ fake_node.ipv6_preferred = reachable_addr_prefer_ipv6_orport(
&mock_options);
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
@@ -2488,7 +2489,7 @@ test_policies_fascist_firewall_choose_address(void *arg)
mock_options.ClientUseIPv4 = 0;
mock_options.ClientUseIPv6 = 0;
/* Simulate the initialisation of fake_node.ipv6_preferred */
- fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
+ fake_node.ipv6_preferred = reachable_addr_prefer_ipv6_orport(
&mock_options);
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
@@ -2510,7 +2511,7 @@ test_policies_fascist_firewall_choose_address(void *arg)
mock_options.ClientPreferIPv6DirPort = 1;
/* Simulate the initialisation of fake_node.ipv6_preferred */
- fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
+ fake_node.ipv6_preferred = reachable_addr_prefer_ipv6_orport(
&mock_options);
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
@@ -2682,9 +2683,9 @@ struct testcase_t policy_tests[] = {
{ "reject_interface_address", test_policies_reject_interface_address, 0,
NULL, NULL },
{ "reject_port_address", test_policies_reject_port_address, 0, NULL, NULL },
- { "fascist_firewall_allows_address",
+ { "reachable_addr_allows",
test_policies_fascist_firewall_allows_address, 0, NULL, NULL },
- { "fascist_firewall_choose_address",
+ { "reachable_addr_choose",
test_policies_fascist_firewall_choose_address, 0, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_prob_distr.c b/src/test/test_prob_distr.c
index 541a81df3a..da65a0f26d 100644
--- a/src/test/test_prob_distr.c
+++ b/src/test/test_prob_distr.c
@@ -442,7 +442,7 @@ test_log_logistic(void *arg)
/* x is a point in the support of the LogLogistic distribution */
double x;
/* 'p' is the probability that a random variable X for a given LogLogistic
- * probability ditribution will take value less-or-equal to x */
+ * probability distribution will take value less-or-equal to x */
double p;
/* 'np' is the probability that a random variable X for a given LogLogistic
* probability distribution will take value greater-or-equal to x. */
@@ -591,7 +591,7 @@ test_weibull(void *arg)
/* x is a point in the support of the Weibull distribution */
double x;
/* 'p' is the probability that a random variable X for a given Weibull
- * probability ditribution will take value less-or-equal to x */
+ * probability distribution will take value less-or-equal to x */
double p;
/* 'np' is the probability that a random variable X for a given Weibull
* probability distribution will take value greater-or-equal to x. */
diff --git a/src/test/test_process.c b/src/test/test_process.c
index c1da6db278..b5185242d3 100644
--- a/src/test/test_process.c
+++ b/src/test/test_process.c
@@ -156,7 +156,7 @@ test_default_values(void *arg)
/* Our command was given to the process_t's constructor in process_new(). */
tt_str_op("/path/to/nothing", OP_EQ, process_get_command(process));
- /* Make sure we are listed in the list of proccesses. */
+ /* Make sure we are listed in the list of processes. */
tt_assert(smartlist_contains(process_get_all_processes(),
process));
diff --git a/src/test/test_process_descs.c b/src/test/test_process_descs.c
index 14865cff13..5c2301f873 100644
--- a/src/test/test_process_descs.c
+++ b/src/test/test_process_descs.c
@@ -38,10 +38,10 @@ test_process_descs_versions(void *arg)
{ "Tor 0.4.0.5", true },
{ "Tor 0.4.1.1-alpha", true },
{ "Tor 0.4.1.4-rc", true },
+ { "Tor 0.4.1.5", true },
// new enough to be supported
{ "Tor 0.3.5.7", false },
{ "Tor 0.3.5.8", 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 },
diff --git a/src/test/test_protover.c b/src/test/test_protover.c
index 71f984a0ac..dd65f4bbf5 100644
--- a/src/test/test_protover.c
+++ b/src/test/test_protover.c
@@ -7,14 +7,18 @@
#include "orconfig.h"
#include "test/test.h"
-#include "core/or/protover.h"
+#include "lib/tls/tortls.h"
#include "core/or/or.h"
+
#include "core/or/connection_or.h"
-#include "lib/tls/tortls.h"
+#include "core/or/protover.h"
+#include "core/or/versions.h"
#include "feature/dirauth/dirvote.h"
+#include "feature/relay/relay_handshake.h"
+
static void
test_protover_parse(void *arg)
{
@@ -35,53 +39,25 @@ test_protover_parse(void *arg)
tt_int_op(smartlist_len(elts), OP_EQ, 4);
const proto_entry_t *e;
- const proto_range_t *r;
e = smartlist_get(elts, 0);
tt_str_op(e->name, OP_EQ, "Foo");
- tt_int_op(smartlist_len(e->ranges), OP_EQ, 2);
- {
- r = smartlist_get(e->ranges, 0);
- tt_int_op(r->low, OP_EQ, 1);
- tt_int_op(r->high, OP_EQ, 1);
-
- r = smartlist_get(e->ranges, 1);
- tt_int_op(r->low, OP_EQ, 3);
- tt_int_op(r->high, OP_EQ, 3);
- }
+ tt_int_op(e->bitmask, OP_EQ, 0x0a);
e = smartlist_get(elts, 1);
tt_str_op(e->name, OP_EQ, "Bar");
- tt_int_op(smartlist_len(e->ranges), OP_EQ, 1);
- {
- r = smartlist_get(e->ranges, 0);
- tt_int_op(r->low, OP_EQ, 3);
- tt_int_op(r->high, OP_EQ, 3);
- }
+ tt_int_op(e->bitmask, OP_EQ, 0x08);
e = smartlist_get(elts, 2);
tt_str_op(e->name, OP_EQ, "Baz");
- tt_int_op(smartlist_len(e->ranges), OP_EQ, 0);
+ tt_int_op(e->bitmask, OP_EQ, 0x00);
e = smartlist_get(elts, 3);
tt_str_op(e->name, OP_EQ, "Quux");
- tt_int_op(smartlist_len(e->ranges), OP_EQ, 3);
- {
- r = smartlist_get(e->ranges, 0);
- tt_int_op(r->low, OP_EQ, 9);
- tt_int_op(r->high, OP_EQ, 12);
-
- r = smartlist_get(e->ranges, 1);
- tt_int_op(r->low, OP_EQ, 14);
- tt_int_op(r->high, OP_EQ, 14);
-
- r = smartlist_get(e->ranges, 2);
- tt_int_op(r->low, OP_EQ, 15);
- tt_int_op(r->high, OP_EQ, 16);
- }
+ tt_int_op(e->bitmask, OP_EQ, 0x1de00);
re_encoded = encode_protocol_list(elts);
tt_assert(re_encoded);
- tt_str_op(re_encoded, OP_EQ, orig);
+ tt_str_op(re_encoded, OP_EQ, "Foo=1,3 Bar=3 Baz= Quux=9-12,14-16");
done:
if (elts)
@@ -366,23 +342,21 @@ test_protover_supports_version(void *arg)
* Hard-coded here, because they are not in the code, or not exposed in the
* headers. */
#define PROTOVER_LINKAUTH_V1 1
-#define PROTOVER_LINKAUTH_V3 3
-
+#define PROTOVER_LINKAUTH_V2 2
#define PROTOVER_RELAY_V1 1
-#define PROTOVER_RELAY_V2 2
+/* Deprecated HSIntro versions */
+#define PROTOVER_HS_INTRO_DEPRECATED_1 1
+#define PROTOVER_HS_INTRO_DEPRECATED_2 2
/* Highest supported HSv2 introduce protocol version.
- * Hard-coded here, because it does not appear anywhere in the code.
* It's not clear if we actually support version 2, see #25068. */
-#define PROTOVER_HSINTRO_V2 3
+#define PROTOVER_HS_INTRO_V2 3
-/* HSv2 Rend and HSDir protocol versions.
- * Hard-coded here, because they do not appear anywhere in the code. */
+/* HSv2 Rend and HSDir protocol versions. */
#define PROTOVER_HS_RENDEZVOUS_POINT_V2 1
#define PROTOVER_HSDIR_V2 1
-/* DirCache, Desc, Microdesc, and Cons protocol versions.
- * Hard-coded here, because they do not appear anywhere in the code. */
+/* DirCache, Desc, Microdesc, and Cons protocol versions. */
#define PROTOVER_DIRCACHE_V1 1
#define PROTOVER_DIRCACHE_V2 2
@@ -395,6 +369,10 @@ test_protover_supports_version(void *arg)
#define PROTOVER_CONS_V1 1
#define PROTOVER_CONS_V2 2
+#define PROTOVER_PADDING_V1 1
+
+#define PROTOVER_FLOWCTRL_V1 1
+
/* Make sure we haven't forgotten any supported protocols */
static void
test_protover_supported_protocols(void *arg)
@@ -409,24 +387,27 @@ test_protover_supported_protocols(void *arg)
PRT_LINK,
MAX_LINK_PROTO));
for (uint16_t i = 0; i < MAX_PROTOCOLS_TO_TEST; i++) {
- if (is_or_protocol_version_known(i)) {
- tt_assert(protocol_list_supports_protocol(supported_protocols,
+ tt_int_op(protocol_list_supports_protocol(supported_protocols,
PRT_LINK,
- i));
- }
+ i),
+ OP_EQ,
+ is_or_protocol_version_known(i));
}
-#ifdef HAVE_WORKING_TOR_TLS_GET_TLSSECRETS
- /* Legacy LinkAuth does not appear anywhere in the code. */
- tt_assert(protocol_list_supports_protocol(supported_protocols,
+ /* Legacy LinkAuth is only supported on OpenSSL and similar. */
+ tt_int_op(protocol_list_supports_protocol(supported_protocols,
PRT_LINKAUTH,
- PROTOVER_LINKAUTH_V1));
-#endif /* defined(HAVE_WORKING_TOR_TLS_GET_TLSSECRETS) */
- /* Latest LinkAuth is not exposed in the headers. */
- tt_assert(protocol_list_supports_protocol(supported_protocols,
- PRT_LINKAUTH,
- PROTOVER_LINKAUTH_V3));
- /* Is there any way to test for new LinkAuth? */
+ PROTOVER_LINKAUTH_V1),
+ OP_EQ,
+ authchallenge_type_is_supported(AUTHTYPE_RSA_SHA256_TLSSECRET));
+ /* LinkAuth=2 is unused */
+ tt_assert(!protocol_list_supports_protocol(supported_protocols,
+ PRT_LINKAUTH,
+ PROTOVER_LINKAUTH_V2));
+ tt_assert(
+ protocol_list_supports_protocol(supported_protocols,
+ PRT_LINKAUTH,
+ PROTOVER_LINKAUTH_ED25519_HANDSHAKE));
/* Relay protovers do not appear anywhere in the code. */
tt_assert(protocol_list_supports_protocol(supported_protocols,
@@ -434,20 +415,38 @@ test_protover_supported_protocols(void *arg)
PROTOVER_RELAY_V1));
tt_assert(protocol_list_supports_protocol(supported_protocols,
PRT_RELAY,
- PROTOVER_RELAY_V2));
- /* Is there any way to test for new Relay? */
+ PROTOVER_RELAY_EXTEND2));
+ tt_assert(protocol_list_supports_protocol(supported_protocols,
+ PRT_RELAY,
+ PROTOVER_RELAY_ACCEPT_IPV6));
+ tt_assert(protocol_list_supports_protocol(supported_protocols,
+ PRT_RELAY,
+ PROTOVER_RELAY_EXTEND_IPV6));
+ tt_assert(protocol_list_supports_protocol(supported_protocols,
+ PRT_RELAY,
+ PROTOVER_RELAY_CANONICAL_IPV6));
+ /* These HSIntro versions are deprecated */
+ tt_assert(!protocol_list_supports_protocol(supported_protocols,
+ PRT_HSINTRO,
+ PROTOVER_HS_INTRO_DEPRECATED_1));
+ tt_assert(!protocol_list_supports_protocol(supported_protocols,
+ PRT_HSINTRO,
+ PROTOVER_HS_INTRO_DEPRECATED_2));
/* We could test legacy HSIntro by calling rend_service_update_descriptor(),
* and checking the protocols field. But that's unlikely to change, so
* we just use a hard-coded value. */
tt_assert(protocol_list_supports_protocol(supported_protocols,
PRT_HSINTRO,
- PROTOVER_HSINTRO_V2));
+ PROTOVER_HS_INTRO_V2));
/* Test for HSv3 HSIntro */
tt_assert(protocol_list_supports_protocol(supported_protocols,
PRT_HSINTRO,
PROTOVER_HS_INTRO_V3));
- /* Is there any way to test for new HSIntro? */
+ /* Test for HSIntro DoS */
+ tt_assert(protocol_list_supports_protocol(supported_protocols,
+ PRT_HSINTRO,
+ PROTOVER_HS_INTRO_DOS));
/* Legacy HSRend does not appear anywhere in the code. */
tt_assert(protocol_list_supports_protocol(supported_protocols,
@@ -457,7 +456,6 @@ test_protover_supported_protocols(void *arg)
tt_assert(protocol_list_supports_protocol(supported_protocols,
PRT_HSREND,
PROTOVER_HS_RENDEZVOUS_POINT_V3));
- /* Is there any way to test for new HSRend? */
/* Legacy HSDir does not appear anywhere in the code. */
tt_assert(protocol_list_supports_protocol(supported_protocols,
@@ -467,16 +465,11 @@ test_protover_supported_protocols(void *arg)
tt_assert(protocol_list_supports_protocol(supported_protocols,
PRT_HSDIR,
PROTOVER_HSDIR_V3));
- /* Is there any way to test for new HSDir? */
/* No DirCache versions appear anywhere in the code. */
tt_assert(protocol_list_supports_protocol(supported_protocols,
PRT_DIRCACHE,
- PROTOVER_DIRCACHE_V1));
- tt_assert(protocol_list_supports_protocol(supported_protocols,
- PRT_DIRCACHE,
PROTOVER_DIRCACHE_V2));
- /* Is there any way to test for new DirCache? */
/* No Desc versions appear anywhere in the code. */
tt_assert(protocol_list_supports_protocol(supported_protocols,
@@ -494,7 +487,6 @@ test_protover_supported_protocols(void *arg)
tt_assert(protocol_list_supports_protocol(supported_protocols,
PRT_MICRODESC,
PROTOVER_MICRODESC_V2));
- /* Is there any way to test for new Microdesc? */
/* No Cons versions appear anywhere in the code. */
tt_assert(protocol_list_supports_protocol(supported_protocols,
@@ -503,7 +495,19 @@ test_protover_supported_protocols(void *arg)
tt_assert(protocol_list_supports_protocol(supported_protocols,
PRT_CONS,
PROTOVER_CONS_V2));
- /* Is there any way to test for new Cons? */
+
+ /* Padding=1 is deprecated. */
+ tt_assert(!protocol_list_supports_protocol(supported_protocols,
+ PRT_PADDING,
+ PROTOVER_PADDING_V1));
+ tt_assert(protocol_list_supports_protocol(supported_protocols,
+ PRT_PADDING,
+ PROTOVER_HS_SETUP_PADDING));
+
+ /* FlowCtrl */
+ tt_assert(protocol_list_supports_protocol(supported_protocols,
+ PRT_FLOWCTRL,
+ PROTOVER_FLOWCTRL_V1));
done:
;
@@ -534,6 +538,10 @@ test_protover_vote_roundtrip(void *args)
{ "N-1=1,2", "N-1=1-2" },
{ "-1=4294967295", NULL },
{ "-1=3", "-1=3" },
+ { "Foo=,", NULL },
+ { "Foo=,1", NULL },
+ { "Foo=1,,3", NULL },
+ { "Foo=1,3,", NULL },
/* junk. */
{ "!!3@*", NULL },
/* Missing equals sign */
@@ -629,6 +637,228 @@ test_protover_vote_roundtrip_ours(void *args)
tor_free(result);
}
+/* Stringifies its argument.
+ * 4 -> "4" */
+#define STR(x) #x
+
+#ifdef COCCI
+#define PROTOVER(proto_string, version_macro)
+#else
+/* Generate a protocol version string using proto_string and version_macro.
+ * PROTOVER("HSIntro", PROTOVER_HS_INTRO_DOS) -> "HSIntro" "=" "5"
+ * Uses two levels of macros to turn PROTOVER_HS_INTRO_DOS into "5".
+ */
+#define PROTOVER(proto_string, version_macro) \
+ (proto_string "=" STR(version_macro))
+#endif
+
+#define DEBUG_PROTOVER(flags) \
+ STMT_BEGIN \
+ log_debug(LD_GENERAL, \
+ "protovers:\n" \
+ "protocols_known: %d,\n" \
+ "supports_extend2_cells: %d,\n" \
+ "supports_accepting_ipv6_extends: %d,\n" \
+ "supports_initiating_ipv6_extends: %d,\n" \
+ "supports_canonical_ipv6_conns: %d,\n" \
+ "supports_ed25519_link_handshake_compat: %d,\n" \
+ "supports_ed25519_link_handshake_any: %d,\n" \
+ "supports_ed25519_hs_intro: %d,\n" \
+ "supports_establish_intro_dos_extension: %d,\n" \
+ "supports_v3_hsdir: %d,\n" \
+ "supports_v3_rendezvous_point: %d,\n" \
+ "supports_hs_setup_padding: %d.", \
+ (flags).protocols_known, \
+ (flags).supports_extend2_cells, \
+ (flags).supports_accepting_ipv6_extends, \
+ (flags).supports_initiating_ipv6_extends, \
+ (flags).supports_canonical_ipv6_conns, \
+ (flags).supports_ed25519_link_handshake_compat, \
+ (flags).supports_ed25519_link_handshake_any, \
+ (flags).supports_ed25519_hs_intro, \
+ (flags).supports_establish_intro_dos_extension, \
+ (flags).supports_v3_hsdir, \
+ (flags).supports_v3_rendezvous_point, \
+ (flags).supports_hs_setup_padding); \
+ STMT_END
+
+/* Test that the proto_string version version_macro sets summary_flag. */
+#define TEST_PROTOVER(proto_string, version_macro, summary_flag) \
+ STMT_BEGIN \
+ memset(&flags, 0, sizeof(flags)); \
+ summarize_protover_flags(&flags, \
+ PROTOVER(proto_string, version_macro), \
+ NULL); \
+ DEBUG_PROTOVER(flags); \
+ tt_int_op(flags.protocols_known, OP_EQ, 1); \
+ tt_int_op(flags.summary_flag, OP_EQ, 1); \
+ flags.protocols_known = 0; \
+ flags.summary_flag = 0; \
+ tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags)); \
+ STMT_END
+
+static void
+test_protover_summarize_flags(void *args)
+{
+ (void) args;
+ char pv[30];
+ memset(&pv, 0, sizeof(pv));
+
+ protover_summary_cache_free_all();
+
+ protover_summary_flags_t zero_flags;
+ memset(&zero_flags, 0, sizeof(zero_flags));
+ protover_summary_flags_t flags;
+
+ memset(&flags, 0, sizeof(flags));
+ summarize_protover_flags(&flags, NULL, NULL);
+ DEBUG_PROTOVER(flags);
+ tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
+
+ memset(&flags, 0, sizeof(flags));
+ summarize_protover_flags(&flags, "", "");
+ DEBUG_PROTOVER(flags);
+ tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
+
+ /* Now check version exceptions */
+
+ /* EXTEND2 cell support */
+ memset(&flags, 0, sizeof(flags));
+ summarize_protover_flags(&flags, NULL, "Tor 0.2.4.8-alpha");
+ DEBUG_PROTOVER(flags);
+ tt_int_op(flags.protocols_known, OP_EQ, 1);
+ tt_int_op(flags.supports_extend2_cells, OP_EQ, 1);
+ /* Now clear those flags, and check the rest are zero */
+ flags.protocols_known = 0;
+ flags.supports_extend2_cells = 0;
+ tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
+
+ /* disabling HSDir v3 support for buggy versions */
+ memset(&flags, 0, sizeof(flags));
+ summarize_protover_flags(&flags,
+ PROTOVER("HSDir", PROTOVER_HSDIR_V3),
+ NULL);
+ DEBUG_PROTOVER(flags);
+ tt_int_op(flags.protocols_known, OP_EQ, 1);
+ tt_int_op(flags.supports_v3_hsdir, OP_EQ, 1);
+ /* Now clear those flags, and check the rest are zero */
+ flags.protocols_known = 0;
+ flags.supports_v3_hsdir = 0;
+ tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
+
+ memset(&flags, 0, sizeof(flags));
+ summarize_protover_flags(&flags,
+ PROTOVER("HSDir", PROTOVER_HSDIR_V3),
+ "Tor 0.3.0.7");
+ DEBUG_PROTOVER(flags);
+ tt_int_op(flags.protocols_known, OP_EQ, 1);
+ /* Now clear that flag, and check the rest are zero */
+ flags.protocols_known = 0;
+ tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
+
+ /* Now check standard summaries */
+
+ /* LinkAuth */
+ memset(&flags, 0, sizeof(flags));
+ summarize_protover_flags(&flags,
+ PROTOVER("LinkAuth",
+ PROTOVER_LINKAUTH_ED25519_HANDSHAKE),
+ NULL);
+ DEBUG_PROTOVER(flags);
+ tt_int_op(flags.protocols_known, OP_EQ, 1);
+ tt_int_op(flags.supports_ed25519_link_handshake_compat, OP_EQ, 1);
+ tt_int_op(flags.supports_ed25519_link_handshake_any, OP_EQ, 1);
+ /* Now clear those flags, and check the rest are zero */
+ flags.protocols_known = 0;
+ flags.supports_ed25519_link_handshake_compat = 0;
+ flags.supports_ed25519_link_handshake_any = 0;
+ tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
+
+ /* Test one greater */
+ memset(&flags, 0, sizeof(flags));
+ snprintf(pv, sizeof(pv),
+ "%s=%d", "LinkAuth", PROTOVER_LINKAUTH_ED25519_HANDSHAKE + 1);
+ summarize_protover_flags(&flags, pv, NULL);
+ DEBUG_PROTOVER(flags);
+ tt_int_op(flags.protocols_known, OP_EQ, 1);
+ tt_int_op(flags.supports_ed25519_link_handshake_compat, OP_EQ, 0);
+ tt_int_op(flags.supports_ed25519_link_handshake_any, OP_EQ, 1);
+ /* Now clear those flags, and check the rest are zero */
+ flags.protocols_known = 0;
+ flags.supports_ed25519_link_handshake_compat = 0;
+ flags.supports_ed25519_link_handshake_any = 0;
+ tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
+
+ /* Test one less */
+ memset(&flags, 0, sizeof(flags));
+ snprintf(pv, sizeof(pv),
+ "%s=%d", "LinkAuth", PROTOVER_LINKAUTH_ED25519_HANDSHAKE - 1);
+ summarize_protover_flags(&flags, pv, NULL);
+ DEBUG_PROTOVER(flags);
+ tt_int_op(flags.protocols_known, OP_EQ, 1);
+ tt_int_op(flags.supports_ed25519_link_handshake_compat, OP_EQ, 0);
+ tt_int_op(flags.supports_ed25519_link_handshake_any, OP_EQ, 0);
+ /* Now clear those flags, and check the rest are zero */
+ flags.protocols_known = 0;
+ flags.supports_ed25519_link_handshake_compat = 0;
+ flags.supports_ed25519_link_handshake_any = 0;
+ tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
+
+ /* We don't test "one more" and "one less" for each protocol version.
+ * But that could be a useful thing to add. */
+
+ /* Relay */
+ memset(&flags, 0, sizeof(flags));
+ /* This test relies on these versions being equal */
+ tt_int_op(PROTOVER_RELAY_EXTEND2, OP_EQ, PROTOVER_RELAY_ACCEPT_IPV6);
+ summarize_protover_flags(&flags,
+ PROTOVER("Relay", PROTOVER_RELAY_EXTEND2), NULL);
+ DEBUG_PROTOVER(flags);
+ tt_int_op(flags.protocols_known, OP_EQ, 1);
+ tt_int_op(flags.supports_extend2_cells, OP_EQ, 1);
+ tt_int_op(flags.supports_accepting_ipv6_extends, OP_EQ, 1);
+ /* Now clear those flags, and check the rest are zero */
+ flags.protocols_known = 0;
+ flags.supports_extend2_cells = 0;
+ flags.supports_accepting_ipv6_extends = 0;
+ tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
+
+ memset(&flags, 0, sizeof(flags));
+ /* This test relies on these versions being equal */
+ tt_int_op(PROTOVER_RELAY_EXTEND_IPV6, OP_EQ, PROTOVER_RELAY_CANONICAL_IPV6);
+ summarize_protover_flags(&flags,
+ PROTOVER("Relay", PROTOVER_RELAY_EXTEND_IPV6),
+ NULL);
+ DEBUG_PROTOVER(flags);
+ tt_int_op(flags.protocols_known, OP_EQ, 1);
+ tt_int_op(flags.supports_accepting_ipv6_extends, OP_EQ, 1);
+ tt_int_op(flags.supports_initiating_ipv6_extends, OP_EQ, 1);
+ tt_int_op(flags.supports_canonical_ipv6_conns, OP_EQ, 1);
+ /* Now clear those flags, and check the rest are zero */
+ flags.protocols_known = 0;
+ flags.supports_accepting_ipv6_extends = 0;
+ flags.supports_initiating_ipv6_extends = 0;
+ flags.supports_canonical_ipv6_conns = 0;
+ tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
+
+ TEST_PROTOVER("HSIntro", PROTOVER_HS_INTRO_V3,
+ supports_ed25519_hs_intro);
+ TEST_PROTOVER("HSIntro", PROTOVER_HS_INTRO_DOS,
+ supports_establish_intro_dos_extension);
+
+ TEST_PROTOVER("HSRend", PROTOVER_HS_RENDEZVOUS_POINT_V3,
+ supports_v3_rendezvous_point);
+
+ TEST_PROTOVER("HSDir", PROTOVER_HSDIR_V3,
+ supports_v3_hsdir);
+
+ TEST_PROTOVER("Padding", PROTOVER_HS_SETUP_PADDING,
+ supports_hs_setup_padding);
+
+ done:
+ ;
+}
+
#define PV_TEST(name, flags) \
{ #name, test_protover_ ##name, (flags), NULL, NULL }
@@ -643,5 +873,7 @@ struct testcase_t protover_tests[] = {
PV_TEST(supported_protocols, 0),
PV_TEST(vote_roundtrip, 0),
PV_TEST(vote_roundtrip_ours, 0),
+ /* fork, because we memoize flags internally */
+ PV_TEST(summarize_flags, TT_FORK),
END_OF_TESTCASES
};
diff --git a/src/test/test_rebind.py b/src/test/test_rebind.py
index 3fc3deb68e..6b72ece911 100644
--- a/src/test/test_rebind.py
+++ b/src/test/test_rebind.py
@@ -116,7 +116,7 @@ tor_process = subprocess.Popen([tor_path,
if tor_process == None:
fail('ERROR: running tor failed')
-wait_for_log('Opened Control listener on')
+wait_for_log('Opened Control listener')
try_connecting_to_socksport()
diff --git a/src/test/test_relay.c b/src/test/test_relay.c
index 066aeaa7b3..b287f0d38b 100644
--- a/src/test/test_relay.c
+++ b/src/test/test_relay.c
@@ -3,20 +3,31 @@
#define CIRCUITBUILD_PRIVATE
#define RELAY_PRIVATE
-#define REPHIST_PRIVATE
+#define BWHIST_PRIVATE
#include "core/or/or.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/channeltls.h"
-#include "feature/stats/rephist.h"
+#include "feature/stats/bwhist.h"
#include "core/or/relay.h"
#include "lib/container/order.h"
+#include "lib/encoding/confline.h"
/* For init/free stuff */
#include "core/or/scheduler.h"
#include "core/or/cell_st.h"
#include "core/or/or_circuit_st.h"
+#define RESOLVE_ADDR_PRIVATE
+#include "feature/nodelist/dirlist.h"
+#include "feature/relay/relay_find_addr.h"
+#include "feature/relay/routermode.h"
+#include "feature/dirclient/dir_server_st.h"
+
+#define CONFIG_PRIVATE
+#include "app/config/config.h"
+#include "app/config/resolve_addr.h"
+
/* Test suite stuff */
#include "test/test.h"
#include "test/fakechans.h"
@@ -24,6 +35,13 @@
static void test_relay_append_cell_to_circuit_queue(void *arg);
+static int
+mock_server_mode_true(const or_options_t *options)
+{
+ (void) options;
+ return 1;
+}
+
static void
assert_circuit_ok_mock(const circuit_t *c)
{
@@ -192,10 +210,179 @@ test_relay_append_cell_to_circuit_queue(void *arg)
return;
}
+static void
+test_suggested_address(void *arg)
+{
+ int ret;
+ const char *untrusted_id = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
+ dir_server_t *ds = NULL;
+ tor_addr_t ipv4_addr, ipv6_addr, cache_addr;
+ tor_addr_t trusted_addr, untrusted_addr;
+ tor_addr_port_t trusted_ap_v6 = { .port = 443 };
+
+ (void) arg;
+
+ MOCK(server_mode, mock_server_mode_true);
+
+ /* Unstrusted relay source. */
+ ret = tor_addr_parse(&untrusted_addr, "8.8.8.8");
+ tt_int_op(ret, OP_EQ, AF_INET);
+
+ /* Add gabelmoo as a trusted directory authority. */
+ ret = tor_addr_parse(&trusted_addr, "[2001:638:a000:4140::ffff:189]");
+ tt_int_op(ret, OP_EQ, AF_INET6);
+ tor_addr_copy(&trusted_ap_v6.addr, &trusted_addr);
+
+ ds = trusted_dir_server_new("gabelmoo", "131.188.40.189", 80, 443,
+ &trusted_ap_v6,
+ "F2044413DAC2E02E3D6BCF4735A19BCA1DE97281",
+ "ED03BB616EB2F60BEC80151114BB25CEF515B226",
+ V3_DIRINFO, 1.0);
+ tt_assert(ds);
+ dir_server_add(ds);
+
+ /* 1. Valid IPv4 from a trusted authority (gabelmoo). */
+ ret = tor_addr_parse(&ipv4_addr, "1.2.3.4");
+ relay_address_new_suggestion(&ipv4_addr, &ds->ipv4_addr, ds->digest);
+ resolved_addr_get_suggested(AF_INET, &cache_addr);
+ tt_assert(tor_addr_eq(&cache_addr, &ipv4_addr));
+ resolve_addr_reset_suggested(AF_INET);
+
+ /* 2. Valid IPv6 from a trusted authority (gabelmoo). */
+ ret = tor_addr_parse(&ipv6_addr, "[4242::4242]");
+ relay_address_new_suggestion(&ipv6_addr, &ds->ipv6_addr, ds->digest);
+ resolved_addr_get_suggested(AF_INET6, &cache_addr);
+ tt_assert(tor_addr_eq(&cache_addr, &ipv6_addr));
+ resolve_addr_reset_suggested(AF_INET6);
+
+ /* 3. Valid IPv4 but untrusted source. */
+ ret = tor_addr_parse(&ipv4_addr, "1.2.3.4");
+ relay_address_new_suggestion(&ipv4_addr, &untrusted_addr, untrusted_id);
+ resolved_addr_get_suggested(AF_INET, &cache_addr);
+ tt_assert(tor_addr_is_unspec(&cache_addr));
+
+ /* 4. Valid IPv6 but untrusted source. */
+ ret = tor_addr_parse(&ipv6_addr, "[4242::4242]");
+ relay_address_new_suggestion(&ipv6_addr, &untrusted_addr, untrusted_id);
+ resolved_addr_get_suggested(AF_INET6, &cache_addr);
+ tt_assert(tor_addr_is_unspec(&cache_addr));
+
+ /* 5. Internal IPv4 from a trusted authority (gabelmoo). */
+ ret = tor_addr_parse(&ipv4_addr, "127.0.0.1");
+ relay_address_new_suggestion(&ipv4_addr, &ds->ipv4_addr, ds->digest);
+ resolved_addr_get_suggested(AF_INET, &cache_addr);
+ tt_assert(tor_addr_is_unspec(&cache_addr));
+
+ /* 6. Internal IPv6 from a trusted authority (gabelmoo). */
+ ret = tor_addr_parse(&ipv6_addr, "[::1]");
+ relay_address_new_suggestion(&ipv6_addr, &ds->ipv6_addr, ds->digest);
+ resolved_addr_get_suggested(AF_INET6, &cache_addr);
+ tt_assert(tor_addr_is_unspec(&cache_addr));
+
+ /* 7. IPv4 from a trusted authority (gabelmoo). */
+ relay_address_new_suggestion(&ds->ipv4_addr, &ds->ipv4_addr, ds->digest);
+ resolved_addr_get_suggested(AF_INET, &cache_addr);
+ tt_assert(tor_addr_is_unspec(&cache_addr));
+
+ /* 8. IPv6 from a trusted authority (gabelmoo). */
+ relay_address_new_suggestion(&ds->ipv6_addr, &ds->ipv6_addr, ds->digest);
+ resolved_addr_get_suggested(AF_INET6, &cache_addr);
+ tt_assert(tor_addr_is_unspec(&cache_addr));
+
+ done:
+ dirlist_free_all();
+
+ UNMOCK(server_mode);
+}
+
+static void
+test_find_addr_to_publish(void *arg)
+{
+ int family;
+ bool ret;
+ tor_addr_t ipv4_addr, ipv6_addr, cache_addr;
+ or_options_t *options;
+
+ (void) arg;
+
+ options = options_new();
+ options_init(options);
+
+ /* Populate our resolved cache with a valid IPv4 and IPv6. */
+ family = tor_addr_parse(&ipv4_addr, "1.2.3.4");
+ tt_int_op(family, OP_EQ, AF_INET);
+ resolved_addr_set_last(&ipv4_addr, RESOLVED_ADDR_CONFIGURED, NULL);
+ resolved_addr_get_last(AF_INET, &cache_addr);
+ tt_assert(tor_addr_eq(&ipv4_addr, &cache_addr));
+
+ family = tor_addr_parse(&ipv6_addr, "[4242::4242]");
+ tt_int_op(family, OP_EQ, AF_INET6);
+ resolved_addr_set_last(&ipv6_addr, RESOLVED_ADDR_CONFIGURED, NULL);
+ resolved_addr_get_last(AF_INET6, &cache_addr);
+ tt_assert(tor_addr_eq(&ipv6_addr, &cache_addr));
+
+ /* Setup ORPort config. */
+ {
+ int n, w, r;
+ char *msg = NULL;
+
+ config_line_append(&options->ORPort_lines, "ORPort", "9001");
+
+ r = parse_ports(options, 0, &msg, &n, &w);
+ tt_int_op(r, OP_EQ, 0);
+ }
+
+ /* 1. Address located in the resolved cache. */
+ ret = relay_find_addr_to_publish(options, AF_INET,
+ RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
+ tt_assert(ret);
+ tt_assert(tor_addr_eq(&ipv4_addr, &cache_addr));
+
+ ret = relay_find_addr_to_publish(options, AF_INET6,
+ RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
+ tt_assert(ret);
+ tt_assert(tor_addr_eq(&ipv6_addr, &cache_addr));
+ resolved_addr_reset_last(AF_INET);
+ resolved_addr_reset_last(AF_INET6);
+
+ /* 2. No IP in the resolve cache, go to the suggested cache. We will ignore
+ * the find_my_address() code path because that is extensively tested in
+ * another unit tests. */
+ resolved_addr_set_suggested(&ipv4_addr);
+ ret = relay_find_addr_to_publish(options, AF_INET,
+ RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
+ tt_assert(ret);
+ tt_assert(tor_addr_eq(&ipv4_addr, &cache_addr));
+
+ resolved_addr_set_suggested(&ipv6_addr);
+ ret = relay_find_addr_to_publish(options, AF_INET6,
+ RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
+ tt_assert(ret);
+ tt_assert(tor_addr_eq(&ipv6_addr, &cache_addr));
+ resolve_addr_reset_suggested(AF_INET);
+ resolve_addr_reset_suggested(AF_INET6);
+
+ /* 3. No IP anywhere. */
+ ret = relay_find_addr_to_publish(options, AF_INET,
+ RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
+ tt_assert(!ret);
+ ret = relay_find_addr_to_publish(options, AF_INET6,
+ RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
+ tt_assert(!ret);
+
+ done:
+ or_options_free(options);
+}
+
struct testcase_t relay_tests[] = {
{ "append_cell_to_circuit_queue", test_relay_append_cell_to_circuit_queue,
TT_FORK, NULL, NULL },
{ "close_circ_rephist", test_relay_close_circuit,
TT_FORK, NULL, NULL },
+ { "suggested_address", test_suggested_address,
+ TT_FORK, NULL, NULL },
+ { "find_addr_to_publish", test_find_addr_to_publish,
+ TT_FORK, NULL, NULL },
+
END_OF_TESTCASES
};
diff --git a/src/test/test_relaycell.c b/src/test/test_relaycell.c
index da9e791fb6..6f5bc7e770 100644
--- a/src/test/test_relaycell.c
+++ b/src/test/test_relaycell.c
@@ -220,7 +220,6 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
int sendme_cells = (STREAMWINDOW_START-edgeconn->package_window)
/STREAMWINDOW_INCREMENT;
ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0;
connection_edge_reached_eof(edgeconn);
/* Data cell not in the half-opened list */
@@ -272,7 +271,6 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
/* DATA cells up to limit */
while (data_cells > 0) {
ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0;
PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234");
if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
@@ -283,7 +281,6 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
data_cells--;
}
ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0;
PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234");
if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
@@ -295,7 +292,6 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
/* SENDME cells up to limit */
while (sendme_cells > 0) {
ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0;
PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234");
if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
@@ -306,7 +302,6 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
sendme_cells--;
}
ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0;
PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234");
if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
@@ -317,7 +312,6 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
/* Only one END cell */
ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0;
PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234");
if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
@@ -327,7 +321,6 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
ASSERT_COUNTED_BW();
ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0;
PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234");
if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
@@ -339,7 +332,6 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
edgeconn = ENTRY_TO_EDGE_CONN(entryconn3);
edgeconn->base_.state = AP_CONN_STATE_OPEN;
ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0;
/* sendme cell on open entryconn with full window */
PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234");
int ret =
@@ -350,7 +342,6 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
/* connected cell on a after EOF */
ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0;
edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT;
connection_edge_reached_eof(edgeconn);
PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234");
@@ -362,7 +353,6 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
ASSERT_COUNTED_BW();
ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0;
PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234");
if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
@@ -373,7 +363,6 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
/* DATA and SENDME after END cell */
ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0;
PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234");
if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
@@ -383,7 +372,6 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
ASSERT_COUNTED_BW();
ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0;
PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234");
ret =
connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
@@ -392,7 +380,6 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
ASSERT_UNCOUNTED_BW();
ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0;
PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234");
if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
@@ -407,11 +394,9 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
edgeconn->base_.state = AP_CONN_STATE_RESOLVE_WAIT;
edgeconn->on_circuit = TO_CIRCUIT(circ);
ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0;
connection_edge_reached_eof(edgeconn);
ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0;
PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_RESOLVED,
"\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
@@ -422,7 +407,6 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
ASSERT_COUNTED_BW();
ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0;
PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_RESOLVED,
"\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
@@ -431,7 +415,6 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
/* Data not counted after resolved */
ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0;
PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234");
if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
@@ -442,7 +425,6 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
/* End not counted after resolved */
ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0;
PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234");
if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
@@ -509,7 +491,7 @@ subtest_halfstream_insertremove(int num)
entryconn = fake_entry_conn(circ, 23);
edgeconn = ENTRY_TO_EDGE_CONN(entryconn);
- /* Explicity test all operations on an absent stream list */
+ /* Explicitly test all operations on an absent stream list */
tt_int_op(connection_half_edge_is_valid_data(circ->half_streams,
23), OP_EQ, 0);
tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams,
@@ -588,7 +570,7 @@ subtest_halfstream_insertremove(int num)
}
tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 0);
- /* Explicity test all operations on an empty stream list */
+ /* Explicitly test all operations on an empty stream list */
tt_int_op(connection_half_edge_is_valid_data(circ->half_streams,
23), OP_EQ, 0);
tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams,
@@ -660,7 +642,6 @@ test_halfstream_wrap(void *arg)
/* Insert an opened stream on the circ with that id */
ENTRY_TO_CONN(entryconn)->marked_for_close = 0;
- ENTRY_TO_CONN(entryconn)->outbuf_flushlen = 0;
edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT;
circ->p_streams = edgeconn;
@@ -784,14 +765,12 @@ test_circbw_relay(void *arg)
/* Sendme on valid stream: counted */
edgeconn->package_window -= STREAMWINDOW_INCREMENT;
- ENTRY_TO_CONN(entryconn1)->outbuf_flushlen = 0;
PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234");
connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
circ->cpath);
ASSERT_COUNTED_BW();
/* Sendme on valid stream with full window: not counted */
- ENTRY_TO_CONN(entryconn1)->outbuf_flushlen = 0;
PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234");
edgeconn->package_window = STREAMWINDOW_START;
connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
@@ -799,7 +778,6 @@ test_circbw_relay(void *arg)
ASSERT_UNCOUNTED_BW();
/* Sendme on unknown stream: not counted */
- ENTRY_TO_CONN(entryconn1)->outbuf_flushlen = 0;
PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234");
connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
circ->cpath);
diff --git a/src/test/test_router.c b/src/test/test_router.c
index cf0c2b3dd1..895178f788 100644
--- a/src/test/test_router.c
+++ b/src/test/test_router.c
@@ -23,8 +23,9 @@
#include "feature/nodelist/routerinfo_st.h"
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/routerstatus_st.h"
+#include "feature/nodelist/torcert.h"
#include "feature/relay/router.h"
-#include "feature/stats/rephist.h"
+#include "feature/stats/bwhist.h"
#include "lib/crypt_ops/crypto_curve25519.h"
#include "lib/crypt_ops/crypto_ed25519.h"
#include "lib/encoding/confline.h"
@@ -35,44 +36,34 @@
#include "test/test.h"
#include "test/log_test_helpers.h"
-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*
-rtr_tests_router_get_my_routerinfo(void)
+static routerinfo_t *
+rtr_tests_gen_routerinfo(crypto_pk_t *ident_key, crypto_pk_t *tap_key)
{
- crypto_pk_t* ident_key;
- crypto_pk_t* tap_key;
time_t now;
- if (!mock_routerinfo) {
- /* Mock the published timestamp, otherwise router_dump_router_to_string()
- * will poop its pants. */
- time(&now);
-
- /* We'll need keys, or router_dump_router_to_string() would return NULL. */
- ident_key = pk_generate(0);
- tap_key = pk_generate(0);
-
- tor_assert(ident_key != NULL);
- tor_assert(tap_key != NULL);
-
- mock_routerinfo = tor_malloc_zero(sizeof(routerinfo_t));
- mock_routerinfo->nickname = tor_strdup("ConlonNancarrow");
- mock_routerinfo->addr = 123456789;
- mock_routerinfo->or_port = 443;
- mock_routerinfo->platform = tor_strdup("unittest");
- mock_routerinfo->cache_info.published_on = now;
- mock_routerinfo->identity_pkey = crypto_pk_dup_key(ident_key);
- router_set_rsa_onion_pkey(tap_key, &mock_routerinfo->onion_pkey,
- &mock_routerinfo->onion_pkey_len);
- mock_routerinfo->bandwidthrate = 9001;
- mock_routerinfo->bandwidthburst = 9002;
- crypto_pk_free(ident_key);
- crypto_pk_free(tap_key);
- }
+ routerinfo_t *mock_routerinfo;
+
+ /* Mock the published timestamp, otherwise router_dump_router_to_string()
+ * will poop its pants. */
+ time(&now);
+
+ /* We'll need keys, or router_dump_router_to_string() would return NULL. */
+ tor_assert(ident_key != NULL);
+ tor_assert(tap_key != NULL);
+
+ mock_routerinfo = tor_malloc_zero(sizeof(routerinfo_t));
+ mock_routerinfo->nickname = tor_strdup("ConlonNancarrow");
+ tor_addr_from_ipv4h(&mock_routerinfo->ipv4_addr, 123456789);
+ mock_routerinfo->ipv4_orport = 443;
+ mock_routerinfo->platform = tor_strdup("unittest");
+ mock_routerinfo->cache_info.published_on = now;
+ mock_routerinfo->identity_pkey = crypto_pk_dup_key(ident_key);
+ mock_routerinfo->protocol_list =
+ tor_strdup("Cons=1-2 Desc=1-2 DirCache=1-2");
+ router_set_rsa_onion_pkey(tap_key, &mock_routerinfo->onion_pkey,
+ &mock_routerinfo->onion_pkey_len);
+ mock_routerinfo->bandwidthrate = 9001;
+ mock_routerinfo->bandwidthburst = 9002;
return mock_routerinfo;
}
@@ -87,12 +78,12 @@ test_router_dump_router_to_string_no_bridge_distribution_method(void *arg)
routerinfo_t* router = NULL;
curve25519_keypair_t ntor_keypair;
ed25519_keypair_t signing_keypair;
+ ed25519_keypair_t identity_keypair;
char* desc = NULL;
char* found = NULL;
(void)arg;
-
- MOCK(router_get_my_routerinfo,
- rtr_tests_router_get_my_routerinfo);
+ crypto_pk_t *ident_key = pk_generate(0);
+ crypto_pk_t *tap_key = pk_generate(0);
options->ORPort_set = 1;
options->BridgeRelay = 1;
@@ -100,12 +91,21 @@ test_router_dump_router_to_string_no_bridge_distribution_method(void *arg)
/* Generate keys which router_dump_router_to_string() expects to exist. */
tt_int_op(0, OP_EQ, curve25519_keypair_generate(&ntor_keypair, 0));
tt_int_op(0, OP_EQ, ed25519_keypair_generate(&signing_keypair, 0));
+ tt_int_op(0, OP_EQ, ed25519_keypair_generate(&identity_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();
+ router = rtr_tests_gen_routerinfo(ident_key, tap_key);
tt_ptr_op(router, OP_NE, NULL);
+ router->cache_info.signing_key_cert =
+ tor_cert_create_ed25519(&identity_keypair,
+ CERT_TYPE_ID_SIGNING,
+ &signing_keypair.pubkey,
+ time(NULL),
+ 86400,
+ CERT_FLAG_INCLUDE_SIGNING_KEY);
+
/* The real router_get_my_routerinfo() looks up onion_curve25519_pkey using
* get_current_curve25519_keypair(), but we don't initialise static data in
* this test. */
@@ -113,22 +113,22 @@ test_router_dump_router_to_string_no_bridge_distribution_method(void *arg)
/* Generate our server descriptor and ensure that the substring
* "bridge-distribution-request any" occurs somewhere within it. */
- crypto_pk_t *onion_pkey = router_get_rsa_onion_pkey(router->onion_pkey,
- router->onion_pkey_len);
desc = router_dump_router_to_string(router,
- router->identity_pkey,
- onion_pkey,
+ ident_key,
+ tap_key,
&ntor_keypair,
&signing_keypair);
- crypto_pk_free(onion_pkey);
tt_ptr_op(desc, OP_NE, NULL);
found = strstr(desc, needle);
tt_ptr_op(found, OP_NE, NULL);
done:
- UNMOCK(router_get_my_routerinfo);
-
+ if (router)
+ router->onion_curve25519_pkey = NULL; // avoid double-free
+ routerinfo_free(router);
tor_free(desc);
+ crypto_pk_free(ident_key);
+ crypto_pk_free(tap_key);
}
static routerinfo_t *mock_router_get_my_routerinfo_result = NULL;
@@ -226,13 +226,13 @@ test_router_check_descriptor_bandwidth_changed(void *arg)
/* When uptime is less than 24h and bandwidthcapacity does not change
* Uptime: 10800, last_changed: x, Previous bw: 10000, Current bw: 20001 */
- MOCK(rep_hist_bandwidth_assess, mock_rep_hist_bandwidth_assess);
+ MOCK(bwhist_bandwidth_assess, mock_rep_hist_bandwidth_assess);
setup_full_capture_of_logs(LOG_INFO);
check_descriptor_bandwidth_changed(time(NULL) + 6*60*60 + 1);
expect_log_msg_containing(
"Measured bandwidth has changed; rebuilding descriptor.");
UNMOCK(get_uptime);
- UNMOCK(rep_hist_bandwidth_assess);
+ UNMOCK(bwhist_bandwidth_assess);
teardown_capture_of_logs();
/* When uptime is more than 24h */
@@ -507,13 +507,12 @@ test_router_get_advertised_or_port(void *arg)
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);
+ // Test one failing case of routerconf_find_ipv6_or_ap().
+ routerconf_find_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));
+ // And one failing case of routerconf_find_or_port().
+ tt_int_op(0, OP_EQ, routerconf_find_or_port(opts, AF_INET));
// Set up a couple of configured ports.
config_line_append(&opts->ORPort_lines, "ORPort", "[1234::5678]:auto");
@@ -522,13 +521,12 @@ test_router_get_advertised_or_port(void *arg)
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_int_op(0, OP_EQ, routerconf_find_or_port(opts, AF_INET6));
+ routerconf_find_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));
+ tt_int_op(9999, OP_EQ, routerconf_find_or_port(opts, AF_INET));
// Now set up a dummy listener.
MOCK(get_connection_array, mock_get_connection_array);
@@ -538,16 +536,15 @@ test_router_get_advertised_or_port(void *arg)
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));
+ tt_int_op(54321, OP_EQ, routerconf_find_or_port(opts, AF_INET6));
- // Test one succeeding case of router_get_advertised_ipv6_or_ap().
- router_get_advertised_ipv6_or_ap(opts, &ipv6);
+ // Test one succeeding case of routerconf_find_ipv6_or_ap().
+ routerconf_find_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));
+ tt_int_op(9999, OP_EQ, routerconf_find_or_port(opts, AF_INET));
done:
or_options_free(opts);
@@ -573,28 +570,26 @@ test_router_get_advertised_or_port_localhost(void *arg)
tt_assert(r == 0);
// We should refuse to advertise them, since we have default dirauths.
- router_get_advertised_ipv6_or_ap(opts, &ipv6);
+ routerconf_find_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));
+ tt_int_op(9999, OP_EQ, routerconf_find_or_port(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));
+ tt_int_op(8888, OP_EQ, routerconf_find_or_port(opts, AF_INET));
// 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_int_op(9999, OP_EQ, routerconf_find_or_port(opts, AF_INET6));
+ routerconf_find_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));
+ tt_int_op(8888, OP_EQ, routerconf_find_or_port(opts, AF_INET));
done:
or_options_free(opts);
diff --git a/src/test/test_routerkeys.c b/src/test/test_routerkeys.c
index fc437dccc0..e5314046b9 100644
--- a/src/test/test_routerkeys.c
+++ b/src/test/test_routerkeys.c
@@ -51,7 +51,7 @@ test_routerkeys_write_fingerprint(void *arg)
tt_int_op(crypto_pk_cmp_keys(get_server_identity_key(),key),OP_EQ,0);
/* Write fingerprint file */
- tt_int_op(0, OP_EQ, router_write_fingerprint(0));
+ tt_int_op(0, OP_EQ, router_write_fingerprint(0, 0));
cp = read_file_to_str(get_fname("write_fingerprint/fingerprint"),
0, NULL);
crypto_pk_get_fingerprint(key, fp, 0);
@@ -61,7 +61,7 @@ test_routerkeys_write_fingerprint(void *arg)
tor_free(cp2);
/* Write hashed-fingerprint file */
- tt_int_op(0, OP_EQ, router_write_fingerprint(1));
+ tt_int_op(0, OP_EQ, router_write_fingerprint(1, 0));
cp = read_file_to_str(get_fname("write_fingerprint/hashed-fingerprint"),
0, NULL);
crypto_pk_get_hashed_fingerprint(key, fp);
@@ -73,7 +73,7 @@ test_routerkeys_write_fingerprint(void *arg)
/* Replace outdated file */
write_str_to_file(get_fname("write_fingerprint/hashed-fingerprint"),
"junk goes here", 0);
- tt_int_op(0, OP_EQ, router_write_fingerprint(1));
+ tt_int_op(0, OP_EQ, router_write_fingerprint(1, 0));
cp = read_file_to_str(get_fname("write_fingerprint/hashed-fingerprint"),
0, NULL);
crypto_pk_get_hashed_fingerprint(key, fp);
@@ -90,6 +90,51 @@ test_routerkeys_write_fingerprint(void *arg)
}
static void
+test_routerkeys_write_ed25519_identity(void *arg)
+{
+ crypto_pk_t *key = pk_generate(2);
+ or_options_t *options = get_options_mutable();
+ time_t now = time(NULL);
+ const char *ddir = get_fname("write_fingerprint");
+ char *cp = NULL, *cp2 = NULL;
+ char ed25519_id[BASE64_DIGEST256_LEN + 1];
+
+ (void) arg;
+
+ tt_assert(key);
+
+ options->ORPort_set = 1; /* So that we can get the server ID key */
+ tor_free(options->DataDirectory);
+ options->DataDirectory = tor_strdup(ddir);
+ options->Nickname = tor_strdup("haflinger");
+ set_server_identity_key(key);
+ set_client_identity_key(crypto_pk_dup_key(key));
+
+ load_ed_keys(options, now);
+ tt_assert(get_master_identity_key());
+
+ tt_int_op(0, OP_EQ, check_private_dir(ddir, CPD_CREATE, NULL));
+
+ /* Write fingerprint file */
+ tt_int_op(0, OP_EQ, router_write_fingerprint(0, 1));
+ cp = read_file_to_str(get_fname("write_fingerprint/fingerprint-ed25519"),
+ 0, NULL);
+ digest256_to_base64(ed25519_id,
+ (const char *) get_master_identity_key()->pubkey);
+ tor_asprintf(&cp2, "haflinger %s\n", ed25519_id);
+ tt_str_op(cp, OP_EQ, cp2);
+ tor_free(cp);
+ tor_free(cp2);
+
+ done:
+ crypto_pk_free(key);
+ set_client_identity_key(NULL);
+ tor_free(cp);
+ tor_free(cp2);
+ routerkeys_free_all();
+}
+
+static void
test_routerkeys_ed_certs(void *args)
{
(void)args;
@@ -106,7 +151,7 @@ test_routerkeys_ed_certs(void *args)
for (int i = 0; i <= 1; ++i) {
uint32_t flags = i ? CERT_FLAG_INCLUDE_SIGNING_KEY : 0;
- cert[i] = tor_cert_create(&kp1, 5, &kp2.pubkey, now, 10000, flags);
+ cert[i] = tor_cert_create_ed25519(&kp1, 5, &kp2.pubkey, now, 10000, flags);
tt_assert(cert[i]);
tt_uint_op(cert[i]->sig_bad, OP_EQ, 0);
@@ -695,6 +740,7 @@ test_routerkeys_rsa_ed_crosscert(void *arg)
struct testcase_t routerkeys_tests[] = {
TEST(write_fingerprint, TT_FORK),
+ TEST(write_ed25519_identity, TT_FORK),
TEST(ed_certs, TT_FORK),
TEST(ed_key_create, TT_FORK),
TEST(ed_key_init_basic, TT_FORK),
diff --git a/src/test/test_routerlist.c b/src/test/test_routerlist.c
index f2a83c18a3..c7b65006f0 100644
--- a/src/test/test_routerlist.c
+++ b/src/test/test_routerlist.c
@@ -52,8 +52,6 @@
#include "test/test_dir_common.h"
#include "test/log_test_helpers.h"
-void construct_consensus(char **consensus_text_md, time_t now);
-
static authority_cert_t *mock_cert;
static authority_cert_t *
@@ -150,7 +148,7 @@ test_routerlist_launch_descriptor_downloads(void *arg)
smartlist_free(downloadable);
}
-void
+static void
construct_consensus(char **consensus_text_md, time_t now)
{
networkstatus_t *vote = NULL;
@@ -341,18 +339,18 @@ test_router_pick_directory_server_impl(void *arg)
node_router1->rs->is_v2_dir = 0;
node_router3->rs->is_v2_dir = 0;
- tmp_dirport1 = node_router1->rs->dir_port;
- tmp_dirport3 = node_router3->rs->dir_port;
- node_router1->rs->dir_port = 0;
- node_router3->rs->dir_port = 0;
+ tmp_dirport1 = node_router1->rs->ipv4_dirport;
+ tmp_dirport3 = node_router3->rs->ipv4_dirport;
+ node_router1->rs->ipv4_dirport = 0;
+ node_router3->rs->ipv4_dirport = 0;
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_ptr_op(rs, OP_NE, NULL);
tt_assert(tor_memeq(rs->identity_digest, router2_id, DIGEST_LEN));
rs = NULL;
node_router1->rs->is_v2_dir = 1;
node_router3->rs->is_v2_dir = 1;
- node_router1->rs->dir_port = tmp_dirport1;
- node_router3->rs->dir_port = tmp_dirport3;
+ node_router1->rs->ipv4_dirport = tmp_dirport1;
+ node_router3->rs->ipv4_dirport = tmp_dirport3;
node_router1->is_valid = 0;
node_router3->is_valid = 0;
@@ -381,23 +379,23 @@ test_router_pick_directory_server_impl(void *arg)
options->ReachableORAddresses = policy_line;
policies_parse_from_options(options);
- node_router1->rs->or_port = 444;
- node_router2->rs->or_port = 443;
- node_router3->rs->or_port = 442;
+ node_router1->rs->ipv4_orport = 444;
+ node_router2->rs->ipv4_orport = 443;
+ node_router3->rs->ipv4_orport = 442;
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_ptr_op(rs, OP_NE, NULL);
tt_assert(tor_memeq(rs->identity_digest, router3_id, DIGEST_LEN));
- node_router1->rs->or_port = 442;
- node_router2->rs->or_port = 443;
- node_router3->rs->or_port = 444;
+ node_router1->rs->ipv4_orport = 442;
+ node_router2->rs->ipv4_orport = 443;
+ node_router3->rs->ipv4_orport = 444;
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_ptr_op(rs, OP_NE, NULL);
tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN));
/* Fascist firewall and overloaded */
- node_router1->rs->or_port = 442;
- node_router2->rs->or_port = 443;
- node_router3->rs->or_port = 442;
+ node_router1->rs->ipv4_orport = 442;
+ node_router2->rs->ipv4_orport = 443;
+ node_router3->rs->ipv4_orport = 442;
node_router3->rs->last_dir_503_at = now;
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_ptr_op(rs, OP_NE, NULL);
@@ -410,12 +408,12 @@ test_router_pick_directory_server_impl(void *arg)
policy_line->value = tor_strdup("accept *:80, reject *:*");
options->ReachableDirAddresses = policy_line;
policies_parse_from_options(options);
- node_router1->rs->or_port = 442;
- node_router2->rs->or_port = 441;
- node_router3->rs->or_port = 443;
- node_router1->rs->dir_port = 80;
- node_router2->rs->dir_port = 80;
- node_router3->rs->dir_port = 81;
+ node_router1->rs->ipv4_orport = 442;
+ node_router2->rs->ipv4_orport = 441;
+ node_router3->rs->ipv4_orport = 443;
+ node_router1->rs->ipv4_dirport = 80;
+ node_router2->rs->ipv4_dirport = 80;
+ node_router3->rs->ipv4_dirport = 81;
node_router1->rs->last_dir_503_at = now;
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_ptr_op(rs, OP_NE, NULL);
diff --git a/src/test/test_routerset.c b/src/test/test_routerset.c
index 892ac6e210..d00eefa23f 100644
--- a/src/test/test_routerset.c
+++ b/src/test/test_routerset.c
@@ -1417,12 +1417,62 @@ test_rset_contains_router(void *arg)
ri.nickname = (char *)nickname;
r = routerset_contains_router(set, &ri, country);
-
tt_int_op(r, OP_EQ, 4);
+
done:
routerset_free(set);
}
+static void
+test_rset_contains_router_ipv4(void *arg)
+{
+ routerset_t *set;
+ routerinfo_t ri;
+ country_t country = 1;
+ int r;
+ const char *s;
+ (void) arg;
+
+ /* IPv4 address test. */
+ memset(&ri, 0, sizeof(ri));
+ set = routerset_new();
+ s = "10.0.0.1";
+ r = routerset_parse(set, s, "");
+ tor_addr_from_ipv4h(&ri.ipv4_addr, 0x0a000001);
+ ri.ipv4_orport = 1234;
+
+ r = routerset_contains_router(set, &ri, country);
+ tt_int_op(r, OP_EQ, 3);
+
+ done:
+ routerset_free(set);
+}
+
+static void
+test_rset_contains_router_ipv6(void *arg)
+{
+ routerset_t *set;
+ routerinfo_t ri;
+ country_t country = 1;
+ int r;
+ const char *s;
+ (void) arg;
+
+ /* IPv6 address test. */
+ memset(&ri, 0, sizeof(ri));
+ set = routerset_new();
+ s = "2600::1";
+ r = routerset_parse(set, s, "");
+ tor_addr_parse(&ri.ipv6_addr, "2600::1");
+ ri.ipv6_orport = 12345;
+
+ r = routerset_contains_router(set, &ri, country);
+ tt_int_op(r, OP_EQ, 3);
+
+ done:
+ routerset_free(set);
+}
+
/*
* Functional test for routerset_contains_routerstatus.
*/
@@ -2144,6 +2194,10 @@ struct testcase_t routerset_tests[] = {
{ "contains_extendinfo", test_rset_contains_extendinfo,
TT_FORK, NULL, NULL },
{ "contains_router", test_rset_contains_router, TT_FORK, NULL, NULL },
+ { "contains_router_ipv4", test_rset_contains_router_ipv4,
+ TT_FORK, NULL, NULL },
+ { "contains_router_ipv6", test_rset_contains_router_ipv6,
+ TT_FORK, NULL, NULL },
{ "contains_routerstatus", test_rset_contains_routerstatus,
TT_FORK, NULL, NULL },
{ "contains_none", test_rset_contains_none, TT_FORK, NULL, NULL },
diff --git a/src/test/test_sendme.c b/src/test/test_sendme.c
index 2ff4809124..b34c7ae143 100644
--- a/src/test/test_sendme.c
+++ b/src/test/test_sendme.c
@@ -56,7 +56,7 @@ test_v1_record_digest(void *arg)
circ = TO_CIRCUIT(or_circ);
/* The package window has to be a multiple of CIRCWINDOW_INCREMENT minus 1
- * in order to catched the CIRCWINDOW_INCREMENT-nth cell. Try something that
+ * in order to catch the CIRCWINDOW_INCREMENT-nth cell. Try something that
* shouldn't be noted. */
circ->package_window = CIRCWINDOW_INCREMENT;
sendme_record_cell_digest_on_circ(circ, NULL);
diff --git a/src/test/test_shared_random.c b/src/test/test_shared_random.c
index 9e49e835c9..678f53234f 100644
--- a/src/test/test_shared_random.c
+++ b/src/test/test_shared_random.c
@@ -1414,7 +1414,7 @@ test_state_transition(void *arg)
sr_state_delete_commits();
tt_int_op(digestmap_size(state->commits), OP_EQ, 0);
/* Add it back so we can continue the rest of the test because after
- * deletiong our commit will be freed so generate a new one. */
+ * deleting our commit will be freed so generate a new one. */
commit = sr_generate_our_commit(now, mock_cert);
tt_assert(commit);
sr_state_add_commit(commit);
@@ -1555,7 +1555,7 @@ test_keep_commit(void *arg)
* in the state and commitment and reveal values match. */
tt_int_op(should_keep_commit(commit, commit->rsa_identity,
SR_PHASE_REVEAL), OP_EQ, 1);
- /* The commit shouldn't be kept if it's not verified that is no matchin
+ /* The commit shouldn't be kept if it's not verified that is no matching
* hashed reveal. */
{
/* Let's save the hash reveal so we can restore it. */
diff --git a/src/test/test_statefile.c b/src/test/test_statefile.c
new file mode 100644
index 0000000000..dc9ecfee3e
--- /dev/null
+++ b/src/test/test_statefile.c
@@ -0,0 +1,56 @@
+/* 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 */
+
+#include "orconfig.h"
+
+#define STATEFILE_PRIVATE
+
+#include "core/or/or.h"
+#include "lib/encoding/confline.h"
+#include "app/config/statefile.h"
+
+#include "test/test.h"
+
+static void
+test_statefile_remove_obsolete(void *arg)
+{
+ (void)arg;
+ config_line_t *inp = NULL;
+ /* try empty config */
+ or_state_remove_obsolete_lines(&inp);
+ tt_assert(!inp);
+
+ /* try removing every line */
+ config_line_append(&inp, "EntryGuard", "doesn't matter");
+ config_line_append(&inp, "HidServRevCounter", "ignore");
+ config_line_append(&inp, "hidservrevcounter", "foobar"); // note case
+ or_state_remove_obsolete_lines(&inp);
+ tt_assert(!inp);
+
+ /* Now try removing a subset of lines. */
+ config_line_append(&inp, "EntryGuard", "doesn't matter");
+ config_line_append(&inp, "Guard", "in use");
+ config_line_append(&inp, "HidServRevCounter", "ignore");
+ config_line_append(&inp, "TorVersion", "this test doesn't care");
+ or_state_remove_obsolete_lines(&inp);
+ tt_assert(inp);
+ tt_str_op(inp->key, OP_EQ, "Guard");
+ tt_str_op(inp->value, OP_EQ, "in use");
+ tt_assert(inp->next);
+ tt_str_op(inp->next->key, OP_EQ, "TorVersion");
+ tt_str_op(inp->next->value, OP_EQ, "this test doesn't care");
+ tt_assert(! inp->next->next);
+
+ done:
+ config_free_lines(inp);
+}
+
+#define T(name) \
+ { #name, test_statefile_##name, 0, NULL, NULL }
+
+struct testcase_t statefile_tests[] = {
+ T(remove_obsolete),
+ END_OF_TESTCASES
+};
diff --git a/src/test/test_stats.c b/src/test/test_stats.c
index 291473ebc9..d45afc7b15 100644
--- a/src/test/test_stats.c
+++ b/src/test/test_stats.c
@@ -30,6 +30,8 @@
#define CIRCUITLIST_PRIVATE
#define MAINLOOP_PRIVATE
#define STATEFILE_PRIVATE
+#define BWHIST_PRIVATE
+#define ROUTER_PRIVATE
#include "core/or/or.h"
#include "lib/err/backtrace.h"
@@ -39,8 +41,12 @@
#include "test/test.h"
#include "core/mainloop/mainloop.h"
#include "lib/memarea/memarea.h"
+#include "feature/stats/connstats.h"
#include "feature/stats/rephist.h"
#include "app/config/statefile.h"
+#include "feature/stats/bwhist.h"
+#include "feature/stats/bw_array_st.h"
+#include "feature/relay/router.h"
/** Run unit tests for some stats code. */
static void
@@ -111,37 +117,41 @@ test_stats(void *arg)
/* 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);
+ conn_stats_note_or_conn_bytes(1, 20, 400, now, false);
+ s = conn_stats_format(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);
+ conn_stats_init(now);
+ conn_stats_note_or_conn_bytes(1, 30000, 400000, now, false);
+ conn_stats_note_or_conn_bytes(1, 30000, 400000, now + 5, false);
+ conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 10, true);
+ conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 15, true);
+ s = conn_stats_format(now + 86400);
+ tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n"
+ "ipv6-conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,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);
+ conn_stats_terminate();
+ conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 15, true);
+ s = conn_stats_format(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);
+ conn_stats_init(now);
+ conn_stats_note_or_conn_bytes(1, 30000, 400000, now, false);
+ conn_stats_note_or_conn_bytes(1, 30000, 400000, now + 5, false);
+ conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 10, true);
+ conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 15, true);
+ conn_stats_reset(now);
+ s = conn_stats_format(now + 86400);
+ tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n"
+ "ipv6-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
@@ -245,6 +255,324 @@ test_rephist_mtbf(void *arg)
tor_free(ddir_fname);
}
+static void
+test_commit_max(void *arg)
+{
+ (void) arg;
+ bw_array_t *b = bw_array_new();
+ time_t now = b->cur_obs_time;
+
+ commit_max(b);
+ tt_int_op(b->next_period, OP_EQ, now + 2*86400);
+
+ b->total_in_period = 100;
+ b->max_total = 10;
+ commit_max(b);
+ tor_assert(b->total_in_period == 0);
+ tor_assert(b->max_total == 0);
+ tt_int_op(b->totals[1], OP_EQ, 100);
+ tt_int_op(b->maxima[1], OP_EQ, 10);
+ tt_int_op(b->next_period, OP_EQ, now + 3*86400);
+
+ commit_max(b);
+ tt_int_op(b->next_period, OP_EQ, now + 4*86400);
+
+ commit_max(b);
+ tt_int_op(b->next_period, OP_EQ, now + 5*86400);
+
+ b->total_in_period = 100;
+ b->max_total = 10;
+ commit_max(b);
+ tor_assert(!b->next_max_idx);
+ tt_int_op(b->cur_obs_idx, OP_EQ, 0);
+ tt_int_op(b->totals[4], OP_EQ, 100);
+ tt_int_op(b->maxima[4], OP_EQ, 10);
+ tt_int_op(b->next_period, OP_EQ, now + 6*86400);
+ done:
+ bw_array_free(b);
+}
+
+#define test_obs(b, idx, time, tot, max) STMT_BEGIN \
+ tt_int_op(b->cur_obs_idx, OP_EQ, idx); \
+ tt_int_op(b->cur_obs_time, OP_EQ, time); \
+ tt_int_op(b->total_obs, OP_EQ, tot); \
+ tt_int_op(b->max_total, OP_EQ, max); \
+ STMT_END;
+
+static void
+test_advance_obs(void *arg)
+{
+ (void) arg;
+ int iter, tot = 0;
+ bw_array_t *b = bw_array_new();
+ time_t now = b->cur_obs_time;
+
+ for (iter = 0; iter < 10; ++iter) {
+ b->obs[b->cur_obs_idx] += 10;
+ tot += 10;
+ advance_obs(b);
+ if (iter == 9) {
+ /* The current value under cur_obs_idx was zeroed in last iterN. */
+ test_obs(b, 0, now+iter+1, tot - 10, tot);
+ break;
+ }
+ test_obs(b, iter+1, now+iter+1, tot, tot);
+ }
+
+ b->total_in_period = 100;
+ b->cur_obs_time = now + NUM_SECS_BW_SUM_INTERVAL - 1;
+ advance_obs(b);
+ test_obs(b, 1, now+NUM_SECS_BW_SUM_INTERVAL, 80, 0);
+ tt_int_op(b->maxima[0], OP_EQ, 100);
+ tt_int_op(b->totals[0], OP_EQ, 100);
+ tt_int_op(b->num_maxes_set, OP_EQ, 1);
+ done:
+ bw_array_free(b);
+}
+
+#define test_add_obs_(b, now, checknow, bw, tot) STMT_BEGIN \
+ tot += bw; \
+ add_obs(b, now, bw); \
+ tt_int_op(b->cur_obs_time, OP_EQ, checknow); \
+ tt_int_op(b->obs[b->cur_obs_idx], OP_EQ, bw); \
+ tt_int_op(b->total_in_period, OP_EQ, tot); \
+ STMT_END;
+
+static void
+test_add_obs(void *arg)
+{
+ (void) arg;
+ bw_array_t *b = bw_array_new();
+ time_t now = b->cur_obs_time;
+ uint64_t bw = 0, tot = 0;
+ /* Requests for the past should not be entertained. */
+ test_add_obs_(b, now-1, now, bw, tot);
+ /* Test the expected functionalities for random values. */
+ now += 53;
+ bw = 97;
+ test_add_obs_(b, now, now, bw, tot);
+
+ now += 60*60;
+ bw = 90;
+ test_add_obs_(b, now, now, bw, tot);
+
+ now += 24*60*60;
+ bw = 100;
+ tot = 0;
+ test_add_obs_(b, now, now, bw, tot);
+ done:
+ bw_array_free(b);
+}
+
+static or_options_t mock_options;
+
+static const or_options_t *
+mock_get_options(void)
+{
+ return &mock_options;
+}
+
+#define MAX_HIST_VALUE_LEN 21*NUM_TOTALS
+
+#define set_test_case(b, max, idx, a1, a2, a3, a4, a5) STMT_BEGIN \
+ b->num_maxes_set = max; \
+ b->next_max_idx = idx; \
+ b->totals[0] = a1; \
+ b->totals[1] = a2; \
+ b->totals[2] = a3; \
+ b->totals[3] = a4; \
+ b->totals[4] = a5; \
+ STMT_END;
+
+#define test_fill_bw(b, buf, rv, str, checkrv) STMT_BEGIN \
+ buf = tor_malloc_zero(MAX_HIST_VALUE_LEN); \
+ rv = bwhist_fill_bandwidth_history(buf, MAX_HIST_VALUE_LEN, b); \
+ tt_str_op(buf, OP_EQ, str); \
+ tt_int_op(rv, OP_EQ, checkrv); \
+ tor_free(buf); \
+ STMT_END;
+
+static void
+test_fill_bandwidth_history(void *arg)
+{
+ (void) arg;
+ bw_array_t *b = bw_array_new();
+ char *buf;
+ size_t rv;
+ /* Remember bandwidth is rounded down to the nearest 1K. */
+ /* Day 1. */
+ set_test_case(b, 0, 0, 0, 0, 0, 0, 0);
+ buf = tor_malloc_zero(MAX_HIST_VALUE_LEN);
+ rv = bwhist_fill_bandwidth_history(buf, MAX_HIST_VALUE_LEN, b);
+ tt_int_op(rv, OP_EQ, 0);
+ tor_free(buf);
+ /* Day 2. */
+ set_test_case(b, 1, 1, 1000, 0, 0, 0, 0);
+ test_fill_bw(b, buf, rv, "0", 1);
+ /* Day 3. */
+ set_test_case(b, 2, 2, 1000, 1500, 0, 0, 0);
+ test_fill_bw(b, buf, rv, "0,1024", 6);
+ /* Day 4. */
+ set_test_case(b, 3, 3, 1000, 1500, 3500, 0, 0);
+ test_fill_bw(b, buf, rv, "0,1024,3072", 11);
+ /* Day 5. */
+ set_test_case(b, 4, 4, 1000, 1500, 3500, 8000, 0);
+ test_fill_bw(b, buf, rv, "0,1024,3072,7168", 16);
+ /* Day 6. */
+ set_test_case(b, 5, 0, 1000, 1500, 3500, 8000, 6000);
+ test_fill_bw(b, buf, rv, "0,1024,3072,7168,5120", 21);
+ /* Day 7. */
+ /* Remember oldest entry first. */
+ set_test_case(b, 5, 1, 10000, 1500, 3500, 8000, 6000);
+ test_fill_bw(b, buf, rv, "1024,3072,7168,5120,9216", 24);
+ /* Mocking get_options to manipulate RelayBandwidthRate. */
+ MOCK(get_options, mock_get_options);
+ /* Limits bandwidth to 1 KBps. */
+ /* Cutoff is set to 88473600. */
+ mock_options.RelayBandwidthRate = 1024;
+ set_test_case(b, 5, 2, 88573600, 88473600, 10000, 8000, 6000);
+ test_fill_bw(b, buf, rv, "9216,7168,5120,88473600,88473600", 32);
+ done:
+ UNMOCK(get_options);
+ bw_array_free(b);
+}
+
+#define set_test_bw_lines(r, w, dr, dw, when) STMT_BEGIN \
+ bwhist_note_bytes_read(r, when, false); \
+ bwhist_note_bytes_written(w, when, false); \
+ bwhist_note_dir_bytes_read(dr, when); \
+ bwhist_note_dir_bytes_written(dw, when); \
+ STMT_END;
+
+#define test_get_bw_lines(str, checkstr) STMT_BEGIN \
+ str = bwhist_get_bandwidth_lines(); \
+ tt_str_op(str, OP_EQ, checkstr); \
+ tor_free(str); \
+ STMT_END;
+
+static void
+test_get_bandwidth_lines(void *arg)
+{
+ (void) arg;
+ char *str = NULL, *checkstr = NULL;
+ char t[ISO_TIME_LEN+1];
+ int len = (67+MAX_HIST_VALUE_LEN)*4;
+ checkstr = tor_malloc_zero(len);
+ time_t now = time(NULL);
+ bwhist_init();
+
+ /* Day 1. */
+ now += 86400;
+ set_test_bw_lines(5000, 5500, 3000, 3500, now - 6*60*60);
+ /* Day 2. */
+ now += 86400;
+ set_test_bw_lines(50000, 55000, 30000, 35000, now - 6*60*60);
+ /* Day 3. */
+ now += 86400;
+ set_test_bw_lines(25000, 27500, 15000, 17500, now - 6*60*60);
+ /* Day 4. */
+ now += 86400;
+ set_test_bw_lines(90000, 76000, 60000, 45000, now - 6*60*60);
+ /* Day 5. */
+ now += 86400;
+ set_test_bw_lines(500, 55000, 30000, 35000, now - 6*60*60);
+ set_test_bw_lines(0, 0, 0, 0, now);
+ format_iso_time(t, now);
+ tor_snprintf(checkstr, len, "write-history %s (86400 s) "
+ "5120,54272,26624,75776,54272\n"
+ "read-history %s (86400 s) "
+ "4096,49152,24576,89088,0\n"
+ "dirreq-write-history %s (86400 s) "
+ "3072,34816,17408,44032,34816\n"
+ "dirreq-read-history %s (86400 s) "
+ "2048,29696,14336,59392,29696\n",
+ t, t, t, t);
+ test_get_bw_lines(str, checkstr);
+
+ done:
+ tor_free(str);
+ tor_free(checkstr);
+ bwhist_free_all();
+}
+
+static void
+test_load_stats_file(void *arg)
+{
+ int ret;
+ char *content = NULL, *read_file_content = NULL, *fname = NULL;
+
+ (void) arg;
+
+ /* Load conn-stats. */
+ fname = get_datadir_fname("conn-stats");
+ tt_assert(fname);
+ read_file_content = tor_strdup(
+ "conn-bi-direct 2020-12-13 15:48:53 (86400 s) 12,34,56,78\n"
+ "ipv6-conn-bi-direct 2020-12-14 15:48:53 (86400 s) 21,43,65,87\n");
+ write_str_to_file(fname, read_file_content, 0);
+ ret = load_stats_file("conn-stats", "conn-bi-direct", 1607874000, &content);
+ tt_int_op(ret, OP_EQ, 1);
+ tt_str_op(read_file_content, OP_EQ, content);
+
+ /* Load hidserv-stats. */
+ tor_free(fname);
+ fname = get_datadir_fname("hidserv-stats");
+ tt_assert(fname);
+ tor_free(read_file_content);
+ read_file_content = tor_strdup(
+ "hidserv-stats-end 2020-12-13 15:48:53 (86400 s)\n"
+ "hidserv-rend-relayed-cells 48754891 delta_f=2048 epsilon=0.30 "
+ "bin_size=1024\n"
+ "hidserv-dir-onions-seen 53 delta_f=8 epsilon=0.30 bin_size=8\n");
+ write_str_to_file(fname, read_file_content, 0);
+ tor_free(content);
+ ret = load_stats_file("hidserv-stats", "hidserv-stats-end", 1607874000,
+ &content);
+ tt_int_op(ret, OP_EQ, 1);
+ tt_str_op(read_file_content, OP_EQ, content);
+
+ /* Load dirreq-stats. */
+ tor_free(fname);
+ fname = get_datadir_fname("dirreq-stats");
+ tt_assert(fname);
+ tor_free(read_file_content);
+ read_file_content = tor_strdup(
+ "dirreq-stats-end 2020-12-13 15:48:53 (86400 s)\n"
+ "dirreq-v3-ips ru=1728,us=1144,de=696,ir=432,gb=328,fr=304,in=296,ua=232\n"
+ "dirreq-v3-reqs ru=3616,us=3576,de=1896,fr=800,gb=632,ir=616\n"
+ "dirreq-v3-resp ok=18472,not-enough-sigs=0,unavailable=0,not-found=0,"
+ "not-modified=3136,busy=0\n"
+ "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v3-tunneled-dl complete=18124,timeout=348,running=4,min=257,"
+ "d1=133653,d2=221050,q1=261242,d3=300622,d4=399758,md=539051,d6=721322,"
+ "d7=959866,q3=1103363,d8=1302035,d9=2046125,max=113404000\n");
+ write_str_to_file(fname, read_file_content, 0);
+ tor_free(content);
+ ret = load_stats_file("dirreq-stats", "dirreq-stats-end", 1607874000,
+ &content);
+ tt_int_op(ret, OP_EQ, 1);
+ tt_str_op(read_file_content, OP_EQ, content);
+
+ /* Attempt to load future-stats file not starting with timestamp tag. */
+ tor_free(fname);
+ fname = get_datadir_fname("future-stats");
+ tt_assert(fname);
+ tor_free(read_file_content);
+ read_file_content = tor_strdup(
+ "future-stuff-at-file-start\n"
+ "future-stats 2020-12-13 15:48:53 (86400 s)\n");
+ write_str_to_file(fname, read_file_content, 0);
+ tor_free(content);
+ ret = load_stats_file("future-stats", "future-stats", 1607874000, &content);
+ tt_int_op(ret, OP_EQ, 1);
+ tt_str_op(read_file_content, OP_EQ, content);
+
+ done:
+ tor_free(fname);
+ tor_free(read_file_content);
+ tor_free(content);
+}
+
#define ENT(name) \
{ #name, test_ ## name , 0, NULL, NULL }
#define FORK(name) \
@@ -253,6 +581,12 @@ test_rephist_mtbf(void *arg)
struct testcase_t stats_tests[] = {
FORK(stats),
ENT(rephist_mtbf),
+ FORK(commit_max),
+ FORK(advance_obs),
+ FORK(add_obs),
+ FORK(fill_bandwidth_history),
+ FORK(get_bandwidth_lines),
+ FORK(load_stats_file),
END_OF_TESTCASES
};
diff --git a/src/test/test_status.c b/src/test/test_status.c
index 82afe0fd2a..b938b86326 100644
--- a/src/test/test_status.c
+++ b/src/test/test_status.c
@@ -26,6 +26,7 @@
#include "feature/nodelist/nodelist.h"
#include "app/config/statefile.h"
#include "lib/tls/tortls.h"
+#include "test/log_test_helpers.h"
#include "core/or/origin_circuit_st.h"
#include "app/config/or_state_st.h"
@@ -308,10 +309,6 @@ static int status_hb_not_in_consensus_public_server_mode(
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;
@@ -332,8 +329,6 @@ test_status_hb_not_in_consensus(void *arg)
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);
@@ -344,18 +339,38 @@ test_status_hb_not_in_consensus(void *arg)
onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR] = 1;
expected = 0;
+ setup_capture_of_logs(LOG_INFO);
actual = log_heartbeat(0);
-
tt_int_op(actual, OP_EQ, expected);
- tt_int_op(status_hb_not_in_consensus_logv_called, OP_EQ, 6);
- done:
+ expect_log_msg("Heartbeat: It seems like we are "
+ "not in the cached consensus.\n");
+ expect_log_msg("Heartbeat: Tor's uptime is 0:00 hours, "
+ "with 0 circuits open. "
+ "I've sent 0 kB and received 0 kB. "
+ "I've received 0 connections on IPv4 and 0 on IPv6. "
+ "I've made 0 connections with IPv4 and 0 with IPv6.\n");
+ expect_log_msg("Average packaged cell fullness: 100.000%. "
+ "TLS write overhead: 0%\n");
+ expect_log_msg("Circuit handshake stats since last time: 1/1 TAP, "
+ "1/1 NTor.\n");
+ expect_log_msg("Since startup we initiated 0 and received 0 v1 "
+ "connections; initiated 0 and received 0 v2 connections; "
+ "initiated 0 and received 0 v3 connections; "
+ "initiated 0 and received 0 v4 connections; "
+ "initiated 0 and received 0 v5 connections.\n");
+ expect_log_msg("DoS mitigation since startup: 0 circuits killed with "
+ "too many cells. [cc not enabled] [conn not enabled] "
+ "0 INTRODUCE2 rejected.\n");
+ tt_int_op(mock_saved_log_n_entries(), OP_EQ, 6);
+
+ done:
+ teardown_capture_of_logs();
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);
}
@@ -396,76 +411,6 @@ status_hb_not_in_consensus_node_get_by_id(const char *identity_digest)
return NULL;
}
-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)
-{
- switch (status_hb_not_in_consensus_logv_called)
- {
- case 0:
- tt_int_op(severity, OP_EQ, LOG_NOTICE);
- tt_u64_op(domain, OP_EQ, LD_HEARTBEAT);
- tt_ptr_op(strstr(funcname, "log_heartbeat"), OP_NE, NULL);
- tt_ptr_op(suffix, OP_EQ, NULL);
- tt_str_op(format, OP_EQ,
- "Heartbeat: It seems like we are not in the cached consensus.");
- break;
- case 1:
- tt_int_op(severity, OP_EQ, LOG_NOTICE);
- tt_u64_op(domain, OP_EQ, LD_HEARTBEAT);
- tt_ptr_op(strstr(funcname, "log_heartbeat"), OP_NE, NULL);
- tt_ptr_op(suffix, OP_EQ, NULL);
- tt_str_op(format, OP_EQ,
- "Heartbeat: Tor's uptime is %s, with %d circuits open. "
- "I've sent %s and received %s.%s");
- tt_str_op(va_arg(ap, char *), OP_EQ, "0:00 hours"); /* uptime */
- tt_int_op(va_arg(ap, int), OP_EQ, 0); /* count_circuits() */
- tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB"); /* bw_sent */
- tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB"); /* bw_rcvd */
- tt_str_op(va_arg(ap, char *), OP_EQ, ""); /* hibernating */
- break;
- case 2:
- tt_int_op(severity, OP_EQ, LOG_INFO);
- break;
- case 3:
- tt_int_op(severity, OP_EQ, LOG_NOTICE);
- tt_u64_op(domain, OP_EQ, LD_HEARTBEAT);
- tt_ptr_op(strstr(funcname, "rep_hist_log_circuit_handshake_stats"),
- OP_NE, NULL);
- tt_ptr_op(suffix, OP_EQ, NULL);
- tt_str_op(format, OP_EQ,
- "Circuit handshake stats since last time: %d/%d TAP, %d/%d NTor.");
- tt_int_op(va_arg(ap, int), OP_EQ, 1); /* handshakes assigned (TAP) */
- tt_int_op(va_arg(ap, int), OP_EQ, 1); /* handshakes requested (TAP) */
- tt_int_op(va_arg(ap, int), OP_EQ, 1); /* handshakes assigned (NTOR) */
- tt_int_op(va_arg(ap, int), OP_EQ, 1); /* handshakes requested (NTOR) */
- break;
- case 4:
- tt_int_op(severity, OP_EQ, LOG_NOTICE);
- tt_u64_op(domain, OP_EQ, LD_HEARTBEAT);
- tt_ptr_op(strstr(funcname, "rep_hist_log_link_protocol_counts"),
- OP_NE, NULL);
- break;
- 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%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
- break;
- }
-
- done:
- status_hb_not_in_consensus_logv_called++;
-}
-
static int
status_hb_not_in_consensus_server_mode(const or_options_t *options)
{
@@ -485,14 +430,8 @@ 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 status_hb_simple_n_msgs = 0;
-
static void
test_status_hb_simple(void *arg)
{
@@ -511,27 +450,32 @@ test_status_hb_simple(void *arg)
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;
+ setup_capture_of_logs(LOG_INFO);
expected = 0;
actual = log_heartbeat(0);
tt_int_op(actual, OP_EQ, expected);
- tt_int_op(status_hb_simple_n_msgs, OP_EQ, 1);
+
+ expect_log_msg("Heartbeat: Tor's uptime is 0:00 hours, "
+ "with 0 circuits open. "
+ "I've sent 0 kB and received 0 kB. "
+ "I've received 0 connections on IPv4 and 0 on IPv6. "
+ "I've made 0 connections with IPv4 and 0 with IPv6. "
+ "We are currently hibernating.\n");
done:
+ teardown_capture_of_logs();
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);
}
@@ -573,32 +517,6 @@ status_hb_simple_get_bytes_written(void)
return 0;
}
-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)
-{
- if (severity == LOG_INFO)
- return;
- ++status_hb_simple_n_msgs;
-
- tt_int_op(severity, OP_EQ, LOG_NOTICE);
- tt_u64_op(domain, OP_EQ, LD_HEARTBEAT);
- tt_ptr_op(strstr(funcname, "log_heartbeat"), OP_NE, NULL);
- tt_ptr_op(suffix, OP_EQ, NULL);
- tt_str_op(format, OP_EQ,
- "Heartbeat: Tor's uptime is %s, with %d circuits open. "
- "I've sent %s and received %s.%s");
- tt_str_op(va_arg(ap, char *), OP_EQ, "0:00 hours"); /* uptime */
- tt_int_op(va_arg(ap, int), OP_EQ, 0); /* count_circuits() */
- tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB"); /* bw_sent */
- tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB"); /* bw_rcvd */
- tt_str_op(va_arg(ap, char *), OP_EQ, " We are currently hibernating.");
-
- done:
- ;
-}
-
static int
status_hb_simple_server_mode(const or_options_t *options)
{
@@ -620,11 +538,6 @@ static int status_hb_calls_log_accounting_public_server_mode(
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);
@@ -653,8 +566,6 @@ test_status_hb_calls_log_accounting(void *arg)
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,
@@ -666,20 +577,31 @@ test_status_hb_calls_log_accounting(void *arg)
log_global_min_severity_ = LOG_DEBUG;
+ setup_capture_of_logs(LOG_NOTICE);
expected = 0;
actual = log_heartbeat(0);
tt_int_op(actual, OP_EQ, expected);
- tt_int_op(status_hb_calls_log_accounting_logv_called, OP_EQ, 3);
+
+ expect_log_msg("Heartbeat: Tor's uptime is 0:00 hours, "
+ "with 0 circuits open. "
+ "I've sent 0 kB and received 0 kB. "
+ "I've received 0 connections on IPv4 and 0 on IPv6. "
+ "I've made 0 connections with IPv4 and 0 with IPv6.\n");
+
+ expect_log_msg_containing("Heartbeat: Accounting enabled. Sent: 0 kB, "
+ "Received: 0 kB, Used: 0 kB / 0 kB, Rule: max. "
+ "The current accounting interval ends on ");
+ tt_int_op(mock_saved_log_n_entries(), OP_EQ, 2);
done:
+ teardown_capture_of_logs();
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);
@@ -725,58 +647,6 @@ status_hb_calls_log_accounting_get_bytes_written(void)
return 0;
}
-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)
-{
- switch (status_hb_calls_log_accounting_logv_called)
- {
- case 0:
- tt_int_op(severity, OP_EQ, LOG_NOTICE);
- tt_u64_op(domain, OP_EQ, LD_HEARTBEAT);
- tt_ptr_op(strstr(funcname, "log_heartbeat"), OP_NE, NULL);
- tt_ptr_op(suffix, OP_EQ, NULL);
- tt_str_op(format, OP_EQ,
- "Heartbeat: Tor's uptime is %s, with %d circuits open. "
- "I've sent %s and received %s.%s");
- tt_str_op(va_arg(ap, char *), OP_EQ, "0:00 hours"); /* uptime */
- tt_int_op(va_arg(ap, int), OP_EQ, 0); /* count_circuits() */
- tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB"); /* bw_sent */
- tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB"); /* bw_rcvd */
- tt_str_op(va_arg(ap, char *), OP_EQ, ""); /* hibernating */
- break;
- case 1:
- tt_int_op(severity, OP_EQ, LOG_NOTICE);
- tt_u64_op(domain, OP_EQ, LD_HEARTBEAT);
- tt_ptr_op(strstr(funcname, "log_accounting"), OP_NE, NULL);
- tt_ptr_op(suffix, OP_EQ, NULL);
- tt_str_op(format, OP_EQ,
- "Heartbeat: Accounting enabled. Sent: %s, Received: %s, Used: %s / "
- "%s, Rule: %s. The current accounting interval ends on %s, in %s.");
- tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB"); /* acc_sent */
- tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB"); /* acc_rcvd */
- tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB"); /* acc_used */
- tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB"); /* acc_max */
- tt_str_op(va_arg(ap, char *), OP_EQ, "max"); /* acc_rule */
- /* format_local_iso_time uses local tz, so we can't just compare
- * the string against a constant */
- char datetime[ISO_TIME_LEN+1];
- format_local_iso_time(datetime, 60);
- tt_str_op(va_arg(ap, char *), OP_EQ, datetime); /* end_buf */
- tt_str_op(va_arg(ap, char *), OP_EQ, "0:01 hours"); /* remaining */
- break;
- case 2:
- tt_int_op(severity, OP_EQ, LOG_INFO);
- break;
- default:
- tt_abort_msg("unexpected call to logv()"); // TODO: prettyprint args
- break;
- }
-
- done:
- status_hb_calls_log_accounting_logv_called++;
-}
-
static int
status_hb_calls_log_accounting_server_mode(const or_options_t *options)
{
@@ -826,11 +696,6 @@ static int status_hb_packaged_cell_fullness_public_server_mode(
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(
@@ -854,8 +719,6 @@ test_status_hb_packaged_cell_fullness(void *arg)
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,
@@ -865,12 +728,20 @@ test_status_hb_packaged_cell_fullness(void *arg)
stats_n_data_bytes_packaged = RELAY_PAYLOAD_SIZE;
stats_n_data_cells_packaged = 2;
expected = 0;
+ setup_capture_of_logs(LOG_INFO);
actual = log_heartbeat(0);
tt_int_op(actual, OP_EQ, expected);
- tt_int_op(status_hb_packaged_cell_fullness_logv_called, OP_EQ, 2);
+ expect_log_msg("Heartbeat: Tor's uptime is 0:00 hours, "
+ "with 0 circuits open. "
+ "I've sent 0 kB and received 0 kB. "
+ "I've received 0 connections on IPv4 and 0 on IPv6. "
+ "I've made 0 connections with IPv4 and 0 with IPv6.\n");
+ expect_log_msg("Average packaged cell fullness: 50.000%. "
+ "TLS write overhead: 0%\n");
done:
+ teardown_capture_of_logs();
stats_n_data_bytes_packaged = 0;
stats_n_data_cells_packaged = 0;
UNMOCK(tls_get_write_overhead_ratio);
@@ -879,7 +750,6 @@ test_status_hb_packaged_cell_fullness(void *arg)
UNMOCK(get_uptime);
UNMOCK(get_bytes_read);
UNMOCK(get_bytes_written);
- UNMOCK(logv);
UNMOCK(server_mode);
UNMOCK(accounting_is_enabled);
}
@@ -923,47 +793,6 @@ status_hb_packaged_cell_fullness_get_bytes_written(void)
return 0;
}
-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)
-{
- switch (status_hb_packaged_cell_fullness_logv_called)
- {
- case 0:
- tt_int_op(severity, OP_EQ, LOG_NOTICE);
- tt_u64_op(domain, OP_EQ, LD_HEARTBEAT);
- tt_ptr_op(strstr(funcname, "log_heartbeat"), OP_NE, NULL);
- tt_ptr_op(suffix, OP_EQ, NULL);
- tt_str_op(format, OP_EQ,
- "Heartbeat: Tor's uptime is %s, with %d circuits open. "
- "I've sent %s and received %s.%s");
- tt_str_op(va_arg(ap, char *), OP_EQ, "0:00 hours"); /* uptime */
- tt_int_op(va_arg(ap, int), OP_EQ, 0); /* count_circuits() */
- tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB"); /* bw_sent */
- tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB"); /* bw_rcvd */
- tt_str_op(va_arg(ap, char *), OP_EQ, ""); /* hibernating */
- break;
- case 1:
- tt_int_op(severity, OP_EQ, LOG_NOTICE);
- tt_u64_op(domain, OP_EQ, LD_HEARTBEAT);
- tt_ptr_op(strstr(funcname, "log_heartbeat"), OP_NE, NULL);
- tt_ptr_op(suffix, OP_EQ, NULL);
- tt_str_op(format, OP_EQ,
- "Average packaged cell fullness: %2.3f%%. "
- "TLS write overhead: %.f%%");
- tt_double_op(fabs(va_arg(ap, double) - 50.0), OP_LE, DBL_EPSILON);
- tt_double_op(fabs(va_arg(ap, double) - 0.0), OP_LE, DBL_EPSILON);
- break;
- default:
- tt_abort_msg("unexpected call to logv()"); // TODO: prettyprint args
- break;
- }
-
- done:
- status_hb_packaged_cell_fullness_logv_called++;
-}
-
static int
status_hb_packaged_cell_fullness_server_mode(const or_options_t *options)
{
@@ -993,11 +822,6 @@ static int status_hb_tls_write_overhead_public_server_mode(
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(
@@ -1021,8 +845,6 @@ test_status_hb_tls_write_overhead(void *arg)
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,
@@ -1031,19 +853,26 @@ test_status_hb_tls_write_overhead(void *arg)
log_global_min_severity_ = LOG_DEBUG;
expected = 0;
+ setup_capture_of_logs(LOG_NOTICE);
actual = log_heartbeat(0);
tt_int_op(actual, OP_EQ, expected);
- tt_int_op(status_hb_tls_write_overhead_logv_called, OP_EQ, 2);
+ expect_log_msg("Heartbeat: Tor's uptime is 0:00 hours, "
+ "with 0 circuits open. "
+ "I've sent 0 kB and received 0 kB. "
+ "I've received 0 connections on IPv4 and 0 on IPv6. "
+ "I've made 0 connections with IPv4 and 0 with IPv6.\n");
+ expect_log_msg("Average packaged cell fullness: 100.000%. "
+ "TLS write overhead: 100%\n");
done:
+ teardown_capture_of_logs();
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);
}
@@ -1086,46 +915,6 @@ status_hb_tls_write_overhead_get_bytes_written(void)
return 0;
}
-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)
-{
- switch (status_hb_tls_write_overhead_logv_called)
- {
- case 0:
- tt_int_op(severity, OP_EQ, LOG_NOTICE);
- tt_u64_op(domain, OP_EQ, LD_HEARTBEAT);
- tt_ptr_op(strstr(funcname, "log_heartbeat"), OP_NE, NULL);
- tt_ptr_op(suffix, OP_EQ, NULL);
- tt_str_op(format, OP_EQ,
- "Heartbeat: Tor's uptime is %s, with %d circuits open. "
- "I've sent %s and received %s.%s");
- tt_str_op(va_arg(ap, char *), OP_EQ, "0:00 hours"); /* uptime */
- tt_int_op(va_arg(ap, int), OP_EQ, 0); /* count_circuits() */
- tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB"); /* bw_sent */
- tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB"); /* bw_rcvd */
- tt_str_op(va_arg(ap, char *), OP_EQ, ""); /* hibernating */
- break;
- case 1:
- tt_int_op(severity, OP_EQ, LOG_NOTICE);
- tt_u64_op(domain, OP_EQ, LD_HEARTBEAT);
- tt_ptr_op(strstr(funcname, "log_heartbeat"), OP_NE, NULL);
- tt_ptr_op(suffix, OP_EQ, NULL);
- tt_str_op(format, OP_EQ,
- "Average packaged cell fullness: %2.3f%%. "
- "TLS write overhead: %.f%%");
- tt_int_op(fabs(va_arg(ap, double) - 100.0) <= DBL_EPSILON, OP_EQ, 1);
- tt_double_op(fabs(va_arg(ap, double) - 100.0), OP_LE, DBL_EPSILON);
- break;
- default:
- tt_abort_msg("unexpected call to logv()"); // TODO: prettyprint args
- break;
- }
-
- done:
- status_hb_tls_write_overhead_logv_called++;
-}
-
static int
status_hb_tls_write_overhead_server_mode(const or_options_t *options)
{
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 00626c7ec0..d43bf781f2 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -18,6 +18,7 @@
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/defs/time.h"
#include "test/test.h"
+#include "test/test_helpers.h"
#include "lib/memarea/memarea.h"
#include "lib/process/waitpid.h"
#include "lib/process/process_win32.h"
@@ -77,6 +78,8 @@
#define DISABLE_PWDB_TESTS
#endif
+static void set_file_mtime(const char *fname, time_t when);
+
#define INFINITY_DBL ((double)INFINITY)
#define NAN_DBL ((double)NAN)
@@ -355,6 +358,55 @@ test_util_write_chunks_to_file(void *arg)
tor_free(temp_str);
}
+/* Test write_str_to_file_if_not_equal(). */
+static void
+test_util_write_str_if_changed(void *arg)
+{
+ (void)arg;
+ char *fname = tor_strdup(get_fname("write_if_changed"));
+ char *s = NULL;
+ int rv;
+ const char str1[] = "The wombat lives across the seas";
+ const char str2[] = "Among the far Antipodes"; /* -- Ogden Nash */
+
+ /* We can create files. */
+ rv = write_str_to_file_if_not_equal(fname, str1);
+ tt_int_op(rv, OP_EQ, 0);
+ s = read_file_to_str(fname, 0, NULL);
+ tt_str_op(s, OP_EQ, str1);
+ tor_free(s);
+
+ /* We can replace files. */
+ rv = write_str_to_file_if_not_equal(fname, str2);
+ tt_int_op(rv, OP_EQ, 0);
+ s = read_file_to_str(fname, 0, NULL);
+ tt_str_op(s, OP_EQ, str2);
+ tor_free(s);
+
+ /* Make sure we don't replace files when they're equal. (That's the whole
+ * point of the function we're testing. */
+ /* First, change the mtime of the file so that we can tell whether we
+ * replaced it. */
+ const time_t now = time(NULL);
+ const time_t five_sec_ago = now - 5;
+ set_file_mtime(fname, five_sec_ago);
+ rv = write_str_to_file_if_not_equal(fname, str2);
+ tt_int_op(rv, OP_EQ, 0);
+ /* Make sure that the file's mtime is unchanged... */
+ struct stat st;
+ rv = stat(fname, &st);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_i64_op(st.st_mtime, OP_EQ, five_sec_ago);
+ /* And make sure its contents are unchanged. */
+ s = read_file_to_str(fname, 0, NULL);
+ tt_str_op(s, OP_EQ, str2);
+ tor_free(s);
+
+ done:
+ tor_free(fname);
+ tor_free(s);
+}
+
#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
@@ -4133,6 +4185,31 @@ test_util_find_str_at_start_of_line(void *ptr)
}
static void
+test_util_tor_strreplacechar(void *ptr)
+{
+ (void)ptr;
+ char empty[] = "";
+ char not_contain[] = "bbb";
+ char contains[] = "bab";
+ char contains_all[] = "aaa";
+
+ tor_strreplacechar(empty, 'a', 'b');
+ tt_str_op(empty, OP_EQ, "");
+
+ tor_strreplacechar(not_contain, 'a', 'b');
+ tt_str_op(not_contain, OP_EQ, "bbb");
+
+ tor_strreplacechar(contains, 'a', 'b');
+ tt_str_op(contains, OP_EQ, "bbb");
+
+ tor_strreplacechar(contains_all, 'a', 'b');
+ tt_str_op(contains_all, OP_EQ, "bbb");
+
+ done:
+ ;
+}
+
+static void
test_util_string_is_C_identifier(void *ptr)
{
(void)ptr;
@@ -4359,6 +4436,438 @@ test_util_listdir(void *ptr)
}
static void
+test_util_glob(void *ptr)
+{
+ (void)ptr;
+
+#ifdef HAVE_GLOB
+ smartlist_t *results = NULL;
+ int r, i;
+ char *dir1 = NULL, *dir2 = NULL, *forbidden = NULL, *dirname = NULL;
+ char *expected = NULL, *pattern = NULL;
+ // used for cleanup
+ char *dir1_forbidden = NULL, *dir2_forbidden = NULL;
+ char *forbidden_forbidden = NULL;
+
+ dirname = tor_strdup(get_fname("test_glob"));
+ tt_ptr_op(dirname, OP_NE, NULL);
+
+#ifdef _WIN32
+ r = mkdir(dirname);
+#else
+ r = mkdir(dirname, 0700);
+#endif
+ if (r) {
+ fprintf(stderr, "Can't create directory %s:", dirname);
+ perror("");
+ exit(1);
+ }
+
+ tt_int_op(0, OP_EQ, create_test_directory_structure(dirname));
+ tor_asprintf(&dir1, "%s"PATH_SEPARATOR"dir1", dirname);
+ tor_asprintf(&dir1_forbidden,
+ "%s"PATH_SEPARATOR"dir1"PATH_SEPARATOR"forbidden", dirname);
+ tt_int_op(0, OP_EQ, create_test_directory_structure(dir1));
+ tor_asprintf(&dir2, "%s"PATH_SEPARATOR"dir2", dirname);
+ tor_asprintf(&dir2_forbidden,
+ "%s"PATH_SEPARATOR"dir2"PATH_SEPARATOR"forbidden", dirname);
+ tt_int_op(0, OP_EQ, create_test_directory_structure(dir2));
+ tor_asprintf(&forbidden, "%s"PATH_SEPARATOR"forbidden", dirname);
+ tor_asprintf(&forbidden_forbidden,
+ "%s"PATH_SEPARATOR"forbidden"PATH_SEPARATOR"forbidden",dirname);
+#ifndef _WIN32
+ tt_int_op(0, OP_EQ, chmod(forbidden, 0700));
+#endif
+ tt_int_op(0, OP_EQ, create_test_directory_structure(forbidden));
+#ifndef _WIN32
+ tt_int_op(0, OP_EQ, chmod(forbidden, 0));
+#endif
+
+#define TEST(input) \
+ do { \
+ tor_asprintf(&pattern, "%s"PATH_SEPARATOR"%s", dirname, input); \
+ results = tor_glob(pattern); \
+ tor_free(pattern); \
+ tt_assert(results); \
+ smartlist_sort_strings(results); \
+ } while (0);
+
+#define EXPECT(result) \
+ do { \
+ tt_int_op(smartlist_len(results), OP_EQ, \
+ sizeof(result)/sizeof(*result)); \
+ i = 0; \
+ SMARTLIST_FOREACH_BEGIN(results, const char *, f) { \
+ tor_asprintf(&expected, "%s"PATH_SEPARATOR"%s", dirname, result[i]); \
+ tt_str_op(f, OP_EQ, expected); \
+ i++; \
+ tor_free(expected); \
+ } SMARTLIST_FOREACH_END(f); \
+ SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \
+ smartlist_free(results); \
+ } while (0);
+
+#define EXPECT_EMPTY() \
+ do { \
+ tt_int_op(smartlist_len(results), OP_EQ, 0); \
+ SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \
+ smartlist_free(results); \
+ } while (0);
+
+ // wildcards at beginning
+ const char *results_test1[] = {"dir2", "file2"};
+ TEST("*2");
+ EXPECT(results_test1);
+
+ // wildcards at end
+ const char *results_test2[] = {"dir1", "dir2"};
+ TEST("d*");
+ EXPECT(results_test2);
+
+ // wildcards at beginning and end
+#ifdef _WIN32
+ // dot files are not ignored on Windows
+ const char *results_test3[] = {".test-hidden", "dir1", "dir2", "file1",
+ "file2", "forbidden"};
+#else
+ const char *results_test3[] = {"dir1", "dir2", "file1", "file2",
+ "forbidden"};
+#endif
+ TEST("*i*");
+ EXPECT(results_test3);
+
+ // wildcards in middle
+ const char *results_test4[] = {"dir1", "dir2"};
+ TEST("d?r*");
+ EXPECT(results_test4);
+
+ // test file that does not exist
+ TEST("not-exist");
+ EXPECT_EMPTY();
+
+ // test wildcard that matches nothing
+ TEST("*not-exist*");
+ EXPECT_EMPTY();
+
+ // test path separator at end - no wildcards
+ const char *results_test7[] = {"dir1"};
+ TEST("dir1");
+ EXPECT(results_test7);
+
+ const char *results_test8[] = {"dir1"};
+ TEST("dir1"PATH_SEPARATOR);
+ EXPECT(results_test8);
+
+ const char *results_test9[] = {"file1"};
+ TEST("file1");
+ EXPECT(results_test9);
+
+#if defined(__APPLE__) || defined(__darwin__) || \
+ defined(__FreeBSD__) || defined(__NetBSD__) || defined(OpenBSD)
+ TEST("file1"PATH_SEPARATOR);
+ EXPECT_EMPTY();
+#else
+ const char *results_test10[] = {"file1"};
+ TEST("file1"PATH_SEPARATOR);
+ EXPECT(results_test10);
+#endif
+
+ // test path separator at end - with wildcards and linux path separator
+ const char *results_test11[] = {"dir1", "dir2", "forbidden"};
+ TEST("*/");
+ EXPECT(results_test11);
+
+#ifdef _WIN32
+ // dot files are not ignored on Windows
+ const char *results_test12[] = {".test-hidden", "dir1", "dir2", "empty",
+ "file1", "file2", "forbidden"};
+#else
+ const char *results_test12[] = {"dir1", "dir2", "empty", "file1", "file2",
+ "forbidden"};
+#endif
+ TEST("*");
+ EXPECT(results_test12);
+
+ // wildcards on folder and file and linux path separator
+ const char *results_test13[] = {"dir1"PATH_SEPARATOR"dir1",
+ "dir1"PATH_SEPARATOR"dir2",
+ "dir1"PATH_SEPARATOR"file1",
+ "dir1"PATH_SEPARATOR"file2",
+ "dir2"PATH_SEPARATOR"dir1",
+ "dir2"PATH_SEPARATOR"dir2",
+ "dir2"PATH_SEPARATOR"file1",
+ "dir2"PATH_SEPARATOR"file2"};
+ TEST("?i*/?i*");
+ EXPECT(results_test13);
+
+ // wildcards on file only
+ const char *results_test14[] = {"dir1"PATH_SEPARATOR"dir1",
+ "dir1"PATH_SEPARATOR"dir2",
+ "dir1"PATH_SEPARATOR"file1",
+ "dir1"PATH_SEPARATOR"file2"};
+ TEST("dir1"PATH_SEPARATOR"?i*");
+ EXPECT(results_test14);
+
+ // wildcards on folder only
+ const char *results_test15[] = {"dir1"PATH_SEPARATOR"file1",
+ "dir2"PATH_SEPARATOR"file1"};
+ TEST("?i*"PATH_SEPARATOR"file1");
+ EXPECT(results_test15);
+
+ // wildcards after file name
+ TEST("file1"PATH_SEPARATOR"*");
+ EXPECT_EMPTY();
+
+#ifndef _WIN32
+ // test wildcard escaping
+ TEST("\\*");
+ EXPECT_EMPTY();
+
+ if (getuid() != 0) {
+ // test forbidden directory, if we're not root.
+ // (Root will be able to see this directory anyway.)
+ tor_asprintf(&pattern, "%s"PATH_SEPARATOR"*"PATH_SEPARATOR"*", dirname);
+ results = tor_glob(pattern);
+ tor_free(pattern);
+ tt_assert(!results);
+ }
+#endif
+
+#undef TEST
+#undef EXPECT
+#undef EXPECT_EMPTY
+
+ done:
+#ifndef _WIN32
+ (void) chmod(forbidden, 0700);
+ (void) chmod(dir1_forbidden, 0700);
+ (void) chmod(dir2_forbidden, 0700);
+ (void) chmod(forbidden_forbidden, 0700);
+#endif
+ tor_free(dir1);
+ tor_free(dir2);
+ tor_free(forbidden);
+ tor_free(dirname);
+ tor_free(dir1_forbidden);
+ tor_free(dir2_forbidden);
+ tor_free(forbidden_forbidden);
+ tor_free(expected);
+ tor_free(pattern);
+ if (results) {
+ SMARTLIST_FOREACH(results, char *, f, tor_free(f));
+ smartlist_free(results);
+ }
+#else
+ tt_skip();
+ done:
+ return;
+#endif
+}
+
+static void
+test_util_get_glob_opened_files(void *ptr)
+{
+ (void)ptr;
+
+#ifdef HAVE_GLOB
+ smartlist_t *results = NULL;
+ int r, i;
+ char *dir1 = NULL, *dir2 = NULL, *forbidden = NULL, *dirname = NULL;
+ char *expected = NULL, *pattern = NULL;
+ // used for cleanup
+ char *dir1_forbidden = NULL, *dir2_forbidden = NULL;
+ char *forbidden_forbidden = NULL;
+
+ dirname = tor_strdup(get_fname("test_get_glob_opened_files"));
+ tt_ptr_op(dirname, OP_NE, NULL);
+
+#ifdef _WIN32
+ r = mkdir(dirname);
+#else
+ r = mkdir(dirname, 0700);
+#endif
+ if (r) {
+ fprintf(stderr, "Can't create directory %s:", dirname);
+ perror("");
+ exit(1);
+ }
+
+ tt_int_op(0, OP_EQ, create_test_directory_structure(dirname));
+ tor_asprintf(&dir1, "%s"PATH_SEPARATOR"dir1", dirname);
+ tor_asprintf(&dir1_forbidden,
+ "%s"PATH_SEPARATOR"dir1"PATH_SEPARATOR"forbidden", dirname);
+ tt_int_op(0, OP_EQ, create_test_directory_structure(dir1));
+ tor_asprintf(&dir2, "%s"PATH_SEPARATOR"dir2", dirname);
+ tor_asprintf(&dir2_forbidden,
+ "%s"PATH_SEPARATOR"dir2"PATH_SEPARATOR"forbidden", dirname);
+ tt_int_op(0, OP_EQ, create_test_directory_structure(dir2));
+ tor_asprintf(&forbidden, "%s"PATH_SEPARATOR"forbidden", dirname);
+ tor_asprintf(&forbidden_forbidden,
+ "%s"PATH_SEPARATOR"forbidden"PATH_SEPARATOR"forbidden",dirname);
+#ifndef _WIN32
+ chmod(forbidden, 0700);
+#endif
+ tt_int_op(0, OP_EQ, create_test_directory_structure(forbidden));
+#ifndef _WIN32
+ chmod(forbidden, 0);
+#endif
+
+#define TEST(input) \
+ do { \
+ if (*input) { \
+ tor_asprintf(&pattern, "%s"PATH_SEPARATOR"%s", dirname, input); \
+ } else { /* do not add path separator if empty string */ \
+ tor_asprintf(&pattern, "%s", dirname); \
+ } \
+ results = get_glob_opened_files(pattern); \
+ tor_free(pattern); \
+ tt_assert(results); \
+ smartlist_sort_strings(results); \
+ } while (0);
+
+#define EXPECT(result) \
+ do { \
+ tt_int_op(smartlist_len(results), OP_EQ, \
+ sizeof(result)/sizeof(*result)); \
+ i = 0; \
+ SMARTLIST_FOREACH_BEGIN(results, const char *, f) { \
+ if (*result[i]) { \
+ tor_asprintf(&expected, "%s"PATH_SEPARATOR"%s", dirname, result[i]); \
+ } else { /* do not add path separator if empty string */ \
+ tor_asprintf(&expected, "%s", dirname); \
+ } \
+ tt_str_op(f, OP_EQ, expected); \
+ i++; \
+ tor_free(expected); \
+ } SMARTLIST_FOREACH_END(f); \
+ SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \
+ smartlist_free(results); \
+ } while (0);
+
+#define EXPECT_EMPTY() \
+ do { \
+ tt_int_op(smartlist_len(results), OP_EQ, 0); \
+ SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \
+ smartlist_free(results); \
+ } while (0);
+
+ // all files on folder
+ const char *results_test1[] = {""}; // only the folder is read
+ TEST("*");
+ EXPECT(results_test1);
+
+ // same as before but ending in path separator
+ const char *results_test2[] = {""}; // only the folder is read
+ TEST("*"PATH_SEPARATOR);
+ EXPECT(results_test2);
+
+ // wildcards in multiple path components
+#ifndef _WIN32
+ const char *results_test3[] = {"", "dir1", "dir2", "empty", "file1", "file2",
+ "forbidden"};
+#else
+ // dot files are not special on windows
+ const char *results_test3[] = {"", ".test-hidden", "dir1", "dir2", "empty",
+ "file1", "file2", "forbidden"};
+#endif
+ TEST("*"PATH_SEPARATOR"*");
+ EXPECT(results_test3);
+
+ // same as before but ending in path separator
+#ifndef _WIN32
+ const char *results_test4[] = {"", "dir1", "dir2", "empty", "file1", "file2",
+ "forbidden"};
+#else
+ // dot files are not special on windows
+ const char *results_test4[] = {"", ".test-hidden", "dir1", "dir2", "empty",
+ "file1", "file2", "forbidden"};
+#endif
+ TEST("*"PATH_SEPARATOR"*"PATH_SEPARATOR);
+ EXPECT(results_test4);
+
+ // no glob - folder
+ TEST("");
+ EXPECT_EMPTY();
+
+ // same as before but ending in path separator
+ TEST(PATH_SEPARATOR);
+ EXPECT_EMPTY();
+
+ // no glob - file
+ TEST("file1");
+ EXPECT_EMPTY();
+
+ // same as before but ending in path separator and linux path separator
+ TEST("file1/");
+ EXPECT_EMPTY();
+
+ // file but with wildcard after
+ const char *results_test9[] = {"file1"};
+ TEST("file1"PATH_SEPARATOR"*");
+ EXPECT(results_test9);
+
+ // dir inside dir and linux path separator
+ TEST("dir1/dir1");
+ EXPECT_EMPTY();
+
+ // same as before but ending in path separator
+ TEST("dir1"PATH_SEPARATOR"dir1"PATH_SEPARATOR);
+ EXPECT_EMPTY();
+
+ // no glob - empty
+ TEST("empty");
+ EXPECT_EMPTY();
+
+ // same as before but ending in path separator
+ TEST("empty"PATH_SEPARATOR);
+ EXPECT_EMPTY();
+
+ // no glob - does not exist
+ TEST("not_exist");
+ EXPECT_EMPTY();
+
+#undef TEST
+#undef EXPECT
+#undef EXPECT_EMPTY
+
+ done:
+#ifndef _WIN32
+ {
+ int chmod_failed = 0;
+ if (forbidden)
+ chmod_failed |= chmod(forbidden, 0700);
+ if (dir1_forbidden)
+ chmod_failed |= chmod(dir1_forbidden, 0700);
+ if (dir2_forbidden)
+ chmod_failed |= chmod(dir2_forbidden, 0700);
+ if (forbidden_forbidden)
+ chmod_failed |= chmod(forbidden_forbidden, 0700);
+ if (chmod_failed) {
+ TT_FAIL(("unable to chmod a file on cleanup: %s", strerror(errno)));
+ }
+ }
+#endif
+ tor_free(dir1);
+ tor_free(dir2);
+ tor_free(forbidden);
+ tor_free(dirname);
+ tor_free(dir1_forbidden);
+ tor_free(dir2_forbidden);
+ tor_free(forbidden_forbidden);
+ tor_free(expected);
+ tor_free(pattern);
+ if (results) {
+ SMARTLIST_FOREACH(results, char *, f, tor_free(f));
+ smartlist_free(results);
+ }
+#else
+ tt_skip();
+ done:
+ return;
+#endif
+}
+
+static void
test_util_parent_dir(void *ptr)
{
char *cp;
@@ -5684,7 +6193,7 @@ test_util_hostname_validation(void *arg)
// XXX: do we allow single-label DNS names?
// We shouldn't for SOCKS (spec says "contains a fully-qualified domain name"
- // but only test pathologically malformed traling '.' cases for now.
+ // but only test pathologically malformed trailing '.' cases for now.
tt_assert(!string_is_valid_nonrfc_hostname("."));
tt_assert(!string_is_valid_nonrfc_hostname(".."));
@@ -5786,6 +6295,20 @@ test_util_get_avail_disk_space(void *arg)
;
}
+/** Helper: Change the atime and mtime of a file. */
+static void
+set_file_mtime(const char *fname, time_t when)
+{
+ struct utimbuf u = { when, when };
+ struct stat st;
+ tt_int_op(0, OP_EQ, utime(fname, &u));
+ tt_int_op(0, OP_EQ, stat(fname, &st));
+ /* Let's hope that utime/stat give the same second as a round-trip? */
+ tt_i64_op(st.st_mtime, OP_EQ, when);
+done:
+ ;
+}
+
static void
test_util_touch_file(void *arg)
{
@@ -5803,11 +6326,7 @@ test_util_touch_file(void *arg)
tt_i64_op(st.st_mtime, OP_GE, now - 1);
const time_t five_sec_ago = now - 5;
- struct utimbuf u = { five_sec_ago, five_sec_ago };
- tt_int_op(0, OP_EQ, utime(fname, &u));
- tt_int_op(0, OP_EQ, stat(fname, &st));
- /* Let's hope that utime/stat give the same second as a round-trip? */
- tt_i64_op(st.st_mtime, OP_EQ, five_sec_ago);
+ set_file_mtime(fname, five_sec_ago);
/* Finally we can touch the file */
tt_int_op(0, OP_EQ, touch_file(fname));
@@ -6469,10 +6988,13 @@ struct testcase_t util_tests[] = {
UTIL_TEST(laplace, 0),
UTIL_TEST(clamp_double_to_int64, 0),
UTIL_TEST(find_str_at_start_of_line, 0),
+ UTIL_TEST(tor_strreplacechar, 0),
UTIL_TEST(string_is_C_identifier, 0),
UTIL_TEST(string_is_utf8, 0),
UTIL_TEST(asprintf, 0),
UTIL_TEST(listdir, 0),
+ UTIL_TEST(glob, 0),
+ UTIL_TEST(get_glob_opened_files, 0),
UTIL_TEST(parent_dir, 0),
UTIL_TEST(ftruncate, 0),
UTIL_TEST(nowrap_math, 0),
@@ -6494,6 +7016,7 @@ struct testcase_t util_tests[] = {
UTIL_TEST(read_file_eof_zero_bytes, 0),
UTIL_TEST(read_file_endlines, 0),
UTIL_TEST(write_chunks_to_file, 0),
+ UTIL_TEST(write_str_if_changed, 0),
UTIL_TEST(mathlog, 0),
UTIL_TEST(fraction, 0),
UTIL_TEST(weak_random, 0),
diff --git a/src/test/test_voting_flags.c b/src/test/test_voting_flags.c
index ae89e43889..72f70b9865 100644
--- a/src/test/test_voting_flags.c
+++ b/src/test/test_voting_flags.c
@@ -42,10 +42,10 @@ setup_cfg(flag_vote_test_cfg_t *c)
c->ri.cache_info.published_on = c->now - 100;
c->expected.published_on = c->now - 100;
- c->ri.addr = 0x7f010105;
- c->expected.addr = 0x7f010105;
- c->ri.or_port = 9090;
- c->expected.or_port = 9090;
+ tor_addr_from_ipv4h(&c->ri.ipv4_addr, 0x7f010105);
+ tor_addr_from_ipv4h(&c->expected.ipv4_addr, 0x7f010105);
+ c->ri.ipv4_orport = 9090;
+ c->expected.ipv4_orport = 9090;
tor_addr_make_null(&c->ri.ipv6_addr, AF_INET6);
tor_addr_make_null(&c->expected.ipv6_addr, AF_INET6);
@@ -69,9 +69,9 @@ check_result(flag_vote_test_cfg_t *c)
// identity_digest and descriptor_digest are not set here.
- tt_uint_op(rs.addr, OP_EQ, c->expected.addr);
- tt_uint_op(rs.or_port, OP_EQ, c->expected.or_port);
- tt_uint_op(rs.dir_port, OP_EQ, c->expected.dir_port);
+ tt_assert(tor_addr_eq(&rs.ipv4_addr, &c->expected.ipv4_addr));
+ tt_uint_op(rs.ipv4_orport, OP_EQ, c->expected.ipv4_orport);
+ tt_uint_op(rs.ipv4_dirport, OP_EQ, c->expected.ipv4_dirport);
tt_assert(tor_addr_eq(&rs.ipv6_addr, &c->expected.ipv6_addr));
tt_uint_op(rs.ipv6_orport, OP_EQ, c->expected.ipv6_orport);
diff --git a/src/test/testing_common.c b/src/test/testing_common.c
index d68dfa4047..9b50de07a8 100644
--- a/src/test/testing_common.c
+++ b/src/test/testing_common.c
@@ -18,6 +18,7 @@
#include "lib/crypt_ops/crypto_ed25519.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "feature/stats/predict_ports.h"
+#include "feature/stats/bwhist.h"
#include "feature/stats/rephist.h"
#include "lib/err/backtrace.h"
#include "test/test.h"
@@ -348,6 +349,7 @@ main(int c, const char **v)
return 1;
}
rep_hist_init();
+ bwhist_init();
setup_directory();
initialize_mainloop_events();
options_init(options);
diff --git a/src/test/vote_descriptors.inc b/src/test/vote_descriptors.inc
index 895dc6c65c..51cf465170 100644
--- a/src/test/vote_descriptors.inc
+++ b/src/test/vote_descriptors.inc
@@ -1,3 +1,6 @@
+/* Not sure where we got this; it appears to be hand-generated and signed.
+ * It's been edited so that the signature doesn't verify any more;
+ * you need to mock check_signature_token for this to work. */
static const char* VOTE_BODY_V3 =
"network-status-version 3\n"
"vote-status vote\n"
@@ -60,6 +63,7 @@ static const char* VOTE_BODY_V3 =
"w Bandwidth=30 Measured=30\n"
"p reject 1-65535\n"
"id ed25519 none\n"
+"pr Cons=1-2 Desc=1-2 DirCache=1-2 FlowCtrl=1 HSDir=1-2 HSIntro=3-5\n"
"m 9,10,11,12,13,14,15,16,17 sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa0\n"
"r router1 BQUFBQUFBQUFBQUFBQUFBQUFBQU TU1NTU1NTU1NTU1NTU1NTU1NTU0 2015-09-02 19:17:35 153.0.153.1 443 0\n"
"a [1:2:3::4]:4711\n"
@@ -68,6 +72,7 @@ static const char* VOTE_BODY_V3 =
"w Bandwidth=120 Measured=120\n"
"p reject 1-65535\n"
"id ed25519 none\n"
+"pr Cons=1-2 Desc=1-2 DirCache=1-2 FlowCtrl=1 HSDir=1-2 HSIntro=3-5\n"
"m 9,10,11,12,13,14,15,16,17 sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa1\n"
"r router3 MzMzMzMzMzMzMzMzMzMzMzMzMzM T09PT09PT09PT09PT09PT09PT08 2015-09-02 19:17:35 170.0.153.1 400 9999\n"
"s Authority Exit Fast Guard Running Stable V2Dir Valid\n"
@@ -75,6 +80,7 @@ static const char* VOTE_BODY_V3 =
"w Bandwidth=120\n"
"p reject 1-65535\n"
"id ed25519 none\n"
+"pr Cons=1-2 Desc=1-2 DirCache=1-2 FlowCtrl=1 HSDir=1-2 HSIntro=3-5\n"
"m 9,10,11,12,13,14,15,16,17 "
"sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa2\n"
"r router4 NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ Ly8vLy8vLy8vLy8vLy8vLy8vLy8 2015-09-02 19:17:35 192.0.2.3 500 1999\n"
@@ -83,6 +89,7 @@ static const char* VOTE_BODY_V3 =
"w Bandwidth=30\n"
"p reject 1-65535\n"
"id ed25519 none\n"
+"pr Cons=1-2 Desc=1-2 DirCache=1-2 FlowCtrl=1 HSDir=1-2 HSIntro=3-5\n"
"m 9,10,11,12,13,14,15,16,17 sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa3\n"
"directory-footer\n"
"directory-signature D867ACF56A9D229B35C25F0090BC9867E906BE69 CBF56A83368A5150F1A9AAADAFB4D77F8C4170E2\n"
@@ -91,4 +98,3 @@ static const char* VOTE_BODY_V3 =
"TXQWGUq9Z7jdSVnzWT3xqPA4zjw6eZkj+DKUtwq+oEDZGlf8eHTFmr0NAWfwZbk9\n"
"NAjbMTUXUP37N2XAZwkoCWwFCrrfMwXrL7OhZbj7ifo=\n"
"-----END SIGNATURE-----\n";
-
diff --git a/src/tools/include.am b/src/tools/include.am
index 72dfe6017c..6daa27f6de 100644
--- a/src/tools/include.am
+++ b/src/tools/include.am
@@ -11,7 +11,7 @@ src_tools_tor_resolve_LDADD = \
$(TOR_UTIL_LIBS) \
$(TOR_CRYPTO_LIBS) $(TOR_LIBS_CRYPTLIB)\
$(rust_ldadd) \
- @TOR_LIB_MATH@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_USERENV@
+ @TOR_LIB_MATH@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_USERENV@
if COVERAGE_ENABLED
src_tools_tor_cov_resolve_SOURCES = src/tools/tor-resolve.c
@@ -36,7 +36,7 @@ src_tools_tor_gencert_LDADD = \
$(TOR_UTIL_LIBS) \
$(rust_ldadd) \
@TOR_LIB_MATH@ @TOR_ZLIB_LIBS@ $(TOR_LIBS_CRYPTLIB) \
- @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@
+ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@
endif
src_tools_tor_print_ed_signing_cert_SOURCES = src/tools/tor-print-ed-signing-cert.c
@@ -46,7 +46,7 @@ src_tools_tor_print_ed_signing_cert_LDADD = \
$(TOR_CRYPTO_LIBS) \
$(TOR_UTIL_LIBS) \
@TOR_LIB_MATH@ $(TOR_LIBS_CRYPTLIB) \
- @TOR_LIB_WS32@ @TOR_LIB_USERENV@ @TOR_LIB_GDI@
+ @TOR_LIB_WS32@ @TOR_LIB_USERENV@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@
if USE_NSS
# ...
@@ -61,7 +61,7 @@ src_tools_tor_cov_gencert_LDADD = \
$(TOR_CRYPTO_TESTING_LIBS) \
$(TOR_UTIL_TESTING_LIBS) \
@TOR_LIB_MATH@ @TOR_ZLIB_LIBS@ $(TOR_LIBS_CRYPTLIB) \
- @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @CURVE25519_LIBS@
+ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @CURVE25519_LIBS@
endif
endif
diff --git a/src/trunnel/circpad_negotiation.c b/src/trunnel/circpad_negotiation.c
index 547818f2ec..4e3ee3d5bd 100644
--- a/src/trunnel/circpad_negotiation.c
+++ b/src/trunnel/circpad_negotiation.c
@@ -112,6 +112,17 @@ circpad_negotiate_set_echo_request(circpad_negotiate_t *inp, uint8_t val)
inp->echo_request = val;
return 0;
}
+uint32_t
+circpad_negotiate_get_machine_ctr(const circpad_negotiate_t *inp)
+{
+ return inp->machine_ctr;
+}
+int
+circpad_negotiate_set_machine_ctr(circpad_negotiate_t *inp, uint32_t val)
+{
+ inp->machine_ctr = val;
+ return 0;
+}
const char *
circpad_negotiate_check(const circpad_negotiate_t *obj)
{
@@ -148,6 +159,9 @@ circpad_negotiate_encoded_len(const circpad_negotiate_t *obj)
/* Length of u8 echo_request IN [0, 1] */
result += 1;
+
+ /* Length of u32 machine_ctr */
+ result += 4;
return result;
}
int
@@ -203,6 +217,13 @@ circpad_negotiate_encode(uint8_t *output, const size_t avail, const circpad_nego
trunnel_set_uint8(ptr, (obj->echo_request));
written += 1; ptr += 1;
+ /* Encode u32 machine_ctr */
+ trunnel_assert(written <= avail);
+ if (avail - written < 4)
+ goto truncated;
+ trunnel_set_uint32(ptr, trunnel_htonl(obj->machine_ctr));
+ written += 4; ptr += 4;
+
trunnel_assert(ptr == output + written);
#ifdef TRUNNEL_CHECK_ENCODED_LEN
@@ -263,6 +284,11 @@ circpad_negotiate_parse_into(circpad_negotiate_t *obj, const uint8_t *input, con
remaining -= 1; ptr += 1;
if (! (obj->echo_request == 0 || obj->echo_request == 1))
goto fail;
+
+ /* Parse u32 machine_ctr */
+ CHECK_REMAINING(4, truncated);
+ obj->machine_ctr = trunnel_ntohl(trunnel_get_uint32(ptr));
+ remaining -= 4; ptr += 4;
trunnel_assert(ptr + remaining == input + len_in);
return len_in - remaining;
@@ -372,6 +398,17 @@ circpad_negotiated_set_machine_type(circpad_negotiated_t *inp, uint8_t val)
inp->machine_type = val;
return 0;
}
+uint32_t
+circpad_negotiated_get_machine_ctr(const circpad_negotiated_t *inp)
+{
+ return inp->machine_ctr;
+}
+int
+circpad_negotiated_set_machine_ctr(circpad_negotiated_t *inp, uint32_t val)
+{
+ inp->machine_ctr = val;
+ return 0;
+}
const char *
circpad_negotiated_check(const circpad_negotiated_t *obj)
{
@@ -408,6 +445,9 @@ circpad_negotiated_encoded_len(const circpad_negotiated_t *obj)
/* Length of u8 machine_type */
result += 1;
+
+ /* Length of u32 machine_ctr */
+ result += 4;
return result;
}
int
@@ -463,6 +503,13 @@ circpad_negotiated_encode(uint8_t *output, const size_t avail, const circpad_neg
trunnel_set_uint8(ptr, (obj->machine_type));
written += 1; ptr += 1;
+ /* Encode u32 machine_ctr */
+ trunnel_assert(written <= avail);
+ if (avail - written < 4)
+ goto truncated;
+ trunnel_set_uint32(ptr, trunnel_htonl(obj->machine_ctr));
+ written += 4; ptr += 4;
+
trunnel_assert(ptr == output + written);
#ifdef TRUNNEL_CHECK_ENCODED_LEN
@@ -523,6 +570,11 @@ circpad_negotiated_parse_into(circpad_negotiated_t *obj, const uint8_t *input, c
CHECK_REMAINING(1, truncated);
obj->machine_type = (trunnel_get_uint8(ptr));
remaining -= 1; ptr += 1;
+
+ /* Parse u32 machine_ctr */
+ CHECK_REMAINING(4, truncated);
+ obj->machine_ctr = trunnel_ntohl(trunnel_get_uint32(ptr));
+ remaining -= 4; ptr += 4;
trunnel_assert(ptr + remaining == input + len_in);
return len_in - remaining;
diff --git a/src/trunnel/circpad_negotiation.h b/src/trunnel/circpad_negotiation.h
index ba9155019e..9004540d43 100644
--- a/src/trunnel/circpad_negotiation.h
+++ b/src/trunnel/circpad_negotiation.h
@@ -26,6 +26,7 @@ struct circpad_negotiate_st {
uint8_t machine_type;
/** If true, send a relay_drop reply.. */
uint8_t echo_request;
+ uint32_t machine_ctr;
uint8_t trunnel_error_code_;
};
#endif
@@ -42,6 +43,14 @@ struct circpad_negotiated_st {
/** Machine type is left unbounded because we can specify
* new machines in the consensus */
uint8_t machine_type;
+ /**
+ * This field is used for shutdown synchronization. It is OK if
+ * it wraps, because all we need to do is make sure the STOP
+ * command is actually for the currently active machine.
+ * For backward-compatibility, though, 0 has special meaning
+ * (it means match any machine).
+ */
+ uint32_t machine_ctr;
uint8_t trunnel_error_code_;
};
#endif
@@ -118,6 +127,15 @@ uint8_t circpad_negotiate_get_echo_request(const circpad_negotiate_t *inp);
* code on 'inp' on failure.
*/
int circpad_negotiate_set_echo_request(circpad_negotiate_t *inp, uint8_t val);
+/** Return the value of the machine_ctr field of the
+ * circpad_negotiate_t in 'inp'
+ */
+uint32_t circpad_negotiate_get_machine_ctr(const circpad_negotiate_t *inp);
+/** Set the value of the machine_ctr field of the circpad_negotiate_t
+ * in 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int circpad_negotiate_set_machine_ctr(circpad_negotiate_t *inp, uint32_t val);
/** Return a newly allocated circpad_negotiated with all elements set
* to zero.
*/
@@ -190,6 +208,15 @@ uint8_t circpad_negotiated_get_machine_type(const circpad_negotiated_t *inp);
* -1 and set the error code on 'inp' on failure.
*/
int circpad_negotiated_set_machine_type(circpad_negotiated_t *inp, uint8_t val);
+/** Return the value of the machine_ctr field of the
+ * circpad_negotiated_t in 'inp'
+ */
+uint32_t circpad_negotiated_get_machine_ctr(const circpad_negotiated_t *inp);
+/** Set the value of the machine_ctr field of the circpad_negotiated_t
+ * in 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int circpad_negotiated_set_machine_ctr(circpad_negotiated_t *inp, uint32_t val);
#endif
diff --git a/src/trunnel/circpad_negotiation.trunnel b/src/trunnel/circpad_negotiation.trunnel
index abbc929cc5..68fed6a013 100644
--- a/src/trunnel/circpad_negotiation.trunnel
+++ b/src/trunnel/circpad_negotiation.trunnel
@@ -27,6 +27,13 @@ struct circpad_negotiate {
// FIXME-MP-AP: Maybe we just say to transition to the first state
// here instead.. Also what about delay before responding?
u8 echo_request IN [0,1];
+
+ // This field is used for shutdown synchronization. It is OK if
+ // it wraps, because all we need to do is make sure the STOP
+ // command is actually for the currently active machine.
+ // For backward-compatibility, though, 0 has special meaning
+ // (it means match any machine).
+ u32 machine_ctr;
};
/**
@@ -41,4 +48,14 @@ struct circpad_negotiated {
/** Machine type is left unbounded because we can specify
* new machines in the consensus */
u8 machine_type;
+
+ /**
+ * This field is used for shutdown synchronization. It is OK if
+ * it wraps, because all we need to do is make sure the STOP
+ * command is actually for the currently active machine.
+ * For backward-compatibility, though, 0 has special meaning
+ * (it means match any machine).
+ */
+ u32 machine_ctr;
+
};
diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h
index 1f6284727b..06e6ad8ff7 100644
--- a/src/win32/orconfig.h
+++ b/src/win32/orconfig.h
@@ -217,7 +217,7 @@
#define USING_TWOS_COMPLEMENT
/* Version number of package */
-#define VERSION "0.4.4.8-dev"
+#define VERSION "0.4.5.8"
#define HAVE_STRUCT_SOCKADDR_IN6
#define HAVE_STRUCT_IN6_ADDR