aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore95
-rw-r--r--.travis.yml3
-rw-r--r--CODE_OF_CONDUCT7
-rw-r--r--ChangeLog70
-rw-r--r--Doxyfile.in1156
-rw-r--r--LICENSE2
-rw-r--r--Makefile.am137
-rw-r--r--acinclude.m42
-rw-r--r--changes/bug221563
-rw-r--r--changes/bug254773
-rw-r--r--changes/bug258867
-rw-r--r--changes/bug261524
-rw-r--r--changes/bug262824
-rw-r--r--changes/bug264884
-rw-r--r--changes/bug265226
-rw-r--r--changes/bug265254
-rw-r--r--changes/doc266384
-rw-r--r--changes/feature83233
-rw-r--r--changes/full_include_paths3
-rw-r--r--changes/iphplapi4
-rw-r--r--changes/split_or_h5
-rw-r--r--changes/ticket199793
-rw-r--r--changes/ticket259284
-rw-r--r--changes/ticket264264
-rw-r--r--changes/ticket264276
-rw-r--r--changes/ticket265104
-rw-r--r--changes/ticket265273
-rw-r--r--changes/ticket265603
-rw-r--r--changes/ticket266263
-rw-r--r--configure.ac60
-rw-r--r--contrib/include.am1
-rw-r--r--contrib/win32build/package_nsis-mingw.sh95
-rw-r--r--contrib/win32build/tor-mingw.nsi.in2
-rw-r--r--doc/HACKING/CodingStandards.md5
-rw-r--r--doc/HACKING/HelpfulTools.md16
-rw-r--r--doc/HACKING/Module.md26
-rw-r--r--doc/HACKING/Tracing.md2
-rw-r--r--doc/include.am6
-rwxr-xr-xscripts/codegen/fuzzing_include_am.py23
-rwxr-xr-xscripts/codegen/gen_server_ciphers.py2
-rwxr-xr-xscripts/codegen/get_mozilla_ciphers.py2
-rw-r--r--scripts/codegen/makedesc.py2
-rwxr-xr-xscripts/maint/checkIncludes.py84
-rw-r--r--scripts/maint/checkOptionDocs.pl.in2
-rwxr-xr-xscripts/maint/checkSpace.pl11
-rw-r--r--scripts/maint/fallback.whitelist3
-rwxr-xr-xscripts/maint/format_changelog.py2
-rwxr-xr-xscripts/maint/rectify_include_paths.py60
-rwxr-xr-xscripts/maint/redox.py2
-rwxr-xr-xscripts/maint/sortChanges.py2
-rwxr-xr-xscripts/maint/updateCopyright.pl4
-rwxr-xr-xscripts/maint/updateFallbackDirs.py8
-rwxr-xr-xscripts/test/coverage2
-rw-r--r--src/app/config/auth_dirs.inc (renamed from src/or/auth_dirs.inc)0
-rw-r--r--src/app/config/config.c (renamed from src/or/config.c)180
-rw-r--r--src/app/config/config.h (renamed from src/or/config.h)32
-rw-r--r--src/app/config/confparse.c (renamed from src/or/confparse.c)37
-rw-r--r--src/app/config/confparse.h (renamed from src/or/confparse.h)13
-rw-r--r--src/app/config/fallback_dirs.inc (renamed from src/or/fallback_dirs.inc)0
-rw-r--r--src/app/config/or_options_st.h1077
-rw-r--r--src/app/config/or_state_st.h86
-rw-r--r--src/app/config/statefile.c (renamed from src/or/statefile.c)36
-rw-r--r--src/app/config/statefile.h (renamed from src/or/statefile.h)6
-rw-r--r--src/app/include.am35
-rw-r--r--src/app/main/ntmain.c (renamed from src/or/ntmain.c)14
-rw-r--r--src/app/main/ntmain.h (renamed from src/or/ntmain.h)2
-rw-r--r--src/app/main/tor_main.c (renamed from src/or/tor_main.c)2
-rw-r--r--src/common/Makefile.nmake28
-rw-r--r--src/common/address_set.c129
-rw-r--r--src/common/compat.c3531
-rw-r--r--src/common/compat.h757
-rw-r--r--src/common/container.c1542
-rw-r--r--src/common/container.h742
-rw-r--r--src/common/crypto.c1118
-rw-r--r--src/common/include.am213
-rw-r--r--src/common/pubsub.c129
-rw-r--r--src/common/pubsub.h179
-rw-r--r--src/common/torint.h379
-rw-r--r--src/common/util.c5378
-rw-r--r--src/common/util.h572
-rw-r--r--src/core/crypto/hs_ntor.c (renamed from src/or/hs_ntor.c)11
-rw-r--r--src/core/crypto/hs_ntor.h69
-rw-r--r--src/core/crypto/onion.c (renamed from src/or/onion.c)42
-rw-r--r--src/core/crypto/onion.h (renamed from src/or/onion.h)13
-rw-r--r--src/core/crypto/onion_fast.c (renamed from src/or/onion_fast.c)12
-rw-r--r--src/core/crypto/onion_fast.h (renamed from src/or/onion_fast.h)2
-rw-r--r--src/core/crypto/onion_ntor.c (renamed from src/or/onion_ntor.c)20
-rw-r--r--src/core/crypto/onion_ntor.h (renamed from src/or/onion_ntor.h)26
-rw-r--r--src/core/crypto/onion_tap.c (renamed from src/or/onion_tap.c)34
-rw-r--r--src/core/crypto/onion_tap.h (renamed from src/or/onion_tap.h)20
-rw-r--r--src/core/crypto/relay_crypto.c (renamed from src/or/relay_crypto.c)19
-rw-r--r--src/core/crypto/relay_crypto.h (renamed from src/or/relay_crypto.h)2
-rw-r--r--src/core/include.am330
-rw-r--r--src/core/mainloop/connection.c (renamed from src/or/connection.c)161
-rw-r--r--src/core/mainloop/connection.h (renamed from src/or/connection.h)138
-rw-r--r--src/core/mainloop/cpuworker.c (renamed from src/or/cpuworker.c)36
-rw-r--r--src/core/mainloop/cpuworker.h (renamed from src/or/cpuworker.h)2
-rw-r--r--src/core/mainloop/main.c (renamed from src/or/main.c)249
-rw-r--r--src/core/mainloop/main.h (renamed from src/or/main.h)11
-rw-r--r--src/core/mainloop/periodic.c (renamed from src/or/periodic.c)14
-rw-r--r--src/core/mainloop/periodic.h (renamed from src/or/periodic.h)2
-rw-r--r--src/core/or/addr_policy_st.h46
-rw-r--r--src/core/or/address_set.c71
-rw-r--r--src/core/or/address_set.h (renamed from src/common/address_set.h)16
-rw-r--r--src/core/or/cell_queue_st.h29
-rw-r--r--src/core/or/cell_st.h20
-rw-r--r--src/core/or/channel.c (renamed from src/or/channel.c)340
-rw-r--r--src/core/or/channel.h (renamed from src/or/channel.h)166
-rw-r--r--src/core/or/channelpadding.c (renamed from src/or/channelpadding.c)61
-rw-r--r--src/core/or/channelpadding.h (renamed from src/or/channelpadding.h)4
-rw-r--r--src/core/or/channeltls.c (renamed from src/or/channeltls.c)128
-rw-r--r--src/core/or/channeltls.h (renamed from src/or/channeltls.h)12
-rw-r--r--src/core/or/circuit_st.h182
-rw-r--r--src/core/or/circuitbuild.c (renamed from src/or/circuitbuild.c)101
-rw-r--r--src/core/or/circuitbuild.h (renamed from src/or/circuitbuild.h)16
-rw-r--r--src/core/or/circuitlist.c (renamed from src/or/circuitlist.c)130
-rw-r--r--src/core/or/circuitlist.h247
-rw-r--r--src/core/or/circuitmux.c (renamed from src/or/circuitmux.c)74
-rw-r--r--src/core/or/circuitmux.h (renamed from src/or/circuitmux.h)6
-rw-r--r--src/core/or/circuitmux_ewma.c (renamed from src/or/circuitmux_ewma.c)14
-rw-r--r--src/core/or/circuitmux_ewma.h (renamed from src/or/circuitmux_ewma.h)6
-rw-r--r--src/core/or/circuitstats.c (renamed from src/or/circuitstats.c)44
-rw-r--r--src/core/or/circuitstats.h (renamed from src/or/circuitstats.h)104
-rw-r--r--src/core/or/circuituse.c (renamed from src/or/circuituse.c)81
-rw-r--r--src/core/or/circuituse.h (renamed from src/or/circuituse.h)2
-rw-r--r--src/core/or/command.c (renamed from src/or/command.c)49
-rw-r--r--src/core/or/command.h (renamed from src/or/command.h)4
-rw-r--r--src/core/or/connection_edge.c (renamed from src/or/connection_edge.c)124
-rw-r--r--src/core/or/connection_edge.h (renamed from src/or/connection_edge.h)61
-rw-r--r--src/core/or/connection_or.c (renamed from src/or/connection_or.c)96
-rw-r--r--src/core/or/connection_or.h (renamed from src/or/connection_or.h)60
-rw-r--r--src/core/or/connection_st.h149
-rw-r--r--src/core/or/cpath_build_state_st.h38
-rw-r--r--src/core/or/crypt_path_reference_st.h23
-rw-r--r--src/core/or/crypt_path_st.h70
-rw-r--r--src/core/or/destroy_cell_queue_st.h27
-rw-r--r--src/core/or/dos.c (renamed from src/or/dos.c)29
-rw-r--r--src/core/or/dos.h (renamed from src/or/dos.h)2
-rw-r--r--src/core/or/edge_connection_st.h77
-rw-r--r--src/core/or/entry_connection_st.h100
-rw-r--r--src/core/or/entry_port_cfg_st.h54
-rw-r--r--src/core/or/extend_info_st.h30
-rw-r--r--src/core/or/git_revision.c (renamed from src/or/git_revision.c)7
-rw-r--r--src/core/or/git_revision.h (renamed from src/or/git_revision.h)2
-rw-r--r--src/core/or/listener_connection_st.h25
-rw-r--r--src/core/or/or.h1088
-rw-r--r--src/core/or/or_circuit_st.h80
-rw-r--r--src/core/or/or_connection_st.h92
-rw-r--r--src/core/or/or_handshake_certs_st.h40
-rw-r--r--src/core/or/or_handshake_state_st.h78
-rw-r--r--src/core/or/origin_circuit_st.h290
-rw-r--r--src/core/or/policies.c (renamed from src/or/policies.c)40
-rw-r--r--src/core/or/policies.h (renamed from src/or/policies.h)39
-rw-r--r--src/core/or/port_cfg_st.h35
-rw-r--r--src/core/or/protover.c (renamed from src/or/protover.c)8
-rw-r--r--src/core/or/protover.h (renamed from src/or/protover.h)16
-rw-r--r--src/core/or/reasons.c (renamed from src/or/reasons.c)11
-rw-r--r--src/core/or/reasons.h (renamed from src/or/reasons.h)6
-rw-r--r--src/core/or/relay.c (renamed from src/or/relay.c)92
-rw-r--r--src/core/or/relay.h (renamed from src/or/relay.h)2
-rw-r--r--src/core/or/relay_crypto_st.h31
-rw-r--r--src/core/or/scheduler.c (renamed from src/or/scheduler.c)20
-rw-r--r--src/core/or/scheduler.h (renamed from src/or/scheduler.h)8
-rw-r--r--src/core/or/scheduler_kist.c (renamed from src/or/scheduler_kist.c)26
-rw-r--r--src/core/or/scheduler_vanilla.c (renamed from src/or/scheduler_vanilla.c)26
-rw-r--r--src/core/or/server_port_cfg_st.h20
-rw-r--r--src/core/or/socks_request_st.h75
-rw-r--r--src/core/or/status.c (renamed from src/or/status.c)61
-rw-r--r--src/core/or/status.h (renamed from src/or/status.h)4
-rw-r--r--src/core/or/tor_version_st.h32
-rw-r--r--src/core/or/var_cell_st.h23
-rw-r--r--src/core/proto/proto_cell.c (renamed from src/or/proto_cell.c)12
-rw-r--r--src/core/proto/proto_cell.h (renamed from src/or/proto_cell.h)2
-rw-r--r--src/core/proto/proto_control0.c (renamed from src/or/proto_control0.c)8
-rw-r--r--src/core/proto/proto_control0.h (renamed from src/or/proto_control0.h)2
-rw-r--r--src/core/proto/proto_ext_or.c (renamed from src/or/proto_ext_or.c)10
-rw-r--r--src/core/proto/proto_ext_or.h (renamed from src/or/proto_ext_or.h)11
-rw-r--r--src/core/proto/proto_http.c (renamed from src/or/proto_http.c)8
-rw-r--r--src/core/proto/proto_http.h (renamed from src/or/proto_http.h)2
-rw-r--r--src/core/proto/proto_socks.c (renamed from src/or/proto_socks.c)24
-rw-r--r--src/core/proto/proto_socks.h (renamed from src/or/proto_socks.h)3
-rw-r--r--src/core/proto/protover_rust.c (renamed from src/or/protover_rust.c)6
-rw-r--r--src/ext/OpenBSD_malloc_Linux.c2
-rw-r--r--src/ext/csiphash.c8
-rw-r--r--src/ext/curve25519_donna/curve25519-donna-c64.c2
-rw-r--r--src/ext/curve25519_donna/curve25519-donna.c2
-rw-r--r--src/ext/ed25519/donna/ed25519-hash-custom.h2
-rw-r--r--src/ext/ed25519/donna/ed25519-randombytes-custom.h2
-rw-r--r--src/ext/ed25519/donna/ed25519_donna_tor.h2
-rw-r--r--src/ext/ed25519/donna/ed25519_tor.c2
-rw-r--r--src/ext/ed25519/ref10/blinding.c2
-rw-r--r--src/ext/ed25519/ref10/crypto_hash_sha512.h2
-rw-r--r--src/ext/ed25519/ref10/crypto_int32.h2
-rw-r--r--src/ext/ed25519/ref10/crypto_int64.h2
-rw-r--r--src/ext/ed25519/ref10/crypto_uint32.h2
-rw-r--r--src/ext/ed25519/ref10/crypto_uint64.h2
-rw-r--r--src/ext/ed25519/ref10/crypto_verify_32.h3
-rw-r--r--src/ext/ed25519/ref10/ed25519_ref10.h2
-rw-r--r--src/ext/ed25519/ref10/keypair.c5
-rw-r--r--src/ext/ed25519/ref10/randombytes.h2
-rw-r--r--src/ext/ht.h2
-rw-r--r--src/ext/keccak-tiny/keccak-tiny-unrolled.c2
-rw-r--r--src/ext/keccak-tiny/keccak-tiny.h2
-rw-r--r--src/ext/mulodi/mulodi4.c2
-rw-r--r--src/feature/api/tor_api.c (renamed from src/or/tor_api.c)6
-rw-r--r--src/feature/api/tor_api.h (renamed from src/or/tor_api.h)2
-rw-r--r--src/feature/api/tor_api_internal.h (renamed from src/or/tor_api_internal.h)2
-rw-r--r--src/feature/client/addressmap.c (renamed from src/or/addressmap.c)28
-rw-r--r--src/feature/client/addressmap.h (renamed from src/or/addressmap.h)4
-rw-r--r--src/feature/client/bridges.c (renamed from src/or/bridges.c)33
-rw-r--r--src/feature/client/bridges.h (renamed from src/or/bridges.h)6
-rw-r--r--src/feature/client/circpathbias.c (renamed from src/or/circpathbias.c)37
-rw-r--r--src/feature/client/circpathbias.h (renamed from src/or/circpathbias.h)5
-rw-r--r--src/feature/client/dnsserv.c (renamed from src/or/dnsserv.c)26
-rw-r--r--src/feature/client/dnsserv.h (renamed from src/or/dnsserv.h)2
-rw-r--r--src/feature/client/entrynodes.c (renamed from src/or/entrynodes.c)65
-rw-r--r--src/feature/client/entrynodes.h (renamed from src/or/entrynodes.h)7
-rw-r--r--src/feature/client/transports.c (renamed from src/or/transports.c)63
-rw-r--r--src/feature/client/transports.h (renamed from src/or/transports.h)10
-rw-r--r--src/feature/control/control.c (renamed from src/or/control.c)198
-rw-r--r--src/feature/control/control.h (renamed from src/or/control.h)95
-rw-r--r--src/feature/control/control_connection_st.h46
-rw-r--r--src/feature/dirauth/dircollate.c (renamed from src/or/dirauth/dircollate.c)9
-rw-r--r--src/feature/dirauth/dircollate.h (renamed from src/or/dirauth/dircollate.h)6
-rw-r--r--src/feature/dirauth/dirvote.c (renamed from src/or/dirauth/dirvote.c)146
-rw-r--r--src/feature/dirauth/dirvote.h (renamed from src/or/dirauth/dirvote.h)6
-rw-r--r--src/feature/dirauth/keypin.c (renamed from src/or/keypin.c)40
-rw-r--r--src/feature/dirauth/keypin.h (renamed from src/or/keypin.h)4
-rw-r--r--src/feature/dirauth/mode.h (renamed from src/or/dirauth/mode.h)4
-rw-r--r--src/feature/dirauth/ns_detached_signatures_st.h22
-rw-r--r--src/feature/dirauth/shared_random.c (renamed from src/or/dirauth/shared_random.c)38
-rw-r--r--src/feature/dirauth/shared_random.h (renamed from src/or/dirauth/shared_random.h)4
-rw-r--r--src/feature/dirauth/shared_random_state.c (renamed from src/or/dirauth/shared_random_state.c)28
-rw-r--r--src/feature/dirauth/shared_random_state.h (renamed from src/or/dirauth/shared_random_state.h)11
-rw-r--r--src/feature/dirauth/vote_microdesc_hash_st.h22
-rw-r--r--src/feature/dircache/cached_dir_st.h25
-rw-r--r--src/feature/dircache/conscache.c (renamed from src/or/conscache.c)14
-rw-r--r--src/feature/dircache/conscache.h (renamed from src/or/conscache.h)13
-rw-r--r--src/feature/dircache/consdiffmgr.c (renamed from src/or/consdiffmgr.c)27
-rw-r--r--src/feature/dircache/consdiffmgr.h (renamed from src/or/consdiffmgr.h)9
-rw-r--r--src/feature/dircache/directory.c (renamed from src/or/directory.c)147
-rw-r--r--src/feature/dircache/directory.h (renamed from src/or/directory.h)119
-rw-r--r--src/feature/dircache/dirserv.c (renamed from src/or/dirserv.c)82
-rw-r--r--src/feature/dircache/dirserv.h (renamed from src/or/dirserv.h)32
-rw-r--r--src/feature/dirclient/dir_server_st.h54
-rw-r--r--src/feature/dirclient/download_status_st.h65
-rw-r--r--src/feature/dircommon/consdiff.c (renamed from src/or/consdiff.c)11
-rw-r--r--src/feature/dircommon/consdiff.h (renamed from src/or/consdiff.h)7
-rw-r--r--src/feature/dircommon/dir_connection_st.h67
-rw-r--r--src/feature/dircommon/fp_pair.c (renamed from src/or/fp_pair.c)6
-rw-r--r--src/feature/dircommon/fp_pair.h (renamed from src/or/fp_pair.h)8
-rw-r--r--src/feature/dircommon/vote_timing_st.h24
-rw-r--r--src/feature/dircommon/voting_schedule.c (renamed from src/or/voting_schedule.c)12
-rw-r--r--src/feature/dircommon/voting_schedule.h (renamed from src/or/voting_schedule.h)4
-rw-r--r--src/feature/hibernate/hibernate.c (renamed from src/or/hibernate.c)69
-rw-r--r--src/feature/hibernate/hibernate.h (renamed from src/or/hibernate.h)4
-rw-r--r--src/feature/hs/hs_cache.c (renamed from src/or/hs_cache.c)26
-rw-r--r--src/feature/hs/hs_cache.h (renamed from src/or/hs_cache.h)34
-rw-r--r--src/feature/hs/hs_cell.c (renamed from src/or/hs_cell.c)29
-rw-r--r--src/feature/hs/hs_cell.h (renamed from src/or/hs_cell.h)6
-rw-r--r--src/feature/hs/hs_circuit.c (renamed from src/or/hs_circuit.c)65
-rw-r--r--src/feature/hs/hs_circuit.h (renamed from src/or/hs_circuit.h)8
-rw-r--r--src/feature/hs/hs_circuitmap.c (renamed from src/or/hs_circuitmap.c)14
-rw-r--r--src/feature/hs/hs_circuitmap.h (renamed from src/or/hs_circuitmap.h)7
-rw-r--r--src/feature/hs/hs_client.c (renamed from src/or/hs_client.c)62
-rw-r--r--src/feature/hs/hs_client.h (renamed from src/or/hs_client.h)8
-rw-r--r--src/feature/hs/hs_common.c (renamed from src/or/hs_common.c)53
-rw-r--r--src/feature/hs/hs_common.h (renamed from src/or/hs_common.h)40
-rw-r--r--src/feature/hs/hs_config.c (renamed from src/or/hs_config.c)13
-rw-r--r--src/feature/hs/hs_config.h (renamed from src/or/hs_config.h)4
-rw-r--r--src/feature/hs/hs_control.c (renamed from src/or/hs_control.c)23
-rw-r--r--src/feature/hs/hs_control.h (renamed from src/or/hs_control.h)4
-rw-r--r--src/feature/hs/hs_descriptor.c (renamed from src/or/hs_descriptor.c)29
-rw-r--r--src/feature/hs/hs_descriptor.h (renamed from src/or/hs_descriptor.h)13
-rw-r--r--src/feature/hs/hs_ident.c (renamed from src/or/hs_ident.c)6
-rw-r--r--src/feature/hs/hs_ident.h (renamed from src/or/hs_ident.h)6
-rw-r--r--src/feature/hs/hs_intropoint.c (renamed from src/or/hs_intropoint.c)36
-rw-r--r--src/feature/hs/hs_intropoint.h (renamed from src/or/hs_intropoint.h)10
-rw-r--r--src/feature/hs/hs_service.c (renamed from src/or/hs_service.c)88
-rw-r--r--src/feature/hs/hs_service.h (renamed from src/or/hs_service.h)18
-rw-r--r--src/feature/hs/hs_stats.c (renamed from src/or/hs_stats.c)6
-rw-r--r--src/feature/hs/hs_stats.h (renamed from src/or/hs_stats.h)0
-rw-r--r--src/feature/hs/hsdir_index_st.h24
-rw-r--r--src/feature/hs_common/replaycache.c (renamed from src/or/replaycache.c)6
-rw-r--r--src/feature/hs_common/replaycache.h (renamed from src/or/replaycache.h)7
-rw-r--r--src/feature/hs_common/shared_random_client.c (renamed from src/or/shared_random_client.c)15
-rw-r--r--src/feature/hs_common/shared_random_client.h (renamed from src/or/shared_random_client.h)4
-rw-r--r--src/feature/nodelist/authority_cert_st.h32
-rw-r--r--src/feature/nodelist/desc_store_st.h39
-rw-r--r--src/feature/nodelist/document_signature_st.h29
-rw-r--r--src/feature/nodelist/extrainfo_st.h30
-rw-r--r--src/feature/nodelist/microdesc.c (renamed from src/or/microdesc.c)54
-rw-r--r--src/feature/nodelist/microdesc.h (renamed from src/or/microdesc.h)2
-rw-r--r--src/feature/nodelist/microdesc_st.h74
-rw-r--r--src/feature/nodelist/networkstatus.c (renamed from src/or/networkstatus.c)100
-rw-r--r--src/feature/nodelist/networkstatus.h (renamed from src/or/networkstatus.h)4
-rw-r--r--src/feature/nodelist/networkstatus_sr_info_st.h23
-rw-r--r--src/feature/nodelist/networkstatus_st.h101
-rw-r--r--src/feature/nodelist/networkstatus_voter_info_st.h30
-rw-r--r--src/feature/nodelist/node_st.h102
-rw-r--r--src/feature/nodelist/nodelist.c (renamed from src/or/nodelist.c)83
-rw-r--r--src/feature/nodelist/nodelist.h (renamed from src/or/nodelist.h)18
-rw-r--r--src/feature/nodelist/parsecommon.c (renamed from src/or/parsecommon.c)17
-rw-r--r--src/feature/nodelist/parsecommon.h (renamed from src/or/parsecommon.h)26
-rw-r--r--src/feature/nodelist/routerinfo_st.h108
-rw-r--r--src/feature/nodelist/routerlist.c (renamed from src/or/routerlist.c)123
-rw-r--r--src/feature/nodelist/routerlist.h (renamed from src/or/routerlist.h)92
-rw-r--r--src/feature/nodelist/routerlist_st.h40
-rw-r--r--src/feature/nodelist/routerparse.c (renamed from src/or/routerparse.c)247
-rw-r--r--src/feature/nodelist/routerparse.h (renamed from src/or/routerparse.h)24
-rw-r--r--src/feature/nodelist/routerset.c (renamed from src/or/routerset.c)27
-rw-r--r--src/feature/nodelist/routerset.h (renamed from src/or/routerset.h)5
-rw-r--r--src/feature/nodelist/routerstatus_st.h80
-rw-r--r--src/feature/nodelist/signed_descriptor_st.h61
-rw-r--r--src/feature/nodelist/torcert.c (renamed from src/or/torcert.c)24
-rw-r--r--src/feature/nodelist/torcert.h (renamed from src/or/torcert.h)13
-rw-r--r--src/feature/nodelist/vote_routerstatus_st.h41
-rw-r--r--src/feature/relay/dns.c (renamed from src/or/dns.c)40
-rw-r--r--src/feature/relay/dns.h (renamed from src/or/dns.h)4
-rw-r--r--src/feature/relay/dns_structs.h (renamed from src/or/dns_structs.h)2
-rw-r--r--src/feature/relay/ext_orport.c (renamed from src/or/ext_orport.c)25
-rw-r--r--src/feature/relay/ext_orport.h (renamed from src/or/ext_orport.h)22
-rw-r--r--src/feature/relay/router.c (renamed from src/or/router.c)87
-rw-r--r--src/feature/relay/router.h (renamed from src/or/router.h)18
-rw-r--r--src/feature/relay/routerkeys.c (renamed from src/or/routerkeys.c)27
-rw-r--r--src/feature/relay/routerkeys.h (renamed from src/or/routerkeys.h)4
-rw-r--r--src/feature/rend/rend_authorized_client_st.h18
-rw-r--r--src/feature/rend/rend_encoded_v2_service_descriptor_st.h17
-rw-r--r--src/feature/rend/rend_intro_point_st.h76
-rw-r--r--src/feature/rend/rend_service_descriptor_st.h34
-rw-r--r--src/feature/rend/rendcache.c (renamed from src/or/rendcache.c)22
-rw-r--r--src/feature/rend/rendcache.h (renamed from src/or/rendcache.h)6
-rw-r--r--src/feature/rend/rendclient.c (renamed from src/or/rendclient.c)71
-rw-r--r--src/feature/rend/rendclient.h (renamed from src/or/rendclient.h)4
-rw-r--r--src/feature/rend/rendcommon.c (renamed from src/or/rendcommon.c)53
-rw-r--r--src/feature/rend/rendcommon.h (renamed from src/or/rendcommon.h)2
-rw-r--r--src/feature/rend/rendmid.c (renamed from src/or/rendmid.c)32
-rw-r--r--src/feature/rend/rendmid.h (renamed from src/or/rendmid.h)2
-rw-r--r--src/feature/rend/rendservice.c (renamed from src/or/rendservice.c)96
-rw-r--r--src/feature/rend/rendservice.h (renamed from src/or/rendservice.h)16
-rw-r--r--src/feature/stats/geoip.c (renamed from src/or/geoip.c)30
-rw-r--r--src/feature/stats/geoip.h (renamed from src/or/geoip.h)65
-rw-r--r--src/feature/stats/rephist.c (renamed from src/or/rephist.c)174
-rw-r--r--src/feature/stats/rephist.h (renamed from src/or/rephist.h)2
-rw-r--r--src/include.am40
-rw-r--r--src/lib/arch/.may_include2
-rw-r--r--src/lib/arch/bytes.h182
-rw-r--r--src/lib/arch/include.am3
-rw-r--r--src/lib/cc/.may_include1
-rw-r--r--src/lib/cc/compat_compiler.h214
-rw-r--r--src/lib/cc/include.am4
-rw-r--r--src/lib/cc/torint.h123
-rw-r--r--src/lib/compress/.may_include12
-rw-r--r--src/lib/compress/compress.c (renamed from src/common/compress.c)32
-rw-r--r--src/lib/compress/compress.h (renamed from src/common/compress.h)14
-rw-r--r--src/lib/compress/compress_buf.c83
-rw-r--r--src/lib/compress/compress_lzma.c (renamed from src/common/compress_lzma.c)13
-rw-r--r--src/lib/compress/compress_lzma.h (renamed from src/common/compress_lzma.h)2
-rw-r--r--src/lib/compress/compress_none.c (renamed from src/common/compress_none.c)13
-rw-r--r--src/lib/compress/compress_none.h (renamed from src/common/compress_none.h)2
-rw-r--r--src/lib/compress/compress_zlib.c (renamed from src/common/compress_zlib.c)12
-rw-r--r--src/lib/compress/compress_zlib.h (renamed from src/common/compress_zlib.h)2
-rw-r--r--src/lib/compress/compress_zstd.c (renamed from src/common/compress_zstd.c)13
-rw-r--r--src/lib/compress/compress_zstd.h (renamed from src/common/compress_zstd.h)2
-rw-r--r--src/lib/compress/include.am26
-rw-r--r--src/lib/container/.may_include18
-rw-r--r--src/lib/container/bitarray.h86
-rw-r--r--src/lib/container/bloomfilt.c113
-rw-r--r--src/lib/container/bloomfilt.h41
-rw-r--r--src/lib/container/buffers.c (renamed from src/common/buffers.c)255
-rw-r--r--src/lib/container/buffers.h (renamed from src/common/buffers.h)23
-rw-r--r--src/lib/container/handles.h (renamed from src/common/handles.h)8
-rw-r--r--src/lib/container/include.am27
-rw-r--r--src/lib/container/map.c413
-rw-r--r--src/lib/container/map.h261
-rw-r--r--src/lib/container/order.c48
-rw-r--r--src/lib/container/order.h60
-rw-r--r--src/lib/container/smartlist.c839
-rw-r--r--src/lib/container/smartlist.h165
-rw-r--r--src/lib/crypt_ops/.may_include24
-rw-r--r--src/lib/crypt_ops/aes.c (renamed from src/common/aes.c)18
-rw-r--r--src/lib/crypt_ops/aes.h (renamed from src/common/aes.h)6
-rw-r--r--src/lib/crypt_ops/compat_openssl.h (renamed from src/common/compat_openssl.h)4
-rw-r--r--src/lib/crypt_ops/crypto.c509
-rw-r--r--src/lib/crypt_ops/crypto.h (renamed from src/common/crypto.h)46
-rw-r--r--src/lib/crypt_ops/crypto_curve25519.c (renamed from src/common/crypto_curve25519.c)21
-rw-r--r--src/lib/crypt_ops/crypto_curve25519.h (renamed from src/common/crypto_curve25519.h)21
-rw-r--r--src/lib/crypt_ops/crypto_dh.c511
-rw-r--r--src/lib/crypt_ops/crypto_dh.h47
-rw-r--r--src/lib/crypt_ops/crypto_digest.c (renamed from src/common/crypto_digest.c)19
-rw-r--r--src/lib/crypt_ops/crypto_digest.h (renamed from src/common/crypto_digest.h)20
-rw-r--r--src/lib/crypt_ops/crypto_ed25519.c (renamed from src/common/crypto_ed25519.c)25
-rw-r--r--src/lib/crypt_ops/crypto_ed25519.h (renamed from src/common/crypto_ed25519.h)24
-rw-r--r--src/lib/crypt_ops/crypto_format.c (renamed from src/common/crypto_format.c)27
-rw-r--r--src/lib/crypt_ops/crypto_format.h (renamed from src/common/crypto_format.h)26
-rw-r--r--src/lib/crypt_ops/crypto_hkdf.c198
-rw-r--r--src/lib/crypt_ops/crypto_hkdf.h27
-rw-r--r--src/lib/crypt_ops/crypto_openssl_mgt.c (renamed from src/common/crypto_openssl_mgt.c)13
-rw-r--r--src/lib/crypt_ops/crypto_openssl_mgt.h (renamed from src/common/crypto_openssl_mgt.h)7
-rw-r--r--src/lib/crypt_ops/crypto_pwbox.c (renamed from src/common/crypto_pwbox.c)29
-rw-r--r--src/lib/crypt_ops/crypto_pwbox.h (renamed from src/common/crypto_pwbox.h)11
-rw-r--r--src/lib/crypt_ops/crypto_rand.c (renamed from src/common/crypto_rand.c)29
-rw-r--r--src/lib/crypt_ops/crypto_rand.h (renamed from src/common/crypto_rand.h)6
-rw-r--r--src/lib/crypt_ops/crypto_rsa.c (renamed from src/common/crypto_rsa.c)50
-rw-r--r--src/lib/crypt_ops/crypto_rsa.h (renamed from src/common/crypto_rsa.h)14
-rw-r--r--src/lib/crypt_ops/crypto_s2k.c (renamed from src/common/crypto_s2k.c)20
-rw-r--r--src/lib/crypt_ops/crypto_s2k.h (renamed from src/common/crypto_s2k.h)11
-rw-r--r--src/lib/crypt_ops/crypto_util.c (renamed from src/common/crypto_util.c)30
-rw-r--r--src/lib/crypt_ops/crypto_util.h (renamed from src/common/crypto_util.h)5
-rw-r--r--src/lib/crypt_ops/digestset.c58
-rw-r--r--src/lib/crypt_ops/digestset.h29
-rw-r--r--src/lib/crypt_ops/include.am46
-rw-r--r--src/lib/ctime/.may_include5
-rw-r--r--src/lib/ctime/di_ops.c (renamed from src/common/di_ops.c)23
-rw-r--r--src/lib/ctime/di_ops.h (renamed from src/common/di_ops.h)4
-rw-r--r--src/lib/ctime/include.am25
-rw-r--r--src/lib/defs/.may_include1
-rw-r--r--src/lib/defs/dh_sizes.h13
-rw-r--r--src/lib/defs/digest_sizes.h27
-rw-r--r--src/lib/defs/include.am5
-rw-r--r--src/lib/defs/x25519_sizes.h27
-rw-r--r--src/lib/encoding/.may_include9
-rw-r--r--src/lib/encoding/binascii.c (renamed from src/common/util_format.c)69
-rw-r--r--src/lib/encoding/binascii.h (renamed from src/common/util_format.h)22
-rw-r--r--src/lib/encoding/confline.c (renamed from src/common/confline.c)199
-rw-r--r--src/lib/encoding/confline.h (renamed from src/common/confline.h)31
-rw-r--r--src/lib/encoding/cstring.c138
-rw-r--r--src/lib/encoding/cstring.h19
-rw-r--r--src/lib/encoding/include.am24
-rw-r--r--src/lib/encoding/keyval.c52
-rw-r--r--src/lib/encoding/keyval.h17
-rw-r--r--src/lib/encoding/time_fmt.c503
-rw-r--r--src/lib/encoding/time_fmt.h44
-rw-r--r--src/lib/err/.may_include3
-rw-r--r--src/lib/err/backtrace.c (renamed from src/common/backtrace.c)105
-rw-r--r--src/lib/err/backtrace.h (renamed from src/common/backtrace.h)20
-rw-r--r--src/lib/err/include.am19
-rw-r--r--src/lib/err/torerr.c238
-rw-r--r--src/lib/err/torerr.h47
-rw-r--r--src/lib/evloop/.may_include16
-rw-r--r--src/lib/evloop/compat_libevent.c (renamed from src/common/compat_libevent.c)15
-rw-r--r--src/lib/evloop/compat_libevent.h (renamed from src/common/compat_libevent.h)7
-rw-r--r--src/lib/evloop/include.am26
-rw-r--r--src/lib/evloop/procmon.c (renamed from src/common/procmon.c)16
-rw-r--r--src/lib/evloop/procmon.h (renamed from src/common/procmon.h)7
-rw-r--r--src/lib/evloop/timers.c (renamed from src/common/timers.c)20
-rw-r--r--src/lib/evloop/timers.h (renamed from src/common/timers.h)4
-rw-r--r--src/lib/evloop/token_bucket.c (renamed from src/common/token_bucket.c)11
-rw-r--r--src/lib/evloop/token_bucket.h (renamed from src/common/token_bucket.h)6
-rw-r--r--src/lib/evloop/workqueue.c (renamed from src/common/workqueue.c)22
-rw-r--r--src/lib/evloop/workqueue.h (renamed from src/common/workqueue.h)5
-rw-r--r--src/lib/fdio/.may_include4
-rw-r--r--src/lib/fdio/fdio.c115
-rw-r--r--src/lib/fdio/fdio.h23
-rw-r--r--src/lib/fdio/include.am17
-rw-r--r--src/lib/fs/.may_include13
-rw-r--r--src/lib/fs/conffile.c174
-rw-r--r--src/lib/fs/conffile.h23
-rw-r--r--src/lib/fs/dir.c367
-rw-r--r--src/lib/fs/dir.h33
-rw-r--r--src/lib/fs/files.c717
-rw-r--r--src/lib/fs/files.h106
-rw-r--r--src/lib/fs/freespace.c62
-rw-r--r--src/lib/fs/include.am37
-rw-r--r--src/lib/fs/lockfile.c145
-rw-r--r--src/lib/fs/lockfile.h20
-rw-r--r--src/lib/fs/mmap.c240
-rw-r--r--src/lib/fs/mmap.h41
-rw-r--r--src/lib/fs/path.c295
-rw-r--r--src/lib/fs/path.h30
-rw-r--r--src/lib/fs/storagedir.c (renamed from src/common/storagedir.c)40
-rw-r--r--src/lib/fs/storagedir.h (renamed from src/common/storagedir.h)20
-rw-r--r--src/lib/fs/userdb.c138
-rw-r--r--src/lib/fs/userdb.h26
-rw-r--r--src/lib/fs/winlib.c30
-rw-r--r--src/lib/fs/winlib.h22
-rw-r--r--src/lib/include.libdonna.am24
-rw-r--r--src/lib/intmath/.may_include4
-rw-r--r--src/lib/intmath/addsub.c28
-rw-r--r--src/lib/intmath/addsub.h19
-rw-r--r--src/lib/intmath/bits.c94
-rw-r--r--src/lib/intmath/bits.h22
-rw-r--r--src/lib/intmath/cmp.h39
-rw-r--r--src/lib/intmath/include.am25
-rw-r--r--src/lib/intmath/logic.h20
-rw-r--r--src/lib/intmath/muldiv.c81
-rw-r--r--src/lib/intmath/muldiv.h28
-rw-r--r--src/lib/intmath/weakrng.c60
-rw-r--r--src/lib/intmath/weakrng.h31
-rw-r--r--src/lib/lock/.may_include5
-rw-r--r--src/lib/lock/compat_mutex.c40
-rw-r--r--src/lib/lock/compat_mutex.h66
-rw-r--r--src/lib/lock/compat_mutex_pthreads.c103
-rw-r--r--src/lib/lock/compat_mutex_winthreads.c46
-rw-r--r--src/lib/lock/include.am24
-rw-r--r--src/lib/log/.may_include15
-rw-r--r--src/lib/log/escape.c132
-rw-r--r--src/lib/log/escape.h18
-rw-r--r--src/lib/log/include.am31
-rw-r--r--src/lib/log/ratelim.c55
-rw-r--r--src/lib/log/ratelim.h48
-rw-r--r--src/lib/log/torlog.c (renamed from src/common/log.c)165
-rw-r--r--src/lib/log/torlog.h (renamed from src/common/torlog.h)17
-rw-r--r--src/lib/log/util_bug.c (renamed from src/common/util_bug.c)42
-rw-r--r--src/lib/log/util_bug.h (renamed from src/common/util_bug.h)16
-rw-r--r--src/lib/log/win32err.c56
-rw-r--r--src/lib/log/win32err.h17
-rw-r--r--src/lib/malloc/.may_include6
-rw-r--r--src/lib/malloc/include.am21
-rw-r--r--src/lib/malloc/util_malloc.c230
-rw-r--r--src/lib/malloc/util_malloc.h92
-rw-r--r--src/lib/math/.may_include5
-rw-r--r--src/lib/math/fp.c119
-rw-r--r--src/lib/math/fp.h23
-rw-r--r--src/lib/math/include.am20
-rw-r--r--src/lib/math/laplace.c73
-rw-r--r--src/lib/math/laplace.h22
-rw-r--r--src/lib/memarea/.may_include7
-rw-r--r--src/lib/memarea/include.am17
-rw-r--r--src/lib/memarea/memarea.c (renamed from src/common/memarea.c)23
-rw-r--r--src/lib/memarea/memarea.h (renamed from src/common/memarea.h)12
-rw-r--r--src/lib/meminfo/.may_include8
-rw-r--r--src/lib/meminfo/include.am17
-rw-r--r--src/lib/meminfo/meminfo.c180
-rw-r--r--src/lib/meminfo/meminfo.h21
-rw-r--r--src/lib/net/.may_include14
-rw-r--r--src/lib/net/address.c (renamed from src/common/address.c)189
-rw-r--r--src/lib/net/address.h (renamed from src/common/address.h)56
-rw-r--r--src/lib/net/alertsock.c (renamed from src/common/compat_threads.c)148
-rw-r--r--src/lib/net/alertsock.h45
-rw-r--r--src/lib/net/buffers_net.c197
-rw-r--r--src/lib/net/buffers_net.h27
-rw-r--r--src/lib/net/gethostname.c25
-rw-r--r--src/lib/net/gethostname.h14
-rw-r--r--src/lib/net/include.am33
-rw-r--r--src/lib/net/ipv4.c52
-rw-r--r--src/lib/net/ipv4.h17
-rw-r--r--src/lib/net/ipv6.c221
-rw-r--r--src/lib/net/ipv6.h86
-rw-r--r--src/lib/net/nettypes.h39
-rw-r--r--src/lib/net/resolve.c236
-rw-r--r--src/lib/net/resolve.h47
-rw-r--r--src/lib/net/socket.c824
-rw-r--r--src/lib/net/socket.h120
-rw-r--r--src/lib/net/socks5_status.h22
-rw-r--r--src/lib/osinfo/.may_include5
-rw-r--r--src/lib/osinfo/include.am17
-rw-r--r--src/lib/osinfo/uname.c111
-rw-r--r--src/lib/osinfo/uname.h9
-rw-r--r--src/lib/process/.may_include17
-rw-r--r--src/lib/process/daemon.c159
-rw-r--r--src/lib/process/daemon.h12
-rw-r--r--src/lib/process/env.c219
-rw-r--r--src/lib/process/env.h36
-rw-r--r--src/lib/process/include.am29
-rw-r--r--src/lib/process/pidfile.c47
-rw-r--r--src/lib/process/pidfile.h11
-rw-r--r--src/lib/process/restrict.c280
-rw-r--r--src/lib/process/restrict.h27
-rw-r--r--src/lib/process/setuid.c381
-rw-r--r--src/lib/process/setuid.h17
-rw-r--r--src/lib/process/subprocess.c1231
-rw-r--r--src/lib/process/subprocess.h129
-rw-r--r--src/lib/process/waitpid.c (renamed from src/common/util_process.c)22
-rw-r--r--src/lib/process/waitpid.h (renamed from src/common/util_process.h)17
-rw-r--r--src/lib/sandbox/.may_include15
-rw-r--r--src/lib/sandbox/include.am18
-rw-r--r--src/lib/sandbox/linux_syscalls.inc (renamed from src/common/linux_syscalls.inc)0
-rw-r--r--src/lib/sandbox/sandbox.c (renamed from src/common/sandbox.c)205
-rw-r--r--src/lib/sandbox/sandbox.h (renamed from src/common/sandbox.h)28
-rw-r--r--src/lib/smartlist_core/.may_include7
-rw-r--r--src/lib/smartlist_core/include.am21
-rw-r--r--src/lib/smartlist_core/smartlist_core.c234
-rw-r--r--src/lib/smartlist_core/smartlist_core.h95
-rw-r--r--src/lib/smartlist_core/smartlist_foreach.h128
-rw-r--r--src/lib/smartlist_core/smartlist_split.c87
-rw-r--r--src/lib/smartlist_core/smartlist_split.h15
-rw-r--r--src/lib/string/.may_include10
-rw-r--r--src/lib/string/compat_ctype.c67
-rw-r--r--src/lib/string/compat_ctype.h62
-rw-r--r--src/lib/string/compat_string.c68
-rw-r--r--src/lib/string/compat_string.h57
-rw-r--r--src/lib/string/include.am27
-rw-r--r--src/lib/string/parse_int.c126
-rw-r--r--src/lib/string/parse_int.h20
-rw-r--r--src/lib/string/printf.c152
-rw-r--r--src/lib/string/printf.h25
-rw-r--r--src/lib/string/scanf.c312
-rw-r--r--src/lib/string/scanf.h19
-rw-r--r--src/lib/string/util_string.c448
-rw-r--r--src/lib/string/util_string.h50
-rw-r--r--src/lib/term/.may_include9
-rw-r--r--src/lib/term/getpass.c115
-rw-r--r--src/lib/term/getpass.h13
-rw-r--r--src/lib/term/include.am24
-rw-r--r--src/lib/testsupport/.may_include0
-rw-r--r--src/lib/testsupport/include.am3
-rw-r--r--src/lib/testsupport/testsupport.h (renamed from src/common/testsupport.h)2
-rw-r--r--src/lib/thread/.may_include6
-rw-r--r--src/lib/thread/compat_pthreads.c (renamed from src/common/compat_pthreads.c)99
-rw-r--r--src/lib/thread/compat_threads.c111
-rw-r--r--src/lib/thread/compat_winthreads.c (renamed from src/common/compat_winthreads.c)38
-rw-r--r--src/lib/thread/include.am27
-rw-r--r--src/lib/thread/numcpus.c93
-rw-r--r--src/lib/thread/numcpus.h11
-rw-r--r--src/lib/thread/threads.h (renamed from src/common/compat_threads.h)74
-rw-r--r--src/lib/time/.may_include11
-rw-r--r--src/lib/time/compat_time.c (renamed from src/common/compat_time.c)76
-rw-r--r--src/lib/time/compat_time.h (renamed from src/common/compat_time.h)9
-rw-r--r--src/lib/time/include.am19
-rw-r--r--src/lib/time/tvdiff.c162
-rw-r--r--src/lib/time/tvdiff.h16
-rw-r--r--src/lib/tls/.may_include16
-rw-r--r--src/lib/tls/buffers_tls.c (renamed from src/common/buffers_tls.c)18
-rw-r--r--src/lib/tls/buffers_tls.h (renamed from src/common/buffers_tls.h)2
-rw-r--r--src/lib/tls/ciphers.inc (renamed from src/common/ciphers.inc)0
-rw-r--r--src/lib/tls/include.am20
-rw-r--r--src/lib/tls/tortls.c (renamed from src/common/tortls.c)38
-rw-r--r--src/lib/tls/tortls.h (renamed from src/common/tortls.h)10
-rw-r--r--src/lib/trace/.may_include3
-rw-r--r--src/lib/trace/debug.h (renamed from src/trace/debug.h)4
-rw-r--r--src/lib/trace/events.h (renamed from src/trace/events.h)4
-rw-r--r--src/lib/trace/include.am18
-rw-r--r--src/lib/trace/trace.c (renamed from src/trace/trace.c)4
-rw-r--r--src/lib/trace/trace.h (renamed from src/trace/trace.h)2
-rw-r--r--src/lib/wallclock/.may_include6
-rw-r--r--src/lib/wallclock/approx_time.c38
-rw-r--r--src/lib/wallclock/approx_time.h20
-rw-r--r--src/lib/wallclock/include.am22
-rw-r--r--src/lib/wallclock/timeval.c0
-rw-r--r--src/lib/wallclock/timeval.h58
-rw-r--r--src/lib/wallclock/tm_cvt.c195
-rw-r--r--src/lib/wallclock/tm_cvt.h17
-rw-r--r--src/lib/wallclock/tor_gettimeofday.c82
-rw-r--r--src/lib/wallclock/tor_gettimeofday.h15
-rw-r--r--src/or/Makefile.nmake79
-rw-r--r--src/or/circuitlist.h98
-rw-r--r--src/or/hs_ntor.h67
-rw-r--r--src/or/include.am320
-rw-r--r--src/or/or.h5534
-rw-r--r--src/rust/build.rs25
-rw-r--r--src/rust/external/external.rs4
-rw-r--r--src/rust/protover/ffi.rs6
-rw-r--r--src/rust/protover/lib.rs2
-rw-r--r--src/rust/protover/protover.rs14
-rw-r--r--src/rust/protover/tests/protover.rs2
-rw-r--r--src/rust/smartlist/lib.rs2
-rw-r--r--src/rust/smartlist/smartlist.rs2
-rw-r--r--src/rust/tor_allocate/lib.rs2
-rw-r--r--src/rust/tor_allocate/tor_allocate.rs2
-rw-r--r--src/rust/tor_log/lib.rs2
-rw-r--r--src/rust/tor_log/tor_log.rs4
-rw-r--r--src/rust/tor_rust/include.am8
-rw-r--r--src/rust/tor_util/ffi.rs2
-rw-r--r--src/rust/tor_util/lib.rs2
-rw-r--r--src/rust/tor_util/strings.rs2
-rw-r--r--src/test/bench.c51
-rwxr-xr-xsrc/test/bt_test.py2
-rw-r--r--src/test/ed25519_exts_ref.py2
-rw-r--r--src/test/fakechans.h2
-rw-r--r--src/test/fuzz/dict/http2
-rw-r--r--src/test/fuzz/fuzz_consensus.c13
-rw-r--r--src/test/fuzz/fuzz_descriptor.c12
-rw-r--r--src/test/fuzz/fuzz_diff.c8
-rw-r--r--src/test/fuzz/fuzz_diff_apply.c8
-rw-r--r--src/test/fuzz/fuzz_extrainfo.c12
-rw-r--r--src/test/fuzz/fuzz_hsdescv2.c12
-rw-r--r--src/test/fuzz/fuzz_hsdescv3.c15
-rw-r--r--src/test/fuzz/fuzz_http.c20
-rw-r--r--src/test/fuzz/fuzz_http_connect.c23
-rw-r--r--src/test/fuzz/fuzz_iptsv2.c15
-rw-r--r--src/test/fuzz/fuzz_microdesc.c13
-rw-r--r--src/test/fuzz/fuzz_vrs.c20
-rw-r--r--src/test/fuzz/fuzzing.h2
-rw-r--r--src/test/fuzz/fuzzing_common.c16
-rw-r--r--src/test/fuzz/include.am20
-rwxr-xr-xsrc/test/fuzz_static_testcases.sh2
-rw-r--r--src/test/hs_ntor_ref.py2
-rw-r--r--src/test/hs_test_helpers.c14
-rw-r--r--src/test/hs_test_helpers.h6
-rw-r--r--src/test/include.am97
-rw-r--r--src/test/log_test_helpers.c6
-rw-r--r--src/test/log_test_helpers.h4
-rwxr-xr-xsrc/test/ntor_ref.py2
-rw-r--r--src/test/rend_test_helpers.c16
-rw-r--r--src/test/rend_test_helpers.h4
-rw-r--r--src/test/test-child.c2
-rw-r--r--src/test/test-memwipe.c12
-rwxr-xr-xsrc/test/test-network.sh4
-rw-r--r--src/test/test-timers.c18
-rw-r--r--src/test/test.c62
-rw-r--r--src/test/test.h27
-rw-r--r--src/test/test_accounting.c15
-rw-r--r--src/test/test_addr.c17
-rw-r--r--src/test/test_address.c10
-rw-r--r--src/test/test_address_set.c27
-rw-r--r--src/test/test_bridges.c17
-rw-r--r--src/test/test_bt_cl.c14
-rw-r--r--src/test/test_buffers.c19
-rw-r--r--src/test/test_bwmgt.c8
-rw-r--r--src/test/test_cell_formats.c32
-rw-r--r--src/test/test_cell_queue.c15
-rw-r--r--src/test/test_channel.c36
-rw-r--r--src/test/test_channelpadding.c39
-rw-r--r--src/test/test_channeltls.c28
-rw-r--r--src/test/test_checkdir.c14
-rw-r--r--src/test/test_circuitbuild.c18
-rw-r--r--src/test/test_circuitlist.c24
-rw-r--r--src/test/test_circuitmux.c20
-rw-r--r--src/test/test_circuitstats.c27
-rw-r--r--src/test/test_circuituse.c21
-rw-r--r--src/test/test_compat_libevent.c10
-rw-r--r--src/test/test_config.c129
-rw-r--r--src/test/test_connection.c40
-rw-r--r--src/test/test_connection.h2
-rw-r--r--src/test/test_conscache.c12
-rw-r--r--src/test/test_consdiff.c12
-rw-r--r--src/test/test_consdiffmgr.c31
-rw-r--r--src/test/test_containers.c21
-rw-r--r--src/test/test_controller.c105
-rw-r--r--src/test/test_controller_events.c19
-rw-r--r--src/test/test_crypto.c142
-rw-r--r--src/test/test_crypto_openssl.c15
-rw-r--r--src/test/test_crypto_slow.c15
-rw-r--r--src/test/test_data.c4
-rw-r--r--src/test/test_dir.c88
-rw-r--r--src/test/test_dir_common.c24
-rw-r--r--src/test/test_dir_common.h8
-rw-r--r--src/test/test_dir_handle_get.c57
-rw-r--r--src/test/test_dns.c17
-rw-r--r--src/test/test_dos.c29
-rw-r--r--src/test/test_entryconn.c28
-rw-r--r--src/test/test_entrynodes.c60
-rw-r--r--src/test/test_extorport.c30
-rw-r--r--src/test/test_geoip.c9
-rw-r--r--src/test/test_guardfraction.c28
-rw-r--r--src/test/test_handles.c11
-rw-r--r--src/test/test_helpers.c42
-rw-r--r--src/test/test_helpers.h4
-rw-r--r--src/test/test_hs.c34
-rw-r--r--src/test/test_hs_cache.c27
-rw-r--r--src/test/test_hs_cell.c20
-rw-r--r--src/test/test_hs_client.c65
-rw-r--r--src/test/test_hs_common.c52
-rw-r--r--src/test/test_hs_config.c18
-rw-r--r--src/test/test_hs_control.c34
-rw-r--r--src/test/test_hs_descriptor.c26
-rw-r--r--src/test/test_hs_intropoint.c36
-rw-r--r--src/test/test_hs_ntor.c13
-rw-r--r--src/test/test_hs_ntor_cl.c17
-rw-r--r--src/test/test_hs_service.c74
-rw-r--r--src/test/test_introduce.c10
-rw-r--r--src/test/test_keypin.c9
-rw-r--r--src/test/test_link_handshake.c34
-rw-r--r--src/test/test_logging.c20
-rw-r--r--src/test/test_mainloop.c12
-rw-r--r--src/test/test_microdesc.c32
-rw-r--r--src/test/test_nodelist.c21
-rw-r--r--src/test/test_ntor_cl.c12
-rw-r--r--src/test/test_oom.c27
-rw-r--r--src/test/test_oos.c19
-rw-r--r--src/test/test_options.c31
-rw-r--r--src/test/test_periodic_event.c18
-rw-r--r--src/test/test_policy.c22
-rw-r--r--src/test/test_procmon.c10
-rw-r--r--src/test/test_proto_http.c12
-rw-r--r--src/test/test_proto_misc.c20
-rw-r--r--src/test/test_protover.c10
-rw-r--r--src/test/test_pt.c25
-rw-r--r--src/test/test_pubsub.c85
-rw-r--r--src/test/test_relay.c19
-rw-r--r--src/test/test_relaycell.c28
-rw-r--r--src/test/test_relaycrypt.c19
-rw-r--r--src/test/test_rendcache.c27
-rw-r--r--src/test/test_replay.c8
-rw-r--r--src/test/test_router.c21
-rw-r--r--src/test/test_routerkeys.c26
-rw-r--r--src/test/test_routerlist.c59
-rw-r--r--src/test/test_routerset.c24
-rw-r--r--src/test/test_scheduler.c22
-rw-r--r--src/test/test_shared_random.c41
-rw-r--r--src/test/test_slow.c6
-rw-r--r--src/test/test_socks.c18
-rw-r--r--src/test/test_status.c37
-rw-r--r--src/test/test_storagedir.c12
-rw-r--r--src/test/test_switch_id.c9
-rw-r--r--src/test/test_threads.c8
-rw-r--r--src/test/test_tortls.c18
-rw-r--r--src/test/test_util.c115
-rw-r--r--src/test/test_util_format.c14
-rw-r--r--src/test/test_util_process.c10
-rw-r--r--src/test/test_util_slow.c19
-rw-r--r--src/test/test_voting_schedule.c6
-rw-r--r--src/test/test_workqueue.c19
-rwxr-xr-xsrc/test/test_zero_length_keys.sh6
-rw-r--r--src/test/testing_common.c48
-rw-r--r--src/test/testing_rsakeys.c8
-rw-r--r--src/tools/include.am33
-rw-r--r--src/tools/tor-gencert.c56
-rw-r--r--src/tools/tor-resolve.c39
-rw-r--r--src/tools/tor_runner.c6
-rw-r--r--src/trace/include.am22
-rw-r--r--src/trunnel/include.am6
-rw-r--r--src/trunnel/trunnel-local.h6
-rw-r--r--src/win32/orconfig.h2
805 files changed, 32631 insertions, 27831 deletions
diff --git a/.gitignore b/.gitignore
index b3b13694af..80c039a684 100644
--- a/.gitignore
+++ b/.gitignore
@@ -132,24 +132,6 @@ uptime-*.json
# /src/trace
/src/trace/libor-trace.a
-# /src/common/
-/src/common/Makefile
-/src/common/Makefile.in
-/src/common/libor.a
-/src/common/libor-testing.a
-/src/common/libor.lib
-/src/common/libor-ctime.a
-/src/common/libor-ctime-testing.a
-/src/common/libor-ctime.lib
-/src/common/libor-crypto.a
-/src/common/libor-crypto-testing.a
-/src/common/libor-crypto.lib
-/src/common/libor-event.a
-/src/common/libor-event-testing.a
-/src/common/libor-event.lib
-/src/common/libcurve25519_donna.a
-/src/common/libcurve25519_donna.lib
-
# /src/config/
/src/config/Makefile
/src/config/Makefile.in
@@ -166,16 +148,73 @@ uptime-*.json
/src/ext/keccak-tiny/libkeccak-tiny.a
/src/ext/keccak-tiny/libkeccak-tiny.lib
-# /src/or/
-/src/or/Makefile
-/src/or/Makefile.in
-/src/or/tor
-/src/or/tor.exe
-/src/or/tor-cov
-/src/or/tor-cov.exe
-/src/or/libtor.a
-/src/or/libtor-testing.a
-/src/or/libtor.lib
+# /src/lib
+/src/lib/libcurve25519_donna.a
+/src/lib/libtor-compress.a
+/src/lib/libtor-compress-testing.a
+/src/lib/libtor-container.a
+/src/lib/libtor-container-testing.a
+/src/lib/libtor-crypt-ops.a
+/src/lib/libtor-crypt-ops-testing.a
+/src/lib/libtor-ctime.a
+/src/lib/libtor-ctime-testing.a
+/src/lib/libtor-encoding.a
+/src/lib/libtor-encoding-testing.a
+/src/lib/libtor-evloop.a
+/src/lib/libtor-evloop-testing.a
+/src/lib/libtor-err.a
+/src/lib/libtor-err-testing.a
+/src/lib/libtor-fdio.a
+/src/lib/libtor-fdio-testing.a
+/src/lib/libtor-fs.a
+/src/lib/libtor-fs-testing.a
+/src/lib/libtor-intmath.a
+/src/lib/libtor-intmath-testing.a
+/src/lib/libtor-lock.a
+/src/lib/libtor-lock-testing.a
+/src/lib/libtor-log.a
+/src/lib/libtor-log-testing.a
+/src/lib/libtor-malloc.a
+/src/lib/libtor-malloc-testing.a
+/src/lib/libtor-math.a
+/src/lib/libtor-math-testing.a
+/src/lib/libtor-memarea.a
+/src/lib/libtor-memarea-testing.a
+/src/lib/libtor-meminfo.a
+/src/lib/libtor-meminfo-testing.a
+/src/lib/libtor-net.a
+/src/lib/libtor-net-testing.a
+/src/lib/libtor-osinfo.a
+/src/lib/libtor-osinfo-testing.a
+/src/lib/libtor-process.a
+/src/lib/libtor-process-testing.a
+/src/lib/libtor-sandbox.a
+/src/lib/libtor-sandbox-testing.a
+/src/lib/libtor-string.a
+/src/lib/libtor-string-testing.a
+/src/lib/libtor-smartlist-core.a
+/src/lib/libtor-smartlist-core-testing.a
+/src/lib/libtor-term.a
+/src/lib/libtor-term-testing.a
+/src/lib/libtor-thread.a
+/src/lib/libtor-thread-testing.a
+/src/lib/libtor-time.a
+/src/lib/libtor-time-testing.a
+/src/lib/libtor-tls.a
+/src/lib/libtor-tls-testing.a
+/src/lib/libtor-trace.a
+/src/lib/libtor-wallclock.a
+/src/lib/libtor-wallclock-testing.a
+
+# /src/tor
+/src/core/libtor-app.a
+/src/core/libtor-app-testing.a
+
+# /src/app
+/src/app/tor
+/src/app/tor.exe
+/src/app/tor-cov
+/src/app/tor-cov.exe
# /src/rust
/src/rust/.cargo/config
diff --git a/.travis.yml b/.travis.yml
index 2661a69323..cb00b0393c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -42,11 +42,12 @@ addons:
packages:
## Required dependencies
- libevent-dev
- - libseccomp2
- zlib1g-dev
## Optional dependencies
+ - libcap-dev
- liblzma-dev
- libscrypt-dev
+ - libseccomp-dev
## zstd doesn't exist in Ubuntu Trusty
#- libzstd
diff --git a/CODE_OF_CONDUCT b/CODE_OF_CONDUCT
new file mode 100644
index 0000000000..d8d160a22a
--- /dev/null
+++ b/CODE_OF_CONDUCT
@@ -0,0 +1,7 @@
+The Tor Project is committed to fostering a inclusive community
+where people feel safe to engage, share their points of view, and
+participate. For the latest version of our Code of Conduct, please
+see
+
+https://gitweb.torproject.org/community/policies.git/plain/code_of_conduct.txt
+
diff --git a/ChangeLog b/ChangeLog
index 60583ac7f3..5d2c6e6ec8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,72 @@
+Changes in version 0.3.4.3-alpha - 2018-06-26
+ Tor 0.3.4.3-alpha fixes several bugs in earlier versions, including
+ one that was causing stability issues on directory authorities.
+
+ o Major bugfixes (directory authority):
+ - Stop leaking memory on directory authorities when planning to
+ vote. This bug was crashing authorities by exhausting their
+ memory. Fixes bug 26435; bugfix on 0.3.3.6.
+
+ o Major bugfixes (rust, testing):
+ - Make sure that failing tests in Rust will actually cause the build
+ to fail: previously, they were ignored. Fixes bug 26258; bugfix
+ on 0.3.3.4-alpha.
+
+ o Minor feature (directory authorities):
+ - Stop warning about incomplete bw lines before the first complete
+ bw line has been found, so that additional header lines can be
+ ignored. Fixes bug 25960; bugfix on 0.2.2.1-alpha
+
+ o Minor features (relay, diagnostic):
+ - Add several checks to detect whether Tor relays are uploading
+ their descriptors without specifying why they regenerated them.
+ Diagnostic for ticket 25686.
+
+ o Minor features (unit tests):
+ - Test complete bandwidth measurements files, and test that
+ incomplete bandwidth lines only give warnings when the end of the
+ header has not been detected. Fixes bug 25947; bugfix
+ on 0.2.2.1-alpha
+
+ o Minor bugfixes (compilation):
+ - Refrain from compiling unit testing related object files when
+ --disable-unittests is set to configure script. Fixes bug 24891;
+ bugfix on 0.2.5.1-alpha.
+ - When linking the libtor_testing.a library, only include the
+ dirauth object files once. Previously, they were getting added
+ twice. Fixes bug 26402; bugfix on 0.3.4.1-alpha.
+ - The --enable-fatal-warnings flag now affects Rust code as well.
+ Closes ticket 26245.
+
+ o Minor bugfixes (onion services):
+ - Recompute some consensus information after detecting a clock jump,
+ or after transitioning from a non-live consensus to a live
+ consensus. We do this to avoid having an outdated state, and
+ miscalculating the index for next-generation onion services. Fixes
+ bug 24977; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (relay):
+ - Relays now correctly block attempts to re-extend to the previous
+ relay by Ed25519 identity. Previously they would warn in this
+ case, but not actually reject the attempt. Fixes bug 26158; bugfix
+ on 0.3.0.1-alpha.
+
+ o Minor bugfixes (testing):
+ - Fix compilation of the doctests in the Rust crypto crate. Fixes
+ bug 26415; bugfix on 0.3.4.1-alpha.
+ - Instead of trying to read the geoip configuration files from
+ within the unit tests, instead create our own ersatz files with
+ just enough geoip data in the format we expect. Trying to read
+ from the source directory created problems on Windows with mingw,
+ where the build system's paths are not the same as the platform's
+ paths. Fixes bug 25787; bugfix on 0.3.4.1-alpha.
+ - Refrain from trying to get an item from an empty smartlist in
+ test_bridges_clear_bridge_list. Set DEBUG_SMARTLIST in unit tests
+ to catch improper smartlist usage. Furthermore, enable
+ DEBUG_SMARTLIST globally when build is configured with fragile
+ hardening. Fixes bug 26196; bugfix on 0.3.4.1-alpha.
+
+
Changes in version 0.3.3.7 - 2018-06-12
Tor 0.3.3.7 backports several changes from the 0.3.4.x series, including
fixes for bugs affecting compatibility and stability.
@@ -28476,4 +28545,3 @@ Changes in version 0.0.2pre13 - 2003-10-19
- If --DebugLogFile is specified, log to it at -l debug
- If --LogFile is specified, use it instead of commandline
- If --RunAsDaemon is set, tor forks and backgrounds on startup
-
diff --git a/Doxyfile.in b/Doxyfile.in
index 4cf9c30ded..8d8b959fb3 100644
--- a/Doxyfile.in
+++ b/Doxyfile.in
@@ -14,211 +14,211 @@
# Project related configuration options
#---------------------------------------------------------------------------
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all
-# text before the first occurrence of this tag. Doxygen uses libiconv (or the
-# iconv built into libc) for the transcoding. See
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
# http://www.gnu.org/software/libiconv for the list of possible encodings.
DOXYFILE_ENCODING = UTF-8
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
PROJECT_NAME = tor
-# The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = @VERSION@
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
-# base path where the generated documentation will be put.
-# If a relative path is entered, it will be relative to the location
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = @top_builddir@/doc/doxygen
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
-# 4096 sub-directories (in 2 levels) under the output directory of each output
-# format and will distribute the generated files over these directories.
-# Enabling this option can be useful when feeding doxygen a huge amount of
-# source files, where putting all generated files in the same directory would
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
# otherwise cause performance problems for the file system.
CREATE_SUBDIRS = NO
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all
-# documentation generated by doxygen is written. Doxygen will use this
-# information to generate all constant output in the proper language.
-# The default language is English, other supported languages are:
-# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
-# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
-# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
-# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
-# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
+# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
# and Ukrainian.
OUTPUT_LANGUAGE = English
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in
-# the file and class documentation (similar to JavaDoc).
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
# Set to NO to disable this.
BRIEF_MEMBER_DESC = NO
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
-# the brief description of a member or function before the detailed description.
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
REPEAT_BRIEF = YES
-# This tag implements a quasi-intelligent brief description abbreviator
-# that is used to form the text in various listings. Each string
-# in this list, if found as the leading text of the brief description, will be
-# stripped from the text and the result after processing the whole list, is
-# used as the annotated text. Otherwise, the brief description is used as-is.
-# If left blank, the following values are used ("$name" is automatically
-# replaced with the name of the entity): "The $name class" "The $name widget"
-# "The $name file" "is" "provides" "specifies" "contains"
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
# "represents" "a" "an" "the"
-ABBREVIATE_BRIEF =
+ABBREVIATE_BRIEF =
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# Doxygen will generate a detailed section even if there is only a brief
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
# description.
ALWAYS_DETAILED_SEC = NO
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
-# inherited members of a class in the documentation of that class as if those
-# members were ordinary class members. Constructors, destructors and assignment
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
INLINE_INHERITED_MEMB = NO
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
-# path before files name in the file list and in the header files. If set
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
FULL_PATH_NAMES = NO
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user-defined part of the path. Stripping is
-# only done if one of the specified strings matches the left-hand part of
-# the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
# path to strip.
-STRIP_FROM_PATH =
+STRIP_FROM_PATH =
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
-# the path mentioned in the documentation of a class, which tells
-# the reader which header file to include in order to use a class.
-# If left blank only the name of the header file containing the class
-# definition is used. Otherwise one should specify the include paths that
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
# are normally passed to the compiler using the -I flag.
-STRIP_FROM_INC_PATH =
+STRIP_FROM_INC_PATH =
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful is your file systems
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
# doesn't support long names like on DOS, Mac, or CD-ROM.
SHORT_NAMES = NO
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like regular Qt-style comments
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
# (thus requiring an explicit @brief command for a brief description.)
JAVADOC_AUTOBRIEF = NO
-# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
-# interpret the first line (until the first dot) of a Qt-style
-# comment as the brief description. If set to NO, the comments
-# will behave just like regular Qt-style comments (thus requiring
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
# an explicit \brief command for a brief description.)
QT_AUTOBRIEF = NO
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
-# treat a multi-line C++ special comment block (i.e. a block of //! or ///
-# comments) as a brief description. This used to be the default behaviour.
-# The new default is to treat a multi-line C++ comment block as a detailed
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
# description. Set this tag to YES if you prefer the old behaviour instead.
MULTILINE_CPP_IS_BRIEF = NO
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
# will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member
+# If set to NO, the detailed description appears after the member
# documentation.
# DETAILS_AT_TOP = NO
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
# re-implements.
INHERIT_DOCS = YES
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
-# a new page for each member. If set to NO, the documentation of a member will
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
# be part of the file/class/namespace that contains it.
SEPARATE_MEMBER_PAGES = NO
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
TAB_SIZE = 8
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user-defined paragraph with heading "Side Effects:".
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
# You can put \n's in the value part of an alias to insert newlines.
-ALIASES =
+ALIASES =
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
-# sources only. Doxygen will then generate output that is more tailored for C.
-# For instance, some of the names that are used will be different. The list
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
# of all members will be omitted, etc.
OPTIMIZE_OUTPUT_FOR_C = YES
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
-# sources only. Doxygen will then generate output that is more tailored for
-# Java. For instance, namespaces will be presented as packages, qualified
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
# scopes will look different, etc.
OPTIMIZE_OUTPUT_JAVA = NO
-# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
-# sources only. Doxygen will then generate output that is more tailored for
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
# Fortran.
OPTIMIZE_FOR_FORTRAN = NO
-# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
-# sources. Doxygen will then generate output that is tailored for
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
# VHDL.
OPTIMIZE_OUTPUT_VHDL = NO
-# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
-# to include (a tag file for) the STL sources as input, then you should
-# set this tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
-# func(std::string) {}). This also make the inheritance and collaboration
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
BUILTIN_STL_SUPPORT = NO
@@ -228,42 +228,42 @@ BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
-# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
-# Doxygen will parse them like normal C++ but will assume all classes use public
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
# instead of private inheritance when no explicit protection keyword is present.
SIP_SUPPORT = NO
-# For Microsoft's IDL there are propget and propput attributes to indicate getter
-# and setter methods for a property. Setting this option to YES (the default)
-# will make doxygen to replace the get and set methods by a property in the
-# documentation. This will only work if the methods are indeed getting or
-# setting a simple type. If this is not the case, or you want to show the
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
# methods anyway, you should set this option to NO.
IDL_PROPERTY_SUPPORT = NO
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
DISTRIBUTE_GROUP_DOC = NO
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
-# the same type (for instance a group of public functions) to be put as a
-# subgroup of that type (e.g. under the Public Functions section). Set it to
-# NO to prevent subgrouping. Alternatively, this can be done per class using
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
# the \nosubgrouping command.
SUBGROUPING = YES
-# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
-# is documented as struct, union, or enum with the name of the typedef. So
-# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
-# with name TypeT. When disabled the typedef will appear as a member of a file,
-# namespace, or class. And the struct will be named TypeS. This can typically
-# be useful for C code in case the coding convention dictates that all compound
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
TYPEDEF_HIDES_STRUCT = NO
@@ -272,364 +272,366 @@ TYPEDEF_HIDES_STRUCT = NO
# Build related configuration options
#---------------------------------------------------------------------------
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
-# documentation are documented, even if no documentation was available.
-# Private class members and static file members will be hidden unless
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
EXTRACT_ALL = NO
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
EXTRACT_PRIVATE = NO
-# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
EXTRACT_STATIC = YES
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
-# defined locally in source files will be included in the documentation.
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
# If set to NO only classes defined in header files are included.
EXTRACT_LOCAL_CLASSES = YES
-# This flag is only useful for Objective-C code. When set to YES local
-# methods, which are defined in the implementation section but not in
-# the interface are included in the documentation.
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
# If set to NO (the default) only methods in the interface are included.
EXTRACT_LOCAL_METHODS = NO
-# If this flag is set to YES, the members of anonymous namespaces will be
-# extracted and appear in the documentation as a namespace called
-# 'anonymous_namespace{file}', where file will be replaced with the base
-# name of the file that contains the anonymous namespace. By default
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
# anonymous namespace are hidden.
EXTRACT_ANON_NSPACES = NO
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
-# undocumented members of documented classes, files or namespaces.
-# If set to NO (the default) these members will be included in the
-# various overviews, but no documentation section is generated.
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
# This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_MEMBERS = NO
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy.
-# If set to NO (the default) these classes will be included in the various
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_CLASSES = NO
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
-# friend (class|struct|union) declarations.
-# If set to NO (the default) these declarations will be included in the
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
# documentation.
HIDE_FRIEND_COMPOUNDS = NO
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
-# documentation blocks found inside the body of a function.
-# If set to NO (the default) these blocks will be appended to the
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
# function's detailed documentation block.
HIDE_IN_BODY_DOCS = NO
-# The INTERNAL_DOCS tag determines if documentation
-# that is typed after a \internal command is included. If the tag is set
-# to NO (the default) then the documentation will be excluded.
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
# Set it to YES to include the internal documentation.
INTERNAL_DOCS = NO
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
-# file names in lower-case letters. If set to YES upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
CASE_SENSE_NAMES = YES
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
-# will show members with their full class and namespace scopes in the
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
HIDE_SCOPE_NAMES = NO
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put a list of the files that are included by a file in the documentation
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
# of that file.
SHOW_INCLUDE_FILES = YES
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
INLINE_INFO = YES
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
-# will sort the (detailed) documentation of file and class members
-# alphabetically by member name. If set to NO the members will appear in
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
# declaration order.
SORT_MEMBER_DOCS = YES
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
-# brief documentation of file, namespace and class members alphabetically
-# by member name. If set to NO (the default) the members will appear in
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
# declaration order.
SORT_BRIEF_DOCS = NO
-# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
-# hierarchy of group names into alphabetical order. If set to NO (the default)
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
# the group names will appear in their defined order.
SORT_GROUP_NAMES = NO
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
-# sorted by fully-qualified names, including namespaces. If set to
-# NO (the default), the class list will be sorted only by class name,
-# not including the namespace part.
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the
+# Note: This option applies only to the class list, not to the
# alphabetical list.
SORT_BY_SCOPE_NAME = NO
-# The GENERATE_TODOLIST tag can be used to enable (YES) or
-# disable (NO) the todo list. This list is created by putting \todo
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
# commands in the documentation.
GENERATE_TODOLIST = YES
-# The GENERATE_TESTLIST tag can be used to enable (YES) or
-# disable (NO) the test list. This list is created by putting \test
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
# commands in the documentation.
GENERATE_TESTLIST = YES
-# The GENERATE_BUGLIST tag can be used to enable (YES) or
-# disable (NO) the bug list. This list is created by putting \bug
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
# commands in the documentation.
GENERATE_BUGLIST = YES
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
-# disable (NO) the deprecated list. This list is created by putting
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
# \deprecated commands in the documentation.
GENERATE_DEPRECATEDLIST= YES
-# The ENABLED_SECTIONS tag can be used to enable conditional
+# The ENABLED_SECTIONS tag can be used to enable conditional
# documentation sections, marked by \if sectionname ... \endif.
-ENABLED_SECTIONS =
+ENABLED_SECTIONS =
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or define consists of for it to appear in
-# the documentation. If the initializer consists of more lines than specified
-# here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and defines in the
-# documentation can be controlled using \showinitializer or \hideinitializer
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
# command in the documentation regardless of this setting.
MAX_INITIALIZER_LINES = 30
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
-# at the bottom of the documentation of classes and structs. If set to YES the
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
SHOW_USED_FILES = YES
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
-# This will remove the Files entry from the Quick Index and from the
+# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.
SHOW_FILES = YES
-# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
# Namespaces page. This will remove the Namespaces entry from the Quick Index
# and from the Folder Tree View (if specified). The default is YES.
SHOW_NAMESPACES = YES
-# The FILE_VERSION_FILTER tag can be used to specify a program or script that
-# doxygen should invoke to get the current version for each file (typically from
-# the version control system). Doxygen will invoke the program by executing (via
-# popen()) the command <command> <input-file>, where <command> is the value of
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
-# provided by doxygen. Whatever the program writes to standard output
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
# is used as the file version. See the manual for examples.
-FILE_VERSION_FILTER =
+FILE_VERSION_FILTER =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
-# The QUIET tag can be used to turn on/off the messages that are generated
+# The QUIET tag can be used to turn on/off the messages that are generated
# by doxygen. Possible values are YES and NO. If left blank NO is used.
QUIET = NO
-# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated by doxygen. Possible values are YES and NO. If left blank
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
# NO is used.
WARNINGS = YES
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
# automatically be disabled.
WARN_IF_UNDOCUMENTED = YES
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some
-# parameters in a documented function, or documenting parameters that
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
# don't exist or using markup commands wrongly.
WARN_IF_DOC_ERROR = YES
-# This WARN_NO_PARAMDOC option can be abled to get warnings for
-# functions that are documented, but have no documentation for their parameters
-# or return value. If set to NO (the default) doxygen will only warn about
-# wrong or incomplete parameter documentation, but not about the absence of
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
# documentation.
WARN_NO_PARAMDOC = NO
-# The WARN_FORMAT tag determines the format of the warning messages that
-# doxygen can produce. The string should contain the $file, $line, and $text
-# tags, which will be replaced by the file and line number from which the
-# warning originated and the warning text. Optionally the format may contain
-# $version, which will be replaced by the version of the file (if it could
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
# be obtained via FILE_VERSION_FILTER)
WARN_FORMAT = "$file:$line: $text"
-# The WARN_LOGFILE tag can be used to specify a file to which warning
-# and error messages should be written. If left blank the output is written
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
# to stderr.
-WARN_LOGFILE =
+WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
-# The INPUT tag can be used to specify the files and/or directories that contain
-# documented source files. You may enter file names like "myfile.cpp" or
-# directories like "/usr/src/myproject". Separate the files or directories
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
-INPUT = @top_srcdir@/src/common \
- @top_srcdir@/src/or
+INPUT = @top_srcdir@/src/lib \
+ @top_srcdir@/src/core \
+ @top_srcdir@/src/feature \
+ @top_srcdir@/src/app
-# This tag can be used to specify the character encoding of the source files
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
-# also the default input encoding. Doxygen uses libiconv (or the iconv built
-# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
# the list of possible encodings.
INPUT_ENCODING = UTF-8
-# If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
FILE_PATTERNS = *.c \
*.h
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories
-# should be searched for input files as well. Possible values are YES and NO.
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.
RECURSIVE = NO
-# The EXCLUDE tag can be used to specify files and/or directories that should
-# excluded from the INPUT source files. This way you can easily exclude a
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
EXCLUDE = tree.h
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
-# directories that are symbolic links (a Unix filesystem feature) are excluded
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
# from the input.
EXCLUDE_SYMLINKS = NO
-# If the value of the INPUT tag contains directories, you can use the
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories. Note that the wildcards are matched
-# against the file with absolute path, so to exclude all test directories
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
# for example use the pattern */test/*
-EXCLUDE_PATTERNS =
+EXCLUDE_PATTERNS =
-# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
-# (namespaces, classes, functions, etc.) that should be excluded from the
-# output. The symbol name can be a fully qualified name, a word, or if the
-# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
-EXCLUDE_SYMBOLS =
+EXCLUDE_SYMBOLS =
-# The EXAMPLE_PATH tag can be used to specify one or more files or
-# directories that contain example code fragments that are included (see
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
# the \include command).
-EXAMPLE_PATH =
+EXAMPLE_PATH =
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.
-EXAMPLE_PATTERNS =
+EXAMPLE_PATTERNS =
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude
-# commands irrespective of the value of the RECURSIVE tag.
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
# Possible values are YES and NO. If left blank NO is used.
EXAMPLE_RECURSIVE = NO
-# The IMAGE_PATH tag can be used to specify one or more files or
-# directories that contain image that are included in the documentation (see
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
# the \image command).
-IMAGE_PATH =
+IMAGE_PATH =
-# The INPUT_FILTER tag can be used to specify a program that doxygen should
-# invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command <filter> <input-file>, where <filter>
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
-# input file. Doxygen will then use the output that the filter program writes
-# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
# ignored.
-INPUT_FILTER =
+INPUT_FILTER =
-# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis. Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match. The filters are a list of the form:
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
-# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
# is applied to all files.
-FILTER_PATTERNS =
+FILTER_PATTERNS =
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will be used to filter the input files when producing source
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
# files to browse (i.e. when SOURCE_BROWSER is set to YES).
FILTER_SOURCE_FILES = NO
@@ -638,32 +640,32 @@ FILTER_SOURCE_FILES = NO
# configuration options related to source browsing
#---------------------------------------------------------------------------
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
-# Note: To get rid of all source code in the generated output, make sure also
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
# VERBATIM_HEADERS is set to NO.
SOURCE_BROWSER = YES
-# Setting the INLINE_SOURCES tag to YES will include the body
+# Setting the INLINE_SOURCES tag to YES will include the body
# of functions and classes directly in the documentation.
INLINE_SOURCES = NO
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
# fragments. Normal C and C++ comments will always remain visible.
STRIP_CODE_COMMENTS = YES
-# If the REFERENCED_BY_RELATION tag is set to YES
-# then for each documented function all documented
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
# functions referencing it will be listed.
REFERENCED_BY_RELATION = YES
-# If the REFERENCES_RELATION tag is set to YES
-# then for each documented function all documented entities
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
# called/used by that function will be listed.
REFERENCES_RELATION = YES
@@ -675,16 +677,16 @@ REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = YES
-# If the USE_HTAGS tag is set to YES then the references to source code
-# will point to the HTML generated by the htags(1) tool instead of doxygen
-# built-in source browser. The htags tool is part of GNU's global source
-# tagging system (see http://www.gnu.org/software/global/global.html). You
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
# will need version 4.8.6 or higher.
USE_HTAGS = NO
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
-# will generate a verbatim copy of the header file for each class for
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.
VERBATIM_HEADERS = YES
@@ -693,123 +695,123 @@ VERBATIM_HEADERS = YES
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
-# of all compounds will be generated. Enable this if the project
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
# contains a lot of classes, structs, unions or interfaces.
ALPHABETICAL_INDEX = NO
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
# in which this list will be split (can be a number in the range [1..20])
COLS_IN_ALPHA_INDEX = 5
-# In case all classes in a project start with a common prefix, all
-# classes will be put under the same header in the alphabetical index.
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
# should be ignored while generating the index headers.
-IGNORE_PREFIX =
+IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
# generate HTML output.
GENERATE_HTML = YES
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `html' will be used as the default path.
HTML_OUTPUT = html
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
# doxygen will generate files with .html extension.
HTML_FILE_EXTENSION = .html
-# The HTML_HEADER tag can be used to specify a personal HTML header for
-# each generated HTML page. If it is left blank doxygen will generate a
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
# standard header.
-HTML_HEADER =
+HTML_HEADER =
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for
-# each generated HTML page. If it is left blank doxygen will generate a
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
# standard footer.
-HTML_FOOTER =
+HTML_FOOTER =
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
-# style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet. Note that doxygen will try to copy
-# the style sheet file to the HTML output directory, so don't put your own
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
# stylesheet in the HTML output directory as well, or it will be erased!
-HTML_STYLESHEET =
+HTML_STYLESHEET =
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files
-# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
# of the generated HTML documentation.
GENERATE_HTMLHELP = NO
-# If the GENERATE_DOCSET tag is set to YES, additional index files
-# will be generated that can be used as input for Apple's Xcode 3
-# integrated development environment, introduced with OSX 10.5 (Leopard).
-# To create a documentation set, doxygen will generate a Makefile in the
-# HTML output directory. Running make will produce the docset in that
-# directory and running "make install" will install the docset in
-# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
# it at startup.
GENERATE_DOCSET = NO
-# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
-# feed. A documentation feed provides an umbrella under which multiple
-# documentation sets from a single provider (such as a company or product suite)
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
# can be grouped.
DOCSET_FEEDNAME = "Doxygen generated docs for Tor"
-# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
-# should uniquely identify the documentation set bundle. This should be a
-# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
# will append .docset to the name.
DOCSET_BUNDLE_ID = org.torproject.Tor
-# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
-# documentation will contain sections that can be hidden and shown after the
-# page has loaded. For this to work a browser that supports
-# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
HTML_DYNAMIC_SECTIONS = NO
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
-# be used to specify the file name of the resulting .chm file. You
-# can add a path in front of the file if the result should not be
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
# written to the html output directory.
-CHM_FILE =
+CHM_FILE =
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
-# be used to specify the location (absolute path including file name) of
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
# the HTML help compiler on the generated index.hhp.
-HHC_LOCATION =
+HHC_LOCATION =
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
-# controls if a separate .chi index file is generated (YES) or that
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
# it should be included in the master .chm file (NO).
GENERATE_CHI = NO
@@ -818,26 +820,26 @@ GENERATE_CHI = NO
# is used to encode HtmlHelp index (hhk), content (hhc) and project file
# content.
-CHM_INDEX_ENCODING =
+CHM_INDEX_ENCODING =
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
-# controls whether a binary table of contents is generated (YES) or a
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
# normal table of contents (NO) in the .chm file.
BINARY_TOC = NO
-# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
# to the contents of the HTML help documentation and to the tree view.
TOC_EXPAND = NO
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
-# top of each HTML page. The value NO (the default) enables the index and
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it.
DISABLE_INDEX = NO
-# This tag can be used to set the number of enum values (range [1..20])
+# This tag can be used to set the number of enum values (range [1..20])
# that doxygen will group on one line in the generated HTML documentation.
ENUM_VALUES_PER_LINE = 4
@@ -845,11 +847,11 @@ ENUM_VALUES_PER_LINE = 4
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information.
# If the tag value is set to FRAME, a side panel will be generated
-# containing a tree-like index structure (just like the one that
-# is generated for HTML Help). For this to work a browser that supports
-# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
-# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
-# probably better off using the HTML help feature. Other possible values
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature. Other possible values
# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
# and Class Hiererachy pages using a tree view instead of an ordered list;
# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
@@ -859,16 +861,16 @@ ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
-# used to set the initial width (in pixels) of the frame in which the tree
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
# is shown.
TREEVIEW_WIDTH = 250
-# Use this tag to change the font size of Latex formulas included
-# as images in the HTML documentation. The default is 10. Note that
-# when you change the font size after a successful doxygen run you need
-# to manually remove any form_*.png images from the HTML output directory
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
# to force them to be regenerated.
FORMULA_FONTSIZE = 10
@@ -877,74 +879,74 @@ FORMULA_FONTSIZE = 10
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = YES
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `latex' will be used as the default path.
LATEX_OUTPUT = latex
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked. If left blank `latex' will be used as the default command name.
LATEX_CMD_NAME = latex
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
-# generate index for LaTeX. If left blank `makeindex' will be used as the
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
# default command name.
MAKEINDEX_CMD_NAME = makeindex
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
-# LaTeX documents. This may be useful for small projects and may help to
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_LATEX = NO
-# The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, a4wide, letter, legal and
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
# executive. If left blank a4wide will be used.
PAPER_TYPE = a4wide
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
# packages that should be included in the LaTeX output.
-EXTRA_PACKAGES =
+EXTRA_PACKAGES =
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
-# the generated latex document. The header should contain everything until
-# the first chapter. If it is left blank doxygen will generate a
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
# standard header. Notice: only use this tag if you know what you are doing!
-LATEX_HEADER =
+LATEX_HEADER =
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will
-# contain links (just like the HTML output) instead of page references
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
# This makes the output suitable for online browsing using a pdf viewer.
PDF_HYPERLINKS = NO
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
-# plain latex in the generated Makefile. Set this option to YES to get a
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.
USE_PDFLATEX = NO
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
-# command to the generated LaTeX files. This will instruct LaTeX to keep
-# running if errors occur, instead of asking the user for help.
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
# This option is also used when generating formulas in HTML.
LATEX_BATCHMODE = NO
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not
-# include the index chapters (such as File Index, Compound Index, etc.)
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
# in the output.
LATEX_HIDE_INDICES = NO
@@ -953,68 +955,68 @@ LATEX_HIDE_INDICES = NO
# configuration options related to the RTF output
#---------------------------------------------------------------------------
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimized for Word 97 and may not look very pretty with
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
# other RTF readers or editors.
GENERATE_RTF = NO
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `rtf' will be used as the default path.
RTF_OUTPUT = rtf
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
-# RTF documents. This may be useful for small projects and may help to
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_RTF = NO
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
-# will contain hyperlink fields. The RTF file will
-# contain links (just like the HTML output) instead of page references.
-# This makes the output suitable for online browsing using WORD or other
-# programs which support those fields.
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
# Note: wordpad (write) and others do not support links.
RTF_HYPERLINKS = NO
-# Load stylesheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assignments. You only have to provide
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
# replacements, missing definitions are set to their default value.
-RTF_STYLESHEET_FILE =
+RTF_STYLESHEET_FILE =
-# Set optional variables used in the generation of an rtf document.
+# Set optional variables used in the generation of an rtf document.
# Syntax is similar to doxygen's config file.
-RTF_EXTENSIONS_FILE =
+RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages
GENERATE_MAN = NO
-# The MAN_OUTPUT tag is used to specify where the man pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `man' will be used as the default path.
MAN_OUTPUT = man
-# The MAN_EXTENSION tag determines the extension that is added to
+# The MAN_EXTENSION tag determines the extension that is added to
# the generated man pages (default is the subroutine's section .3)
MAN_EXTENSION = .3
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
-# then it will generate one additional man file for each entity
-# documented in the real man page(s). These additional files
-# only source the real man page, but without them the man command
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
# would be unable to find the correct page. The default is NO.
MAN_LINKS = NO
@@ -1023,21 +1025,21 @@ MAN_LINKS = NO
# configuration options related to the XML output
#---------------------------------------------------------------------------
-# If the GENERATE_XML tag is set to YES Doxygen will
-# generate an XML file that captures the structure of
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
# the code including all documentation.
GENERATE_XML = NO
-# The XML_OUTPUT tag is used to specify where the XML pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `xml' will be used as the default path.
XML_OUTPUT = xml
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
-# dump the program listings (including syntax highlighting
-# and cross-referencing information) to the XML output. Note that
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
# enabling this will significantly increase the size of the XML output.
XML_PROGRAMLISTING = YES
@@ -1046,10 +1048,10 @@ XML_PROGRAMLISTING = YES
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
-# generate an AutoGen Definitions (see autogen.sf.net) file
-# that captures the structure of the code including all
-# documentation. Note that this feature is still experimental
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
# and incomplete at the moment.
GENERATE_AUTOGEN_DEF = NO
@@ -1058,338 +1060,338 @@ GENERATE_AUTOGEN_DEF = NO
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will
-# generate a Perl module file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
# moment.
GENERATE_PERLMOD = NO
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
# to generate PDF and DVI output from the Perl module output.
PERLMOD_LATEX = NO
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
-# nicely formatted so it can be parsed by a human reader. This is useful
-# if you want to understand what is going on. On the other hand, if this
-# tag is set to NO the size of the Perl module output will be much smaller
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
# and Perl will parse it just the same.
PERLMOD_PRETTY = YES
-# The names of the make variables in the generated doxyrules.make file
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
-# This is useful so different doxyrules.make files included by the same
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
# Makefile don't overwrite each other's variables.
-PERLMOD_MAKEVAR_PREFIX =
+PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor
+# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
-# evaluate all C-preprocessor directives found in the sources and include
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
# files.
ENABLE_PREPROCESSING = YES
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional
-# compilation will be performed. Macro expansion can be done in a controlled
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
# way by setting EXPAND_ONLY_PREDEF to YES.
MACRO_EXPANSION = NO
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
-# then the macro expansion is limited to the macros specified with the
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
# PREDEFINED and EXPAND_AS_DEFINED tags.
EXPAND_ONLY_PREDEF = NO
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
# in the INCLUDE_PATH (see below) will be search if a #include is found.
SEARCH_INCLUDES = YES
-# The INCLUDE_PATH tag can be used to specify one or more directories that
-# contain include files that are not input files but should be processed by
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
# the preprocessor.
-INCLUDE_PATH =
+INCLUDE_PATH =
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
-# patterns (like *.h and *.hpp) to filter out the header-files in the
-# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
# be used.
-INCLUDE_FILE_PATTERNS =
+INCLUDE_FILE_PATTERNS =
-# The PREDEFINED tag can be used to specify one or more macro names that
-# are defined before the preprocessor is started (similar to the -D option of
-# gcc). The argument of the tag is a list of macros of the form: name
-# or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed. To prevent a macro definition from being
-# undefined via #undef or recursively expanded use the := operator
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
-PREDEFINED =
+PREDEFINED =
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
-# this tag can be used to specify a list of macro names that should be expanded.
-# The macro definition that is found in the sources will be used.
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
# Use the PREDEFINED tag if you want to use a different macro definition.
-EXPAND_AS_DEFINED =
+EXPAND_AS_DEFINED =
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all function-like macros that are alone
-# on a line, have an all uppercase name, and do not end with a semicolon. Such
-# function macros are typically used for boiler-plate code, and will confuse
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
# the parser if not removed.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
-# Configuration::additions related to external references
+# Configuration::additions related to external references
#---------------------------------------------------------------------------
-# The TAGFILES option can be used to specify one or more tagfiles.
-# Optionally an initial location of the external documentation
-# can be added for each tagfile. The format of a tag file without
-# this location is as follows:
-# TAGFILES = file1 file2 ...
-# Adding location for the tag files is done as follows:
-# TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths or
-# URLs. If a location is present for each tag, the installdox tool
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
# does not have to be run to correct the links.
# Note that each tag file must have a unique name
# (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen
+# If a tag file is not located in the directory in which doxygen
# is run, you must also specify the path to the tagfile here.
-TAGFILES =
+TAGFILES =
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
# a tag file that is based on the input files it reads.
-GENERATE_TAGFILE =
+GENERATE_TAGFILE =
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed
-# in the class index. If set to NO only the inherited external classes
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
# will be listed.
ALLEXTERNALS = NO
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
# be listed.
EXTERNAL_GROUPS = YES
-# The PERL_PATH should be the absolute path and name of the perl script
+# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of `which perl').
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
-# Configuration options related to the dot tool
+# Configuration options related to the dot tool
#---------------------------------------------------------------------------
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
-# or super classes. Setting the tag to NO turns the diagrams off. Note that
-# this option is superseded by the HAVE_DOT option below. This is only a
-# fallback. It is recommended to install and use dot, since it yields more
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
# powerful graphs.
CLASS_DIAGRAMS = YES
-# You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see
-# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
-# documentation. The MSCGEN_PATH tag allows you to specify the directory where
-# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.
-MSCGEN_PATH =
+MSCGEN_PATH =
-# If set to YES, the inheritance and collaboration graphs will hide
-# inheritance and usage relations if the target is undocumented
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
# or is not a class.
HIDE_UNDOC_RELATIONS = YES
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
-# available from the path. This tool is part of Graphviz, a graph visualization
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
HAVE_DOT = NO
-# By default doxygen will write a font called FreeSans.ttf to the output
-# directory and reference it in all dot files that doxygen generates. This
-# font does not include all possible unicode characters however, so when you need
-# these (or just want a differently looking font) you can specify the font name
-# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
-# which can be done by putting it in a standard location or by setting the
-# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
# containing the font.
DOT_FONTNAME =
-# By default doxygen will tell dot to use the output directory to look for the
-# FreeSans.ttf font (which doxygen will put there itself). If you specify a
-# different font using DOT_FONTNAME you can set the path where dot
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
# can find it using this tag.
-DOT_FONTPATH =
+DOT_FONTPATH =
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect inheritance relations. Setting this tag to YES will force the
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
# the CLASS_DIAGRAMS tag to NO.
CLASS_GRAPH = YES
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect implementation dependencies (inheritance, containment, and
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
# class references variables) of the class with other documented classes.
COLLABORATION_GRAPH = YES
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for groups, showing the direct groups dependencies
GROUP_GRAPHS = YES
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
-# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
UML_LOOK = NO
-# If set to YES, the inheritance and collaboration graphs will show the
+# If set to YES, the inheritance and collaboration graphs will show the
# relations between templates and their instances.
TEMPLATE_RELATIONS = YES
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
-# tags are set to YES then doxygen will generate a graph for each documented
-# file showing the direct and indirect include dependencies of the file with
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
# other documented files.
INCLUDE_GRAPH = YES
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
-# documented header file showing the documented files that directly or
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
# indirectly include this file.
INCLUDED_BY_GRAPH = YES
-# If the CALL_GRAPH and HAVE_DOT options are set to YES then
-# doxygen will generate a call dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable call graphs
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
# for selected functions only using the \callgraph command.
CALL_GRAPH = NO
-# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
-# doxygen will generate a caller dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable caller
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
# graphs for selected functions only using the \callergraph command.
CALLER_GRAPH = NO
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will graphical hierarchy of all classes instead of a textual one.
GRAPHICAL_HIERARCHY = YES
-# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
-# then doxygen will show the dependencies a directory has on other directories
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
# in a graphical way. The dependency relations are determined by the #include
# relations between the files in the directories.
DIRECTORY_GRAPH = YES
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. Possible values are png, jpg, or gif
# If left blank png will be used.
DOT_IMAGE_FORMAT = png
-# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
-DOT_PATH =
+DOT_PATH =
-# The DOTFILE_DIRS tag can be used to specify one or more directories that
-# contain dot files that are included in the documentation (see the
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
# \dotfile command).
-DOTFILE_DIRS =
+DOTFILE_DIRS =
-# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
-# nodes that will be shown in the graph. If the number of nodes in a graph
-# becomes larger than this value, doxygen will truncate the graph, which is
-# visualized by representing a node as a red box. Note that doxygen if the
-# number of direct children of the root node in a graph is already larger than
-# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
DOT_GRAPH_MAX_NODES = 50
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
-# graphs generated by dot. A depth value of 3 means that only nodes reachable
-# from the root by following a path via at most 3 edges will be shown. Nodes
-# that lay further from the root node will be omitted. Note that setting this
-# option to 1 or 2 may greatly reduce the computation time needed for large
-# code bases. Also note that the size of a graph can be further restricted by
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
MAX_DOT_GRAPH_DEPTH = 0
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is enabled by default, which results in a transparent
-# background. Warning: Depending on the platform used, enabling this option
-# may lead to badly anti-aliased labels on the edges of a graph (i.e. they
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is enabled by default, which results in a transparent
+# background. Warning: Depending on the platform used, enabling this option
+# may lead to badly anti-aliased labels on the edges of a graph (i.e. they
# become hard to read).
DOT_TRANSPARENT = NO
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
-# files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
# support this, this feature is disabled by default.
DOT_MULTI_TARGETS = NO
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
-# generate a legend page explaining the meaning of the various boxes and
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
# arrows in the dot generated graphs.
GENERATE_LEGEND = YES
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
-# remove the intermediate dot files that are used to generate
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
# the various graphs.
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine
+# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
-# The SEARCHENGINE tag specifies whether or not a search engine should be
+# The SEARCHENGINE tag specifies whether or not a search engine should be
# used. If set to NO the values of all tags below this one will be ignored.
SEARCHENGINE = NO
diff --git a/LICENSE b/LICENSE
index 3d0f8c121b..057ae57652 100644
--- a/LICENSE
+++ b/LICENSE
@@ -13,7 +13,7 @@ Tor is distributed under this license:
Copyright (c) 2001-2004, Roger Dingledine
Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson
-Copyright (c) 2007-2017, The Tor Project, Inc.
+Copyright (c) 2007-2018, The Tor Project, Inc.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
diff --git a/Makefile.am b/Makefile.am
index 552b75a35f..0f934cf0f2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
# Copyright (c) 2001-2004, Roger Dingledine
# Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson
-# Copyright (c) 2007-2017, The Tor Project, Inc.
+# Copyright (c) 2007-2018, The Tor Project, Inc.
# See LICENSE for licensing information
ACLOCAL_AMFLAGS = -I m4
@@ -15,14 +15,19 @@ TESTS=
noinst_PROGRAMS=
DISTCLEANFILES=
bin_SCRIPTS=
-AM_CPPFLAGS=
+AM_CPPFLAGS=\
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/ext \
+ -I$(top_srcdir)/src/ext/trunnel \
+ -I$(top_srcdir)/src/trunnel
+
AM_CFLAGS=@TOR_SYSTEMD_CFLAGS@ @CFLAGS_BUGTRAP@ @TOR_LZMA_CFLAGS@ @TOR_ZSTD_CFLAGS@
SHELL=@SHELL@
if COVERAGE_ENABLED
-TESTING_TOR_BINARY=$(top_builddir)/src/or/tor-cov$(EXEEXT)
+TESTING_TOR_BINARY=$(top_builddir)/src/app/tor-cov$(EXEEXT)
else
-TESTING_TOR_BINARY=$(top_builddir)/src/or/tor$(EXEEXT)
+TESTING_TOR_BINARY=$(top_builddir)/src/app/tor$(EXEEXT)
endif
if USE_RUST
@@ -33,6 +38,97 @@ else
rust_ldadd=
endif
+# "Common" libraries used to link tor's utility code.
+TOR_UTIL_LIBS = \
+ src/lib/libtor-process.a \
+ src/lib/libtor-time.a \
+ src/lib/libtor-fs.a \
+ src/lib/libtor-encoding.a \
+ src/lib/libtor-sandbox.a \
+ src/lib/libtor-container.a \
+ src/lib/libtor-net.a \
+ src/lib/libtor-thread.a \
+ src/lib/libtor-memarea.a \
+ src/lib/libtor-math.a \
+ src/lib/libtor-meminfo.a \
+ src/lib/libtor-osinfo.a \
+ src/lib/libtor-log.a \
+ src/lib/libtor-lock.a \
+ src/lib/libtor-fdio.a \
+ src/lib/libtor-string.a \
+ src/lib/libtor-term.a \
+ src/lib/libtor-smartlist-core.a \
+ src/lib/libtor-malloc.a \
+ src/lib/libtor-wallclock.a \
+ src/lib/libtor-err.a \
+ src/lib/libtor-intmath.a \
+ src/lib/libtor-ctime.a
+
+# Variants of the above for linking the testing variant of tor (for coverage
+# and tests)
+TOR_UTIL_TESTING_LIBS = \
+ src/lib/libtor-process-testing.a \
+ src/lib/libtor-time-testing.a \
+ src/lib/libtor-fs-testing.a \
+ src/lib/libtor-encoding-testing.a \
+ src/lib/libtor-sandbox-testing.a \
+ src/lib/libtor-container-testing.a \
+ src/lib/libtor-net-testing.a \
+ src/lib/libtor-thread-testing.a \
+ src/lib/libtor-memarea-testing.a \
+ src/lib/libtor-math-testing.a \
+ src/lib/libtor-meminfo-testing.a \
+ src/lib/libtor-osinfo-testing.a \
+ src/lib/libtor-term-testing.a \
+ src/lib/libtor-log-testing.a \
+ src/lib/libtor-lock-testing.a \
+ src/lib/libtor-fdio-testing.a \
+ src/lib/libtor-string-testing.a \
+ src/lib/libtor-smartlist-core-testing.a \
+ src/lib/libtor-malloc-testing.a \
+ src/lib/libtor-wallclock-testing.a \
+ src/lib/libtor-err-testing.a \
+ src/lib/libtor-intmath.a \
+ src/lib/libtor-ctime-testing.a
+
+# Internal crypto libraries used in Tor
+TOR_CRYPTO_LIBS = \
+ src/lib/libtor-tls.a \
+ src/lib/libtor-crypt-ops.a \
+ $(LIBKECCAK_TINY) \
+ $(LIBDONNA)
+
+# Variants of the above for linking the testing variant of tor (for coverage
+# and tests)
+TOR_CRYPTO_TESTING_LIBS = \
+ src/lib/libtor-tls-testing.a \
+ src/lib/libtor-crypt-ops-testing.a \
+ $(LIBKECCAK_TINY) \
+ $(LIBDONNA)
+
+# All static libraries used to link tor.
+TOR_INTERNAL_LIBS = \
+ src/core/libtor-app.a \
+ src/lib/libtor-compress.a \
+ src/lib/libtor-evloop.a \
+ $(TOR_CRYPTO_LIBS) \
+ $(TOR_UTIL_LIBS) \
+ src/trunnel/libor-trunnel.a \
+ src/lib/libtor-trace.a
+
+# Variants of the above for linking the testing variant of tor (for coverage
+# and tests)
+TOR_INTERNAL_TESTING_LIBS = \
+ src/core/libtor-app-testing.a \
+ src/lib/libtor-compress-testing.a \
+ src/lib/libtor-evloop-testing.a \
+ $(TOR_CRYPTO_TESTING_LIBS) \
+ $(TOR_UTIL_TESTING_LIBS) \
+ src/trunnel/libor-trunnel-testing.a \
+ src/lib/libtor-trace.a
+
+# All libraries used to link tor-cov
+
include src/include.am
include doc/include.am
include contrib/include.am
@@ -40,11 +136,13 @@ include contrib/include.am
EXTRA_DIST+= \
ChangeLog \
CONTRIBUTING \
+ CODE_OF_CONDUCT \
INSTALL \
LICENSE \
Makefile.nmake \
README \
ReleaseNotes \
+ scripts/maint/checkIncludes.py \
scripts/maint/checkSpace.pl
## This tells etags how to find mockable function definitions.
@@ -205,13 +303,20 @@ coverage-html-full: all
check-spaces:
if USE_PERL
$(PERL) $(top_srcdir)/scripts/maint/checkSpace.pl -C \
- $(top_srcdir)/src/common/*.[ch] \
- $(top_srcdir)/src/or/*.[ch] \
+ $(top_srcdir)/src/lib/*/*.[ch] \
+ $(top_srcdir)/src/core/*/*.[ch] \
+ $(top_srcdir)/src/feature/*/*.[ch] \
+ $(top_srcdir)/src/app/*/*.[ch] \
$(top_srcdir)/src/test/*.[ch] \
$(top_srcdir)/src/test/*/*.[ch] \
$(top_srcdir)/src/tools/*.[ch]
endif
+check-includes:
+if USEPYTHON
+ $(top_srcdir)/scripts/maint/checkIncludes.py
+endif
+
check-docs: all
$(PERL) $(top_builddir)/scripts/maint/checkOptionDocs.pl
@@ -239,6 +344,20 @@ check-typos:
echo "You can install the latest version of misspell here: https://github.com/client9/misspell#install"; \
fi
+.PHONY: clippy
+clippy:
+if USE_RUST
+ @if test -x "`which cargo-clippy 2>&1;true`"; then \
+ echo "Running cargo clippy ..."; \
+ echo "Prepare yourself for the onslaught of suggestions ..."; \
+ (cd "$(top_srcdir)/src/rust" && cargo clippy); \
+ else \
+ echo "Tor can use clippy to lint Rust code."; \
+ echo "However, it seems that you don't have clippy installed."; \
+ echo "You can install the latest version of clippy by following the directions here: https://github.com/rust-lang-nursery/rust-clippy"; \
+ fi
+endif
+
.PHONY: check-changes
check-changes:
if USEPYTHON
@@ -284,3 +403,9 @@ show-distdir-testlog:
cat $(distdir)/_build/sub/$(TEST_SUITE_LOG); \
else \
cat $(distdir)/_build/$(TEST_SUITE_LOG); fi
+
+show-libs:
+ @echo $(TOR_INTERNAL_LIBS)
+
+show-testing-libs:
+ @echo $(TOR_INTERNAL_TESTING_LIBS)
diff --git a/acinclude.m4 b/acinclude.m4
index 49d4f14471..c9cfc3f014 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -2,7 +2,7 @@ dnl Helper macros for Tor configure.ac
dnl Copyright (c) 2001-2004, Roger Dingledine
dnl Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson
dnl Copyright (c) 2007-2008, Roger Dingledine, Nick Mathewson
-dnl Copyright (c) 2007-2017, The Tor Project, Inc.
+dnl Copyright (c) 2007-2018, The Tor Project, Inc.
dnl See LICENSE for licensing information
AC_DEFUN([TOR_EXTEND_CODEPATH],
diff --git a/changes/bug22156 b/changes/bug22156
new file mode 100644
index 0000000000..685f2a551b
--- /dev/null
+++ b/changes/bug22156
@@ -0,0 +1,3 @@
+ o Minor features (development):
+ - Tor's makefile now supports running the "clippy" Rust style tool
+ on our Rust code. Closes ticket 22156.
diff --git a/changes/bug25477 b/changes/bug25477
new file mode 100644
index 0000000000..0eac06137f
--- /dev/null
+++ b/changes/bug25477
@@ -0,0 +1,3 @@
+ o Minor bugfixes (logging):
+ - Refrain from mentioning bug 21018, as it is already fixed.
+ Fixes bug 25477; bugfix on 0.2.9.8.
diff --git a/changes/bug25886 b/changes/bug25886
new file mode 100644
index 0000000000..45f9a54069
--- /dev/null
+++ b/changes/bug25886
@@ -0,0 +1,7 @@
+ o Minor bugfixes (relay):
+ - In frac_nodes_with_descriptors(), add for_direct_connect, and replace
+ node_has_any_descriptor() with node_has_preferred_descriptor(). Also,
+ if we are using bridges and there is at least one bridge with a full
+ descriptor, set f_guard in compute_frac_paths_available() to 1.0.
+ Fixes bug 25886; bugfix on 0.3.5.1-alpha. Patch by Neel Chauhan.
+
diff --git a/changes/bug26152 b/changes/bug26152
new file mode 100644
index 0000000000..34fda09b25
--- /dev/null
+++ b/changes/bug26152
@@ -0,0 +1,4 @@
+ o Minor bugfixes (testing):
+ - When logging a version mismatch in our openssl_version tests,
+ report the actual offending version strings. Fixes bug 26152; bugfix on
+ 0.2.9.1-alpha.
diff --git a/changes/bug26282 b/changes/bug26282
new file mode 100644
index 0000000000..c278f0b60a
--- /dev/null
+++ b/changes/bug26282
@@ -0,0 +1,4 @@
+ o Minor bugfixes (C correctness):
+ - Avoid casting smartlist index to int implicitly, as it may trigger
+ a warning (-Wshorten-64-to-32). Fixes bug 26282; bugfix on
+ 0.2.3.13-alpha, 0.2.7.1-alpha and 0.2.1.1-alpha.
diff --git a/changes/bug26488 b/changes/bug26488
new file mode 100644
index 0000000000..f93d4c6f00
--- /dev/null
+++ b/changes/bug26488
@@ -0,0 +1,4 @@
+ o Major bugfixes (directory authority):
+ - Actually check that address we get from DirAuthority configuration
+ line is valid IPv4. Explicitly disallow DirAuthority adress to be
+ DNS hostname. Fixes bug 26488; bugfix on 0.1.2.10-rc.
diff --git a/changes/bug26522 b/changes/bug26522
new file mode 100644
index 0000000000..c6b30eed79
--- /dev/null
+++ b/changes/bug26522
@@ -0,0 +1,6 @@
+ o Minor bugfixes (security):
+ - Refrain from potentially insecure usage of strncat() in
+ configure_backtrace_handler(). Use snprintf() instead.
+ Fixes bug 26522; bugfix on
+ a969ce464dc23db39725a891d60537f3d3e51b50 (not in any tor
+ release).
diff --git a/changes/bug26525 b/changes/bug26525
new file mode 100644
index 0000000000..27862eee96
--- /dev/null
+++ b/changes/bug26525
@@ -0,0 +1,4 @@
+ o Minor bugfixes (code quality):
+ - Rename sandbox_getaddrinfo() and other functions to no longer
+ misleadingly suggest that they are sandbox-only. Fixes bug
+ 26525; bugfix on 0.2.7.1-alpha.
diff --git a/changes/doc26638 b/changes/doc26638
new file mode 100644
index 0000000000..d6f9b1de70
--- /dev/null
+++ b/changes/doc26638
@@ -0,0 +1,4 @@
+ o Minor features (development):
+ - Copy paragraph and URL to Tor's code of conduct document
+ from CONTRIBUTING to new CODE_OF_CONDUCT file. Resolves
+ ticket 26638.
diff --git a/changes/feature8323 b/changes/feature8323
new file mode 100644
index 0000000000..6fbc972d26
--- /dev/null
+++ b/changes/feature8323
@@ -0,0 +1,3 @@
+ o Minor features (controller):
+ - Implement 'GETINFO md/all' controller command to enable
+ getting all known microdesriptors. Closes ticket 8323.
diff --git a/changes/full_include_paths b/changes/full_include_paths
new file mode 100644
index 0000000000..c0ac0a05d3
--- /dev/null
+++ b/changes/full_include_paths
@@ -0,0 +1,3 @@
+ o Code simplification and refactoring:
+ - Include paths to header files within Tor are now qualified by directory
+ within the top-level src directory.
diff --git a/changes/iphplapi b/changes/iphplapi
new file mode 100644
index 0000000000..806f71c3f3
--- /dev/null
+++ b/changes/iphplapi
@@ -0,0 +1,4 @@
+ o Removed features:
+ - Tor no longer attempts to run on Windows environments without the
+ GetAdaptersAddresses() function. This function has existed since
+ Windows XP, which is itself already older than we support.
diff --git a/changes/split_or_h b/changes/split_or_h
new file mode 100644
index 0000000000..53d54ca6dd
--- /dev/null
+++ b/changes/split_or_h
@@ -0,0 +1,5 @@
+ o Code simplification and refactoring:
+ - Many structures have been removed from the centralized "or.h" header,
+ and moved into their own headers. This will allow us to reduce
+ the number of places in the code that rely on each structure's
+ contents and layout. Closes ticket 26383.
diff --git a/changes/ticket19979 b/changes/ticket19979
new file mode 100644
index 0000000000..a6bf93f1a4
--- /dev/null
+++ b/changes/ticket19979
@@ -0,0 +1,3 @@
+ o Minor features (openssl):
+ - When possible, use RFC5869 HKDF implementation from OpenSSL.
+ Resolves ticket 19979.
diff --git a/changes/ticket25928 b/changes/ticket25928
new file mode 100644
index 0000000000..30759fcb66
--- /dev/null
+++ b/changes/ticket25928
@@ -0,0 +1,4 @@
+ o Minor features (directory):
+ - Improved support for networks with only a single authority or a
+ single fallback directory. Patch from Gabriel Somlo. Closes
+ ticket 25928.
diff --git a/changes/ticket26426 b/changes/ticket26426
new file mode 100644
index 0000000000..05fa974943
--- /dev/null
+++ b/changes/ticket26426
@@ -0,0 +1,4 @@
+ o Removed features:
+ - Tor no longer supports building with the dmalloc library. For debugging
+ memory issues, we suggest using gperftools or msan instead.
+ Closes ticket 26426.
diff --git a/changes/ticket26427 b/changes/ticket26427
new file mode 100644
index 0000000000..ff33f7bd4c
--- /dev/null
+++ b/changes/ticket26427
@@ -0,0 +1,6 @@
+ o Minor features (code layout):
+ - Make a new lowest-level error-handling API for use by code invoked
+ from within the logging module. This interface it makes it so
+ the logging code is no longer at risk of calling into itself if
+ a failure occurs while trying to log something.
+ Closes ticket 26427.
diff --git a/changes/ticket26510 b/changes/ticket26510
new file mode 100644
index 0000000000..f00457964d
--- /dev/null
+++ b/changes/ticket26510
@@ -0,0 +1,4 @@
+ o Code simplification and refactoring:
+ - Unify our bloom filter logic. Previously we had two copies of this
+ code: one for routerlist filtering, and one for address set
+ calculations. Closes ticket 26510.
diff --git a/changes/ticket26527 b/changes/ticket26527
new file mode 100644
index 0000000000..ea1d650fef
--- /dev/null
+++ b/changes/ticket26527
@@ -0,0 +1,3 @@
+ o Code simplification and refactoring:
+ - Remove ATTR_NONNULL macro from codebase. Resolves
+ ticket 26527.
diff --git a/changes/ticket26560 b/changes/ticket26560
new file mode 100644
index 0000000000..5b4fb1bfe7
--- /dev/null
+++ b/changes/ticket26560
@@ -0,0 +1,3 @@
+ o Minor features (continuous integration):
+ - Install libcap-dev and libseccomp2-dev so these optional
+ dependencies get tested on Travis CI. Closes ticket 26560.
diff --git a/changes/ticket26626 b/changes/ticket26626
new file mode 100644
index 0000000000..84591342dc
--- /dev/null
+++ b/changes/ticket26626
@@ -0,0 +1,3 @@
+ o Code simplification and refactoring:
+ - Tor now assumes that you have standards-conformant stdint.h and
+ inttypes.h headers when compiling. Closes ticket 26626.
diff --git a/configure.ac b/configure.ac
index 8cc509c430..296591f025 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,11 +1,11 @@
dnl Copyright (c) 2001-2004, Roger Dingledine
dnl Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson
-dnl Copyright (c) 2007-2017, The Tor Project, Inc.
+dnl Copyright (c) 2007-2018, The Tor Project, Inc.
dnl See LICENSE for licensing information
AC_PREREQ([2.63])
-AC_INIT([tor],[0.3.4.4-rc])
-AC_CONFIG_SRCDIR([src/or/main.c])
+AC_INIT([tor],[0.3.5.0-alpha-dev])
+AC_CONFIG_SRCDIR([src/app/main/tor_main.c])
AC_CONFIG_MACRO_DIR([m4])
# "foreign" means we don't follow GNU package layout standards
@@ -21,16 +21,6 @@ AC_CANONICAL_HOST
PKG_PROG_PKG_CONFIG
-if test -f "/etc/redhat-release"; then
- if test -f "/usr/kerberos/include"; then
- CPPFLAGS="$CPPFLAGS -I/usr/kerberos/include"
- fi
-fi
-
-# Not a no-op; we want to make sure that CPPFLAGS is set before we use
-# the += operator on it in src/or/Makefile.am
-CPPFLAGS="$CPPFLAGS -I\${top_srcdir}/src/common"
-
AC_ARG_ENABLE(openbsd-malloc,
AS_HELP_STRING(--enable-openbsd-malloc, [use malloc code from OpenBSD. Linux only]))
AC_ARG_ENABLE(static-openssl,
@@ -432,7 +422,7 @@ AH_BOTTOM([
#endif
])
-
+AM_CONDITIONAL(WIN32, test "x$bwin32" = "xtrue")
AM_CONDITIONAL(BUILD_NT_SERVICES, test "x$bwin32" = "xtrue")
AM_CONDITIONAL(BUILD_LIBTORRUNNER, test "x$bwin32" != "xtrue")
@@ -620,6 +610,8 @@ AC_CHECK_FUNCS(
sigaction \
socketpair \
statvfs \
+ strncasecmp \
+ strcasecmp \
strlcat \
strlcpy \
strnlen \
@@ -1372,8 +1364,7 @@ AC_SUBST(CURVE25519_LIBS)
dnl Make sure to enable support for large off_t if available.
AC_SYS_LARGEFILE
-AC_CHECK_HEADERS([assert.h \
- errno.h \
+AC_CHECK_HEADERS([errno.h \
fcntl.h \
signal.h \
string.h \
@@ -1402,7 +1393,6 @@ AC_CHECK_HEADERS([assert.h \
netinet/in6.h \
pwd.h \
readpassphrase.h \
- stdint.h \
stdatomic.h \
sys/eventfd.h \
sys/file.h \
@@ -1526,22 +1516,6 @@ AC_CHECK_MEMBERS([struct timeval.tv_sec], , ,
#include <sys/time.h>
#endif])
-dnl In case we aren't given a working stdint.h, we'll need to grow our own.
-dnl Watch out.
-
-AC_CHECK_SIZEOF(int8_t)
-AC_CHECK_SIZEOF(int16_t)
-AC_CHECK_SIZEOF(int32_t)
-AC_CHECK_SIZEOF(int64_t)
-AC_CHECK_SIZEOF(uint8_t)
-AC_CHECK_SIZEOF(uint16_t)
-AC_CHECK_SIZEOF(uint32_t)
-AC_CHECK_SIZEOF(uint64_t)
-AC_CHECK_SIZEOF(intptr_t)
-AC_CHECK_SIZEOF(uintptr_t)
-
-dnl AC_CHECK_TYPES([int8_t, int16_t, int32_t, int64_t, uint8_t, uint16_t, uint32_t, uint64_t, intptr_t, uintptr_t])
-
AC_CHECK_SIZEOF(char)
AC_CHECK_SIZEOF(short)
AC_CHECK_SIZEOF(int)
@@ -1786,26 +1760,6 @@ if test "$tor_cv_uint8_uchar" = "no"; then
AC_MSG_ERROR([We assume that uint8_t is the same type as unsigned char, but your compiler disagrees.])
fi
-# Whether we should use the dmalloc memory allocation debugging library.
-AC_MSG_CHECKING(whether to use dmalloc (debug memory allocation library))
-AC_ARG_WITH(dmalloc,
-AS_HELP_STRING(--with-dmalloc, [use debug memory allocation library]),
-[if [[ "$withval" = "yes" ]]; then
- dmalloc=1
- AC_MSG_RESULT(yes)
-else
- dmalloc=1
- AC_MSG_RESULT(no)
-fi], [ dmalloc=0; AC_MSG_RESULT(no) ]
-)
-
-if [[ $dmalloc -eq 1 ]]; then
- AC_CHECK_HEADERS(dmalloc.h, , AC_MSG_ERROR(dmalloc header file not found. Do you have the development files for dmalloc installed?))
- AC_SEARCH_LIBS(dmalloc_malloc, [dmallocth dmalloc], , AC_MSG_ERROR(Libdmalloc library not found. If you enable it you better have it installed.))
- AC_DEFINE(USE_DMALLOC, 1, [Debug memory allocation library])
- AC_CHECK_FUNCS(dmalloc_strdup dmalloc_strndup)
-fi
-
AC_ARG_WITH(tcmalloc,
AS_HELP_STRING(--with-tcmalloc, [use tcmalloc memory allocation library]),
[ tcmalloc=yes ], [ tcmalloc=no ])
diff --git a/contrib/include.am b/contrib/include.am
index 5d5f216490..a23e82d6da 100644
--- a/contrib/include.am
+++ b/contrib/include.am
@@ -10,7 +10,6 @@ EXTRA_DIST+= \
contrib/operator-tools/linux-tor-prio.sh \
contrib/operator-tools/tor-exit-notice.html \
contrib/or-tools/exitlist \
- contrib/win32build/package_nsis-mingw.sh \
contrib/win32build/tor-mingw.nsi.in \
contrib/win32build/tor.ico \
contrib/win32build/tor.nsi.in
diff --git a/contrib/win32build/package_nsis-mingw.sh b/contrib/win32build/package_nsis-mingw.sh
deleted file mode 100644
index cae862b919..0000000000
--- a/contrib/win32build/package_nsis-mingw.sh
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/bin/sh
-#
-# ===============================================================================
-# package_nsis-ming.sh is distributed under this license:
-
-# Copyright (c) 2006-2007 Andrew Lewman
-# Copyright (c) 2008 The Tor Project, Inc.
-
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-
-# * Neither the names of the copyright owners nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-# ===============================================================================
-
-# Script to package a Tor installer on win32. This script assumes that
-# you have already built Tor, that you are running msys/mingw, and that
-# you know what you are doing.
-
-# Start in the tor source directory after you've compiled tor.exe
-# This means start as ./contrib/win32build/package_nsis-mingw.sh
-
-rm -rf win_tmp
-mkdir win_tmp
-mkdir win_tmp/bin
-mkdir win_tmp/contrib
-mkdir win_tmp/doc
-mkdir win_tmp/doc/spec
-mkdir win_tmp/doc/design-paper
-mkdir win_tmp/doc/contrib
-mkdir win_tmp/src
-mkdir win_tmp/src/config
-mkdir win_tmp/tmp
-
-cp src/or/tor.exe win_tmp/bin/
-cp src/tools/tor-resolve.exe win_tmp/bin/
-cp contrib/win32build/tor.ico win_tmp/bin/
-cp src/config/geoip win_tmp/bin/
-strip win_tmp/bin/*.exe
-
-# There is no man2html in mingw.
-# Maybe we should add this into make dist instead.
-# One has to do this manually and cp it do the tor-source/doc dir
-#man2html doc/tor.1.in > win_tmp/tmp/tor-reference.html
-#man2html doc/tor-resolve.1 > win_tmp/tmp/tor-resolve.html
-
-clean_newlines() {
- perl -pe 's/^\n$/\r\n/mg; s/([^\r])\n$/\1\r\n/mg;' $1 >$2
-}
-
-clean_localstatedir() {
- perl -pe 's/^\n$/\r\n/mg; s/([^\r])\n$/\1\r\n/mg; s{\@LOCALSTATEDIR\@/(lib|log)/tor/}{C:\\Documents and Settings\\Application Data\\Tor\\}' $1 >$2
-}
-
-for fn in address-spec.txt bridges-spec.txt control-spec.txt dir-spec.txt path-spec.txt rend-spec.txt socks-extensions.txt tor-spec.txt version-spec.txt; do
- clean_newlines doc/spec/$fn win_tmp/doc/spec/$fn
-done
-
-for fn in HACKING tor-gencert.html tor.html torify.html tor-resolve.html; do
- clean_newlines doc/$fn win_tmp/doc/$fn
-done
-
-for fn in README ChangeLog LICENSE; do
- clean_newlines $fn win_tmp/$fn
-done
-
-clean_localstatedir src/config/torrc.sample.in win_tmp/src/config/torrc.sample
-
-cp contrib/win32build/tor-mingw.nsi.in win_tmp/contrib/
-
-cd win_tmp
-makensis.exe contrib/tor-mingw.nsi.in
-
diff --git a/contrib/win32build/tor-mingw.nsi.in b/contrib/win32build/tor-mingw.nsi.in
index bdf310bc99..c9822790bb 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.3.4.4-rc"
+!define VERSION "0.3.5.0-alpha-dev"
!define INSTALLER "tor-${VERSION}-win32.exe"
!define WEBSITE "https://www.torproject.org/"
!define LICENSE "LICENSE"
diff --git a/doc/HACKING/CodingStandards.md b/doc/HACKING/CodingStandards.md
index 3711f70198..b830ecea93 100644
--- a/doc/HACKING/CodingStandards.md
+++ b/doc/HACKING/CodingStandards.md
@@ -172,7 +172,6 @@ deviations from our C whitespace style. Generally, we use:
- Unix-style line endings
- K&R-style indentation
- No space before newlines
- - A blank line at the end of each file
- Never more than one blank line in a row
- Always spaces, never tabs
- No more than 79-columns per line.
@@ -185,6 +184,9 @@ deviations from our C whitespace style. Generally, we use:
`puts (x)`.
- Function declarations at the start of the line.
+If you use an editor that has plugins for editorconfig.org, the file
+`.editorconfig` will help you to conform this coding style.
+
We try hard to build without warnings everywhere. In particular, if
you're using gcc, you should invoke the configure script with the
option `--enable-fatal-warnings`. This will tell the compiler
@@ -434,4 +436,3 @@ the functions that call your function rely on it doing something, then your
function should mention that it does that something in the documentation. If
you rely on a function doing something beyond what is in its documentation,
then you should watch out, or it might do something else later.
-
diff --git a/doc/HACKING/HelpfulTools.md b/doc/HACKING/HelpfulTools.md
index a0795076e0..13d1c4b0d7 100644
--- a/doc/HACKING/HelpfulTools.md
+++ b/doc/HACKING/HelpfulTools.md
@@ -25,20 +25,10 @@ Jenkins
https://jenkins.torproject.org
-Dmalloc
--------
-
-The dmalloc library will keep track of memory allocation, so you can find out
-if we're leaking memory, doing any double-frees, or so on.
-
- dmalloc -l -/dmalloc.log
- (run the commands it tells you)
- ./configure --with-dmalloc
-
Valgrind
--------
- valgrind --leak-check=yes --error-limit=no --show-reachable=yes src/or/tor
+ 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
@@ -242,10 +232,10 @@ Beforehand, install google-perftools.
Now you can run Tor with profiling enabled, and use the pprof utility to look at
performance! See the gperftools manual for more info, but basically:
-2. Run `env CPUPROFILE=/tmp/profile src/or/tor -f <path/torrc>`. The profile file
+2. Run `env CPUPROFILE=/tmp/profile src/app/tor -f <path/torrc>`. The profile file
is not written to until Tor finishes execuction.
-3. Run `pprof src/or/tor /tm/profile` to start the REPL.
+3. Run `pprof src/app/tor /tm/profile` to start the REPL.
Generating and analyzing a callgraph
------------------------------------
diff --git a/doc/HACKING/Module.md b/doc/HACKING/Module.md
index 1028a029d9..6684e258df 100644
--- a/doc/HACKING/Module.md
+++ b/doc/HACKING/Module.md
@@ -12,9 +12,9 @@ Currently, there is only one module:
- Directory Authority subsystem (dirauth)
-It is located in its own directory in `src/or/dirauth/`. To disable it, one
-need to pass `--disable-module-dirauth` at configure time. All modules are
-currently enabled by default.
+It is located in its own directory in `src/feature/dirauth/`. To disable it,
+one need to pass `--disable-module-dirauth` at configure time. All modules
+are currently enabled by default.
## Build System ##
@@ -32,10 +32,10 @@ The changes to the build system are pretty straightforward.
the C code to conditionally compile things for your module. And the
`BUILD_MODULE_<name>` is also defined for automake files (e.g: include.am).
-3. In the `src/or/include.am` file, locate the `MODULE_DIRAUTH_SOURCES` value.
- You need to create your own `_SOURCES` variable for your module and then
- conditionally add the it to `LIBTOR_A_SOURCES` if you should build the
- module.
+3. In the `src/core/include.am` file, locate the `MODULE_DIRAUTH_SOURCES`
+ value. You need to create your own `_SOURCES` variable for your module
+ and then conditionally add the it to `LIBTOR_A_SOURCES` if you should
+ build the module.
It is then **very** important to add your SOURCES variable to
`src_or_libtor_testing_a_SOURCES` so the tests can build it.
@@ -51,7 +51,7 @@ always build everything in order to tests everything.
## Coding ##
As mentioned above, a module must be isolated in its own directory (name of
-the module) in `src/or/`.
+the module) in `src/feature/`.
There are couples of "rules" you want to follow:
@@ -87,10 +87,10 @@ There are couples of "rules" you want to follow:
making the code much more difficult to follow/understand.
* It is possible that you end up with code that needs to be used by the rest
- of the code base but is still part of your module. As a good example, if you
- look at `src/or/shared_random_client.c`: it contains code needed by the hidden
- service subsystem but mainly related to the shared random subsystem very
- specific to the dirauth module.
+ of the code base but is still part of your module. As a good example, if
+ you look at `src/feature/shared_random_client.c`: it contains code needed
+ by the hidden service subsystem but mainly related to the shared random
+ subsystem very specific to the dirauth module.
This is fine but try to keep it as lean as possible and never use the same
filename as the one in the module. For example, this is a bad idea and
@@ -102,7 +102,7 @@ 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 "dirauth/dirvote.h"`
+ `#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/Tracing.md b/doc/HACKING/Tracing.md
index 349aade23a..24fa761310 100644
--- a/doc/HACKING/Tracing.md
+++ b/doc/HACKING/Tracing.md
@@ -69,7 +69,7 @@ configure option:
## Instrument Tor ##
This is pretty easy. Let's say you want to add a trace event in
-`src/or/rendcache.c`, you only have to add this include statement:
+`src/feature/rend/rendcache.c`, you only have to add this include statement:
#include "trace/events.h"
diff --git a/doc/include.am b/doc/include.am
index 7942188eaf..e429d05a49 100644
--- a/doc/include.am
+++ b/doc/include.am
@@ -29,9 +29,9 @@ doc_DATA =
endif
EXTRA_DIST+= doc/asciidoc-helper.sh \
- $(html_in) $(man_in) $(txt_in) \
- doc/state-contents.txt \
- doc/torrc_format.txt \
+ $(html_in) $(man_in) $(txt_in) \
+ doc/state-contents.txt \
+ doc/torrc_format.txt \
doc/TUNING \
doc/HACKING/README.1st.md \
doc/HACKING/CodingStandards.md \
diff --git a/scripts/codegen/fuzzing_include_am.py b/scripts/codegen/fuzzing_include_am.py
index fda57d2ae8..42a61876e8 100755
--- a/scripts/codegen/fuzzing_include_am.py
+++ b/scripts/codegen/fuzzing_include_am.py
@@ -24,32 +24,17 @@ FUZZING_CFLAGS = \
FUZZING_LDFLAG = \
@TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@
FUZZING_LIBS = \
- src/or/libtor-testing.a \
- src/common/libor-crypto-testing.a \
- $(LIBKECCAK_TINY) \
- $(LIBDONNA) \
- src/common/libor-testing.a \
- src/common/libor-ctime-testing.a \
- src/common/libor-event-testing.a \
- src/trunnel/libor-trunnel-testing.a \
+ $(TOR_INTERNAL_TESTING_LIBS) \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \
- @TOR_LIBEVENT_LIBS@ \
- @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
- @CURVE25519_LIBS@ \
+ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
+ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@ \
@TOR_SYSTEMD_LIBS@ \
@TOR_LZMA_LIBS@ \
@TOR_ZSTD_LIBS@
oss-fuzz-prereqs: \
- src/or/libtor-testing.a \
- src/common/libor-crypto-testing.a \
- $(LIBKECCAK_TINY) \
- $(LIBDONNA) \
- src/common/libor-testing.a \
- src/common/libor-ctime-testing.a \
- src/common/libor-event-testing.a \
- src/trunnel/libor-trunnel-testing.a
+ $(TOR_INTERNAL_TESTING_LIBS)
noinst_HEADERS += \
src/test/fuzz/fuzzing.h
diff --git a/scripts/codegen/gen_server_ciphers.py b/scripts/codegen/gen_server_ciphers.py
index 7ea39c540d..5b2eef07ef 100755
--- a/scripts/codegen/gen_server_ciphers.py
+++ b/scripts/codegen/gen_server_ciphers.py
@@ -1,5 +1,5 @@
#!/usr/bin/python
-# Copyright 2014-2017, The Tor Project, Inc
+# Copyright 2014-2018, The Tor Project, Inc
# See LICENSE for licensing information
# This script parses openssl headers to find ciphersuite names, determines
diff --git a/scripts/codegen/get_mozilla_ciphers.py b/scripts/codegen/get_mozilla_ciphers.py
index 946957ac77..4f986daba9 100755
--- a/scripts/codegen/get_mozilla_ciphers.py
+++ b/scripts/codegen/get_mozilla_ciphers.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
# coding=utf-8
-# Copyright 2011-2017, The Tor Project, Inc
+# Copyright 2011-2018, The Tor Project, Inc
# original version by Arturo Filastò
# See LICENSE for licensing information
diff --git a/scripts/codegen/makedesc.py b/scripts/codegen/makedesc.py
index 8d9d4edaaf..4ee8106f03 100644
--- a/scripts/codegen/makedesc.py
+++ b/scripts/codegen/makedesc.py
@@ -1,5 +1,5 @@
#!/usr/bin/python
-# Copyright 2014-2017, The Tor Project, Inc.
+# Copyright 2014-2018, The Tor Project, Inc.
# See LICENSE for license information
# This is a kludgey python script that uses ctypes and openssl to sign
diff --git a/scripts/maint/checkIncludes.py b/scripts/maint/checkIncludes.py
new file mode 100755
index 0000000000..9da15a2b9c
--- /dev/null
+++ b/scripts/maint/checkIncludes.py
@@ -0,0 +1,84 @@
+#!/usr/bin/python3
+# Copyright 2018 The Tor Project, Inc. See LICENSE file for licensing info.
+
+import fnmatch
+import os
+import re
+import sys
+
+trouble = False
+
+def err(msg):
+ global trouble
+ trouble = True
+ print(msg, file=sys.stderr)
+
+def fname_is_c(fname):
+ return fname.endswith(".h") or fname.endswith(".c")
+
+INCLUDE_PATTERN = re.compile(r'\s*#\s*include\s+"([^"]*)"')
+RULES_FNAME = ".may_include"
+
+class Rules(object):
+ def __init__(self, dirpath):
+ self.dirpath = dirpath
+ self.patterns = []
+ self.usedPatterns = set()
+
+ def addPattern(self, pattern):
+ self.patterns.append(pattern)
+
+ def includeOk(self, path):
+ for pattern in self.patterns:
+ if fnmatch.fnmatchcase(path, pattern):
+ self.usedPatterns.add(pattern)
+ return True
+ return False
+
+ def applyToLines(self, lines, context=""):
+ lineno = 0
+ for line in lines:
+ lineno += 1
+ m = INCLUDE_PATTERN.match(line)
+ if m:
+ include = m.group(1)
+ if not self.includeOk(include):
+ err("Forbidden include of {} on line {}{}".format(
+ include, lineno, context))
+
+ def applyToFile(self, fname):
+ with open(fname, 'r') as f:
+ #print(fname)
+ self.applyToLines(iter(f), " of {}".format(fname))
+
+ def noteUnusedRules(self):
+ for p in self.patterns:
+ if p not in self.usedPatterns:
+ print("Pattern {} in {} was never used.".format(p, self.dirpath))
+
+def load_include_rules(fname):
+ result = Rules(os.path.split(fname)[0])
+ with open(fname, 'r') as f:
+ for line in f:
+ line = line.strip()
+ if line.startswith("#") or not line:
+ continue
+ result.addPattern(line)
+ return result
+
+list_unused = False
+
+for dirpath, dirnames, fnames in os.walk("src"):
+ if ".may_include" in fnames:
+ rules = load_include_rules(os.path.join(dirpath, RULES_FNAME))
+ for fname in fnames:
+ if fname_is_c(fname):
+ rules.applyToFile(os.path.join(dirpath,fname))
+ if list_unused:
+ rules.noteUnusedRules()
+
+if trouble:
+ err(
+"""To change which includes are allowed in a C file, edit the {} files in its
+enclosing directory.""".format(RULES_FNAME))
+ sys.exit(1)
diff --git a/scripts/maint/checkOptionDocs.pl.in b/scripts/maint/checkOptionDocs.pl.in
index 1f53adf099..6533c762c5 100644
--- a/scripts/maint/checkOptionDocs.pl.in
+++ b/scripts/maint/checkOptionDocs.pl.in
@@ -7,7 +7,7 @@ my %torrcSampleOptions = ();
my %manPageOptions = ();
# Load the canonical list as actually accepted by Tor.
-open(F, "@abs_top_builddir@/src/or/tor --list-torrc-options |") or die;
+open(F, "@abs_top_builddir@/src/app/tor --list-torrc-options |") or die;
while (<F>) {
next if m!\[notice\] Tor v0\.!;
if (m!^([A-Za-z0-9_]+)!) {
diff --git a/scripts/maint/checkSpace.pl b/scripts/maint/checkSpace.pl
index a12370f21f..633b47e314 100755
--- a/scripts/maint/checkSpace.pl
+++ b/scripts/maint/checkSpace.pl
@@ -16,12 +16,21 @@ if ($ARGV[0] =~ /^-/) {
$C = ($lang eq '-C');
}
+our %basenames = ();
+
for my $fn (@ARGV) {
open(F, "$fn");
my $lastnil = 0;
my $lastline = "";
my $incomment = 0;
my $in_func_head = 0;
+ my $basename = $fn;
+ $basename =~ s#.*/##;
+ if ($basenames{$basename}) {
+ msg "Duplicate fnames: $fn and $basenames{$basename}.\n";
+ } else {
+ $basenames{$basename} = $fn;
+ }
while (<F>) {
## Warn about windows-style newlines.
# (We insist on lines that end with a single LF character, not
@@ -126,7 +135,7 @@ for my $fn (@ARGV) {
## Warn about double semi-colons at the end of a line.
if (/;;$/) {
msg " double semi-colons at the end of $. in $fn\n"
- }
+ }
## Warn about multiple internal spaces.
#if (/[^\s,:]\s{2,}[^\s\\=]/) {
# msg " X X:$fn:$.\n";
diff --git a/scripts/maint/fallback.whitelist b/scripts/maint/fallback.whitelist
index e9158e1280..79551948c6 100644
--- a/scripts/maint/fallback.whitelist
+++ b/scripts/maint/fallback.whitelist
@@ -12,7 +12,8 @@
# To replace this list with the hard-coded fallback list (for testing), use
# a command similar to:
-# cat src/or/fallback_dirs.inc | grep \" | grep -v weight | tr -d '\n' | \
+# cat src/app/config/fallback_dirs.inc | grep \" | grep -v weight | \
+# tr -d '\n' | \
# sed 's/"" / /g' | sed 's/""/"/g' | tr \" '\n' | grep -v '^$' \
# > scripts/maint/fallback.whitelist
#
diff --git a/scripts/maint/format_changelog.py b/scripts/maint/format_changelog.py
index c5a0cfc81b..98fbbfb516 100755
--- a/scripts/maint/format_changelog.py
+++ b/scripts/maint/format_changelog.py
@@ -1,5 +1,5 @@
#!/usr/bin/python
-# Copyright (c) 2014-2017, The Tor Project, Inc.
+# Copyright (c) 2014-2018, The Tor Project, Inc.
# See LICENSE for licensing information
#
# This script reformats a section of the changelog to wrap everything to
diff --git a/scripts/maint/rectify_include_paths.py b/scripts/maint/rectify_include_paths.py
new file mode 100755
index 0000000000..401fadae6d
--- /dev/null
+++ b/scripts/maint/rectify_include_paths.py
@@ -0,0 +1,60 @@
+#!/usr/bin/python3
+
+import os
+import os.path
+import re
+
+# Find all the include files, map them to their real names.
+
+def exclude(paths, dirnames):
+ for p in paths:
+ if p in dirnames:
+ dirnames.remove(p)
+
+def get_include_map():
+ includes = { }
+
+ for dirpath,dirnames,fnames in os.walk("src"):
+ exclude(["ext", "win32"], dirnames)
+
+ for fname in fnames:
+ if fname.endswith(".h"):
+ assert fname not in includes
+ include = os.path.join(dirpath, fname)
+ assert include.startswith("src/")
+ includes[fname] = include[4:]
+
+ return includes
+
+INCLUDE_PAT = re.compile(r'( *# *include +")([^"]+)(".*)')
+
+def get_base_header_name(hdr):
+ return os.path.split(hdr)[1]
+
+def fix_includes(inp, out, mapping):
+ for line in inp:
+ m = INCLUDE_PAT.match(line)
+ if m:
+ include,hdr,rest = m.groups()
+ basehdr = get_base_header_name(hdr)
+ if basehdr in mapping:
+ out.write('{}{}{}\n'.format(include,mapping[basehdr],rest))
+ continue
+
+ out.write(line)
+
+incs = get_include_map()
+
+for dirpath,dirnames,fnames in os.walk("src"):
+ exclude(["trunnel"], dirnames)
+
+ for fname in fnames:
+ if fname.endswith(".c") or fname.endswith(".h"):
+ fname = os.path.join(dirpath, fname)
+ tmpfile = fname+".tmp"
+ f_in = open(fname, 'r')
+ f_out = open(tmpfile, 'w')
+ fix_includes(f_in, f_out, incs)
+ f_in.close()
+ f_out.close()
+ os.rename(tmpfile, fname)
diff --git a/scripts/maint/redox.py b/scripts/maint/redox.py
index 53d3d902eb..e8b2622ab9 100755
--- a/scripts/maint/redox.py
+++ b/scripts/maint/redox.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# Copyright (c) 2008-2017, The Tor Project, Inc.
+# Copyright (c) 2008-2018, The Tor Project, Inc.
# See LICENSE for licensing information.
#
# Hi!
diff --git a/scripts/maint/sortChanges.py b/scripts/maint/sortChanges.py
index 22e40fd369..c85e6563b8 100755
--- a/scripts/maint/sortChanges.py
+++ b/scripts/maint/sortChanges.py
@@ -1,5 +1,5 @@
#!/usr/bin/python
-# Copyright (c) 2014-2017, The Tor Project, Inc.
+# Copyright (c) 2014-2018, The Tor Project, Inc.
# See LICENSE for licensing information
"""This script sorts a bunch of changes files listed on its command
diff --git a/scripts/maint/updateCopyright.pl b/scripts/maint/updateCopyright.pl
index beb0b8f26e..bd24377d38 100755
--- a/scripts/maint/updateCopyright.pl
+++ b/scripts/maint/updateCopyright.pl
@@ -1,7 +1,7 @@
#!/usr/bin/perl -i -w -p
-$NEWYEAR=2017;
+$NEWYEAR=2018;
-s/Copyright(.*) (201[^7]), The Tor Project/Copyright$1 $2-${NEWYEAR}, The Tor Project/;
+s/Copyright(.*) (201[^8]), The Tor Project/Copyright$1 $2-${NEWYEAR}, The Tor Project/;
s/Copyright(.*)-(20..), The Tor Project/Copyright$1-${NEWYEAR}, The Tor Project/;
diff --git a/scripts/maint/updateFallbackDirs.py b/scripts/maint/updateFallbackDirs.py
index b093463e08..355dc027df 100755
--- a/scripts/maint/updateFallbackDirs.py
+++ b/scripts/maint/updateFallbackDirs.py
@@ -3,11 +3,11 @@
# Usage:
#
# Regenerate the list:
-# scripts/maint/updateFallbackDirs.py > src/or/fallback_dirs.inc 2> fallback_dirs.log
+# scripts/maint/updateFallbackDirs.py > src/app/config/fallback_dirs.inc 2> fallback_dirs.log
#
# Check the existing list:
# scripts/maint/updateFallbackDirs.py check_existing > fallback_dirs.inc.ok 2> fallback_dirs.log
-# mv fallback_dirs.inc.ok src/or/fallback_dirs.inc
+# mv fallback_dirs.inc.ok src/app/config/fallback_dirs.inc
#
# This script should be run from a stable, reliable network connection,
# with no other network activity (and not over tor).
@@ -112,7 +112,7 @@ DOWNLOAD_MICRODESC_CONSENSUS = True
# expired consensus. This makes them fail the download check.
# We use a tolerance of 0, so that 0.2.x series relays also fail the download
# check if they serve an expired consensus.
-CONSENSUS_EXPIRY_TOLERANCE = 0
+CONSENSUS_EXPIRY_TOLERANCE = 0
# Output fallback name, flags, bandwidth, and ContactInfo in a C comment?
OUTPUT_COMMENTS = True if OUTPUT_CANDIDATES else False
@@ -161,7 +161,7 @@ BLACKLIST_EXCLUDES_WHITELIST_ENTRIES = True
WHITELIST_FILE_NAME = 'scripts/maint/fallback.whitelist'
BLACKLIST_FILE_NAME = 'scripts/maint/fallback.blacklist'
-FALLBACK_FILE_NAME = 'src/or/fallback_dirs.inc'
+FALLBACK_FILE_NAME = 'src/app/config/fallback_dirs.inc'
# The number of bytes we'll read from a filter file before giving up
MAX_LIST_FILE_SIZE = 1024 * 1024
diff --git a/scripts/test/coverage b/scripts/test/coverage
index f10c5afaae..59d468ee1e 100755
--- a/scripts/test/coverage
+++ b/scripts/test/coverage
@@ -7,7 +7,7 @@
dst=$1
-for fn in src/or/*.c src/common/*.c; do
+for fn in src/core/*/*.c src/feature/*/*.c src/app/*/*.c src/lib/*/*.c; do
BN=`basename $fn`
DN=`dirname $fn`
F=`echo $BN | sed -e 's/\.c$//;'`
diff --git a/src/or/auth_dirs.inc b/src/app/config/auth_dirs.inc
index e0937541ea..e0937541ea 100644
--- a/src/or/auth_dirs.inc
+++ b/src/app/config/auth_dirs.inc
diff --git a/src/or/config.c b/src/app/config/config.c
index 94a58f3488..665732ea56 100644
--- a/src/or/config.c
+++ b/src/app/config/config.c
@@ -2,7 +2,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -60,61 +60,84 @@
**/
#define CONFIG_PRIVATE
-#include "or.h"
-#include "bridges.h"
-#include "compat.h"
-#include "addressmap.h"
-#include "channel.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuitmux.h"
-#include "circuitmux_ewma.h"
-#include "circuitstats.h"
-#include "compress.h"
-#include "config.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "connection_or.h"
-#include "consdiffmgr.h"
-#include "control.h"
-#include "confparse.h"
-#include "cpuworker.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "dirserv.h"
-#include "dns.h"
-#include "dos.h"
-#include "entrynodes.h"
-#include "git_revision.h"
-#include "geoip.h"
-#include "hibernate.h"
-#include "main.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "policies.h"
-#include "relay.h"
-#include "rendclient.h"
-#include "rendservice.h"
-#include "hs_config.h"
-#include "rephist.h"
-#include "router.h"
-#include "sandbox.h"
-#include "util.h"
-#include "routerlist.h"
-#include "routerset.h"
-#include "scheduler.h"
-#include "statefile.h"
-#include "transports.h"
-#include "ext_orport.h"
-#include "voting_schedule.h"
+#include "core/or/or.h"
+#include "feature/client/bridges.h"
+#include "feature/client/addressmap.h"
+#include "core/or/channel.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuitmux.h"
+#include "core/or/circuitmux_ewma.h"
+#include "core/or/circuitstats.h"
+#include "lib/compress/compress.h"
+#include "app/config/config.h"
+#include "lib/encoding/confline.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "core/or/connection_or.h"
+#include "feature/dircache/consdiffmgr.h"
+#include "feature/control/control.h"
+#include "app/config/confparse.h"
+#include "core/mainloop/cpuworker.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/relay/dns.h"
+#include "core/or/dos.h"
+#include "feature/client/entrynodes.h"
+#include "core/or/git_revision.h"
+#include "feature/stats/geoip.h"
+#include "feature/hibernate/hibernate.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "core/or/relay.h"
+#include "feature/rend/rendclient.h"
+#include "feature/rend/rendservice.h"
+#include "feature/hs/hs_config.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "lib/sandbox/sandbox.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerset.h"
+#include "core/or/scheduler.h"
+#include "app/config/statefile.h"
+#include "feature/client/transports.h"
+#include "feature/relay/ext_orport.h"
+#include "feature/dircommon/voting_schedule.h"
#ifdef _WIN32
#include <shlobj.h>
#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "lib/meminfo/meminfo.h"
+#include "lib/osinfo/uname.h"
+#include "lib/process/daemon.h"
+#include "lib/process/pidfile.h"
+#include "lib/process/restrict.h"
+#include "lib/process/setuid.h"
+#include "lib/process/subprocess.h"
+#include "lib/net/gethostname.h"
+#include "lib/thread/numcpus.h"
-#include "procmon.h"
+#include "lib/encoding/keyval.h"
+#include "lib/fs/conffile.h"
+#include "lib/evloop/procmon.h"
-#include "dirauth/dirvote.h"
-#include "dirauth/mode.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/dirauth/mode.h"
+
+#include "core/or/connection_st.h"
+#include "core/or/port_cfg_st.h"
#ifdef HAVE_SYSTEMD
# if defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__)
@@ -132,6 +155,10 @@ static const char unix_socket_prefix[] = "unix:";
* configuration. */
static const char unix_q_socket_prefix[] = "unix:\"";
+/* limits for TCP send and recv buffer size used for constrained sockets */
+#define MIN_CONSTRAINED_TCP_BUFFER 2048
+#define MAX_CONSTRAINED_TCP_BUFFER 262144 /* 256k */
+
/** macro to help with the bulk rename of *DownloadSchedule to
* *DowloadInitialDelay . */
#define DOWNLOAD_SCHEDULE(name) \
@@ -2626,7 +2653,7 @@ print_usage(void)
printf(
"Copyright (c) 2001-2004, Roger Dingledine\n"
"Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson\n"
-"Copyright (c) 2007-2017, The Tor Project, Inc.\n\n"
+"Copyright (c) 2007-2018, The Tor Project, Inc.\n\n"
"tor -f <torrc> [args]\n"
"See man page for options, or https://www.torproject.org/ for "
"documentation.\n");
@@ -3033,8 +3060,8 @@ ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg)
--*value;
}
if (*value > ROUTER_MAX_DECLARED_BANDWIDTH) {
- tor_asprintf(msg, "%s ("U64_FORMAT") must be at most %d",
- desc, U64_PRINTF_ARG(*value),
+ tor_asprintf(msg, "%s (%"PRIu64") must be at most %d",
+ desc, (*value),
ROUTER_MAX_DECLARED_BANDWIDTH);
return -1;
}
@@ -4567,8 +4594,8 @@ compute_real_max_mem_in_queues(const uint64_t val, int log_guess)
uint64_t result;
if (val == 0) {
-#define ONE_GIGABYTE (U64_LITERAL(1) << 30)
-#define ONE_MEGABYTE (U64_LITERAL(1) << 20)
+#define ONE_GIGABYTE (UINT64_C(1) << 30)
+#define ONE_MEGABYTE (UINT64_C(1) << 20)
/* The user didn't pick a memory limit. Choose a very large one
* that is still smaller than the system memory */
static int notice_sent = 0;
@@ -4622,10 +4649,10 @@ compute_real_max_mem_in_queues(const uint64_t val, int log_guess)
}
}
if (log_guess && ! notice_sent) {
- log_notice(LD_CONFIG, "%sMaxMemInQueues is set to "U64_FORMAT" MB. "
+ log_notice(LD_CONFIG, "%sMaxMemInQueues is set to %"PRIu64" MB. "
"You can override this by setting MaxMemInQueues by hand.",
ram ? "Based on detected system memory, " : "",
- U64_PRINTF_ARG(result / ONE_MEGABYTE));
+ (result / ONE_MEGABYTE));
notice_sent = 1;
}
return result;
@@ -5635,6 +5662,23 @@ addressmap_register_auto(const char *from, const char *to,
}
/**
+ * As add_file_log, but open the file as appropriate.
+ */
+STATIC int
+open_and_add_file_log(const log_severity_list_t *severity,
+ const char *filename, int truncate_log)
+{
+ int open_flags = O_WRONLY|O_CREAT;
+ open_flags |= truncate_log ? O_TRUNC : O_APPEND;
+
+ int fd = tor_open_cloexec(filename, open_flags, 0640);
+ if (fd < 0)
+ return -1;
+
+ return add_file_log(severity, filename, fd);
+}
+
+/**
* Initialize the logs based on the configuration file.
*/
static int
@@ -5759,7 +5803,7 @@ options_init_logs(const or_options_t *old_options, or_options_t *options,
}
}
}
- if (add_file_log(severity, fname, truncate_log) < 0) {
+ if (open_and_add_file_log(severity, fname, truncate_log) < 0) {
log_warn(LD_CONFIG, "Couldn't open file for 'Log %s': %s",
opt->value, strerror(errno));
ok = 0;
@@ -6414,6 +6458,23 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type,
}
addrport = smartlist_get(items, 0);
smartlist_del_keeporder(items, 0);
+
+ const char *addrport_sep = strchr(addrport, ':');
+ if (!addrport_sep) {
+ log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s' "
+ "(':' not found)", addrport);
+ goto err;
+ }
+
+ address = tor_strndup(addrport, addrport_sep - addrport);
+ if (!string_is_valid_ipv4_address(address)) {
+ log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s' "
+ "(invalid IPv4 address)", address);
+ goto err;
+ }
+
+ tor_free(address);
+
if (addr_port_lookup(LOG_WARN, addrport, &address, NULL, &dir_port)<0) {
log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s'", addrport);
goto err;
@@ -8449,4 +8510,3 @@ options_any_client_port_set(const or_options_t *options)
options->DNSPort_set ||
options->HTTPTunnelPort_set);
}
-
diff --git a/src/or/config.h b/src/app/config/config.h
index 4b41274434..a169cfd451 100644
--- a/src/or/config.h
+++ b/src/app/config/config.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,8 @@
#ifndef TOR_CONFIG_H
#define TOR_CONFIG_H
-#include "testsupport.h"
+#include "app/config/or_options_st.h"
+#include "lib/testsupport/testsupport.h"
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(DARWIN)
#define KERNEL_MAY_SUPPORT_IPFW
@@ -24,9 +25,9 @@
/** Maximum default value for MaxMemInQueues, in bytes. */
#if SIZEOF_VOID_P >= 8
-#define MAX_DEFAULT_MEMORY_QUEUE_SIZE (U64_LITERAL(8) << 30)
+#define MAX_DEFAULT_MEMORY_QUEUE_SIZE (UINT64_C(8) << 30)
#else
-#define MAX_DEFAULT_MEMORY_QUEUE_SIZE (U64_LITERAL(2) << 30)
+#define MAX_DEFAULT_MEMORY_QUEUE_SIZE (UINT64_C(2) << 30)
#endif
MOCK_DECL(const char*, get_dirportfrontpage, (void));
@@ -42,7 +43,16 @@ void init_protocol_warning_severity_level(void);
int get_protocol_warning_severity_level(void);
const char *get_version(void);
const char *get_short_version(void);
-setopt_err_t options_trial_assign(config_line_t *list, unsigned flags,
+
+/** An error from options_trial_assign() or options_init_from_string(). */
+typedef enum setopt_err_t {
+ SETOPT_OK = 0,
+ SETOPT_ERR_MISC = -1,
+ SETOPT_ERR_PARSE = -2,
+ SETOPT_ERR_TRANSITION = -3,
+ SETOPT_ERR_SETTING = -4,
+} setopt_err_t;
+setopt_err_t options_trial_assign(struct config_line_t *list, unsigned flags,
char **msg);
uint32_t get_last_resolved_addr(void);
@@ -62,7 +72,7 @@ setopt_err_t options_init_from_string(const char *cf_defaults, const char *cf,
int command, const char *command_arg, char **msg);
int option_is_recognized(const char *key);
const char *option_get_canonical_name(const char *key);
-config_line_t *option_get_assignment(const or_options_t *options,
+struct config_line_t *option_get_assignment(const or_options_t *options,
const char *key);
int options_save_current(void);
const char *get_torrc_fname(int defaults_fname);
@@ -180,8 +190,8 @@ int init_cookie_authentication(const char *fname, const char *header,
or_options_t *options_new(void);
int config_parse_commandline(int argc, char **argv, int ignore_errors,
- config_line_t **result,
- config_line_t **cmdline_result);
+ struct config_line_t **result,
+ struct config_line_t **cmdline_result);
void config_register_addressmaps(const or_options_t *options);
/* XXXX move to connection_edge.h */
@@ -260,7 +270,7 @@ STATIC int parse_dir_fallback_line(const char *line, int validate_only);
STATIC int have_enough_mem_for_dircache(const or_options_t *options,
size_t total_mem, char **msg);
STATIC int parse_port_config(smartlist_t *out,
- const config_line_t *ports,
+ const struct config_line_t *ports,
const char *portname,
int listener_type,
const char *defaultaddr,
@@ -271,8 +281,10 @@ STATIC int check_bridge_distribution_setting(const char *bd);
STATIC uint64_t compute_real_max_mem_in_queues(const uint64_t val,
int log_guess);
+STATIC int open_and_add_file_log(const log_severity_list_t *severity,
+ const char *fname,
+ int truncate_log);
#endif /* defined(CONFIG_PRIVATE) */
#endif /* !defined(TOR_CONFIG_H) */
-
diff --git a/src/or/confparse.c b/src/app/config/confparse.c
index 6bab790945..5b7f54bc65 100644
--- a/src/or/confparse.c
+++ b/src/app/config/confparse.c
@@ -1,8 +1,7 @@
-
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -22,9 +21,12 @@
* specified, and a linked list of key-value pairs.
*/
-#include "or.h"
-#include "confparse.h"
-#include "routerset.h"
+#include "core/or/or.h"
+#include "app/config/confparse.h"
+#include "feature/nodelist/routerset.h"
+
+#include "lib/container/bitarray.h"
+#include "lib/encoding/confline.h"
static uint64_t config_parse_memunit(const char *s, int *ok);
static int config_parse_msec_interval(const char *s, int *ok);
@@ -573,8 +575,8 @@ config_get_assigned_option(const config_format_t *fmt, const void *options,
escape_val = 0; /* Can't need escape. */
break;
case CONFIG_TYPE_MEMUNIT:
- tor_asprintf(&result->value, U64_FORMAT,
- U64_PRINTF_ARG(*(uint64_t*)value));
+ tor_asprintf(&result->value, "%"PRIu64,
+ (*(uint64_t*)value));
escape_val = 0; /* Can't need escape. */
break;
case CONFIG_TYPE_DOUBLE:
@@ -1039,15 +1041,15 @@ static struct unit_table_t memory_units[] = {
{ "gigabit", 1<<27 },
{ "gbits", 1<<27 },
{ "gbit", 1<<27 },
- { "tb", U64_LITERAL(1)<<40 },
- { "tbyte", U64_LITERAL(1)<<40 },
- { "tbytes", U64_LITERAL(1)<<40 },
- { "terabyte", U64_LITERAL(1)<<40 },
- { "terabytes", U64_LITERAL(1)<<40 },
- { "terabits", U64_LITERAL(1)<<37 },
- { "terabit", U64_LITERAL(1)<<37 },
- { "tbits", U64_LITERAL(1)<<37 },
- { "tbit", U64_LITERAL(1)<<37 },
+ { "tb", UINT64_C(1)<<40 },
+ { "tbyte", UINT64_C(1)<<40 },
+ { "tbytes", UINT64_C(1)<<40 },
+ { "terabyte", UINT64_C(1)<<40 },
+ { "terabytes", UINT64_C(1)<<40 },
+ { "terabits", UINT64_C(1)<<37 },
+ { "terabit", UINT64_C(1)<<37 },
+ { "tbits", UINT64_C(1)<<37 },
+ { "tbit", UINT64_C(1)<<37 },
{ NULL, 0 },
};
@@ -1116,7 +1118,7 @@ config_parse_units(const char *val, struct unit_table_t *u, int *ok)
if (!cp) {
*ok = 1;
- v = use_float ? DBL_TO_U64(d) : v;
+ v = use_float ? ((uint64_t)d) : v;
goto done;
}
@@ -1186,4 +1188,3 @@ config_parse_interval(const char *s, int *ok)
}
return (int)r;
}
-
diff --git a/src/or/confparse.h b/src/app/config/confparse.h
index 4b4bf0adb4..cbd2ea88e2 100644
--- a/src/or/confparse.h
+++ b/src/app/config/confparse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_CONFPARSE_H
@@ -65,9 +65,9 @@ typedef union {
time_t *ISOTIME;
smartlist_t **CSV;
int *CSV_INTERVAL;
- config_line_t **LINELIST;
- config_line_t **LINELIST_S;
- config_line_t **LINELIST_V;
+ struct config_line_t **LINELIST;
+ struct config_line_t **LINELIST_S;
+ struct config_line_t **LINELIST_V;
routerset_t **ROUTERSET;
} confparse_dummy_values_t;
#endif /* defined(TOR_UNIT_TESTS) */
@@ -185,7 +185,7 @@ void config_free_(const config_format_t *fmt, void *options);
(options) = NULL; \
} while (0)
-config_line_t *config_get_assigned_option(const config_format_t *fmt,
+struct config_line_t *config_get_assigned_option(const config_format_t *fmt,
const void *options, const char *key,
int escape_val);
int config_is_same(const config_format_t *fmt,
@@ -197,7 +197,7 @@ char *config_dump(const config_format_t *fmt, const void *default_options,
const void *options, int minimal,
int comment_defaults);
int config_assign(const config_format_t *fmt, void *options,
- config_line_t *list,
+ struct config_line_t *list,
unsigned flags, char **msg);
config_var_t *config_find_option_mutable(config_format_t *fmt,
const char *key);
@@ -219,4 +219,3 @@ void warn_deprecated_option(const char *what, const char *why);
#define CFG_EQ_ROUTERSET(a,b,opt) routerset_equal((a)->opt, (b)->opt)
#endif /* !defined(TOR_CONFPARSE_H) */
-
diff --git a/src/or/fallback_dirs.inc b/src/app/config/fallback_dirs.inc
index c446152e6a..c446152e6a 100644
--- a/src/or/fallback_dirs.inc
+++ b/src/app/config/fallback_dirs.inc
diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h
new file mode 100644
index 0000000000..0c0c5d32bb
--- /dev/null
+++ b/src/app/config/or_options_st.h
@@ -0,0 +1,1077 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_OR_OPTIONS_ST_H
+#define TOR_OR_OPTIONS_ST_H
+
+#include "lib/cc/torint.h"
+#include "lib/net/address.h"
+
+struct smartlist_t;
+struct config_line_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;
+
+/** Configuration options for a Tor process. */
+struct or_options_t {
+ uint32_t magic_;
+
+ /** What should the tor process actually do? */
+ enum {
+ CMD_RUN_TOR=0, CMD_LIST_FINGERPRINT, CMD_HASH_PASSWORD,
+ CMD_VERIFY_CONFIG, CMD_RUN_UNITTESTS, CMD_DUMP_CONFIG,
+ CMD_KEYGEN,
+ CMD_KEY_EXPIRATION,
+ } command;
+ char *command_arg; /**< Argument for command-line option. */
+
+ struct config_line_t *Logs; /**< New-style list of configuration lines
+ * for logs */
+ int LogTimeGranularity; /**< Log resolution in milliseconds. */
+
+ int LogMessageDomains; /**< Boolean: Should we log the domain(s) in which
+ * each log message occurs? */
+ 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
+ * configured by the user. */
+ char *DataDirectory; /**< Where to store long-term data, as modified. */
+ int DataDirectoryGroupReadable; /**< Boolean: Is the DataDirectory g+r? */
+
+ char *KeyDirectory_option; /**< Where to store keys, as
+ * configured by the user. */
+ char *KeyDirectory; /**< Where to store keys data, as modified. */
+ int KeyDirectoryGroupReadable; /**< Boolean: Is the KeyDirectory g+r? */
+
+ char *CacheDirectory_option; /**< Where to store cached data, as
+ * configured by the user. */
+ char *CacheDirectory; /**< Where to store cached data, as modified. */
+ 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. */
+ char *PidFile; /**< Where to store PID of Tor process. */
+
+ routerset_t *ExitNodes; /**< Structure containing nicknames, digests,
+ * country codes and IP address patterns of ORs to
+ * consider as exits. */
+ routerset_t *EntryNodes;/**< Structure containing nicknames, digests,
+ * country codes and IP address patterns of ORs to
+ * consider as entry points. */
+ int StrictNodes; /**< Boolean: When none of our EntryNodes or ExitNodes
+ * are up, or we need to access a node in ExcludeNodes,
+ * do we just fail instead? */
+ routerset_t *ExcludeNodes;/**< Structure containing nicknames, digests,
+ * country codes and IP address patterns of ORs
+ * not to use in circuits. But see StrictNodes
+ * above. */
+ routerset_t *ExcludeExitNodes;/**< Structure containing nicknames, digests,
+ * country codes and IP address patterns of
+ * ORs not to consider as exits. */
+
+ /** Union of ExcludeNodes and ExcludeExitNodes */
+ routerset_t *ExcludeExitNodesUnion_;
+
+ int DisableAllSwap; /**< Boolean: Attempt to call mlockall() on our
+ * process for all current and future memory. */
+
+ struct config_line_t *ExitPolicy; /**< Lists of exit policy components. */
+ int ExitPolicyRejectPrivate; /**< Should we not exit to reserved private
+ * addresses, and our own published addresses?
+ */
+ int ExitPolicyRejectLocalInterfaces; /**< Should we not exit to local
+ * interface addresses?
+ * Includes OutboundBindAddresses and
+ * configured ports. */
+ int ReducedExitPolicy; /**<Should we use the Reduced Exit Policy? */
+ struct config_line_t *SocksPolicy; /**< Lists of socks policy components */
+ struct config_line_t *DirPolicy; /**< Lists of dir policy components */
+ /** Local address to bind outbound sockets */
+ struct config_line_t *OutboundBindAddress;
+ /** Local address to bind outbound relay sockets */
+ struct config_line_t *OutboundBindAddressOR;
+ /** Local address to bind outbound exit sockets */
+ struct config_line_t *OutboundBindAddressExit;
+ /** Addresses derived from the various OutboundBindAddress lines.
+ * [][0] is IPv4, [][1] is IPv6
+ */
+ tor_addr_t OutboundBindAddresses[OUTBOUND_ADDR_MAX][2];
+ /** Directory server only: which versions of
+ * Tor should we tell users to run? */
+ struct config_line_t *RecommendedVersions;
+ struct config_line_t *RecommendedClientVersions;
+ struct config_line_t *RecommendedServerVersions;
+ struct config_line_t *RecommendedPackages;
+ /** Whether dirservers allow router descriptors with private IPs. */
+ int DirAllowPrivateAddresses;
+ /** Whether routers accept EXTEND cells to routers with private IPs. */
+ int ExtendAllowPrivateAddresses;
+ char *User; /**< Name of user to run Tor as. */
+ /** Ports to listen on for OR connections. */
+ 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 SOCKS connections. */
+ struct config_line_t *SocksPort_lines;
+ /** Ports to listen on for transparent pf/netfilter connections. */
+ struct config_line_t *TransPort_lines;
+ char *TransProxyType; /**< What kind of transparent proxy
+ * implementation are we using? */
+ /** Parsed value of TransProxyType. */
+ enum {
+ TPT_DEFAULT,
+ TPT_PF_DIVERT,
+ TPT_IPFW,
+ TPT_TPROXY,
+ } TransProxyType_parsed;
+ /** Ports to listen on for transparent natd connections. */
+ struct config_line_t *NATDPort_lines;
+ /** Ports to listen on for HTTP Tunnel connections. */
+ struct config_line_t *HTTPTunnelPort_lines;
+ struct config_line_t *ControlPort_lines; /**< Ports to listen on for control
+ * connections. */
+ /** List of Unix Domain Sockets to listen on for control connections. */
+ struct config_line_t *ControlSocket;
+
+ int ControlSocketsGroupWritable; /**< Boolean: Are control sockets g+rw? */
+ int UnixSocksGroupWritable; /**< Boolean: Are SOCKS Unix sockets g+rw? */
+ /** Ports to listen on for directory connections. */
+ struct config_line_t *DirPort_lines;
+ /** Ports to listen on for DNS requests. */
+ struct config_line_t *DNSPort_lines;
+
+ /* MaxMemInQueues value as input by the user. We clean this up to be
+ * MaxMemInQueues. */
+ uint64_t MaxMemInQueues_raw;
+ uint64_t MaxMemInQueues;/**< If we have more memory than this allocated
+ * for queues and buffers, run the OOM handler */
+ /** Above this value, consider ourselves low on RAM. */
+ uint64_t MaxMemInQueues_low_threshold;
+
+ /** @name port booleans
+ *
+ * Derived booleans: For server ports and ControlPort, true iff there is a
+ * non-listener port on an AF_INET or AF_INET6 address of the given type
+ * configured in one of the _lines options above.
+ * For client ports, also true if there is a unix socket configured.
+ * If you are checking for client ports, you may want to use:
+ * SocksPort_set || TransPort_set || NATDPort_set || DNSPort_set ||
+ * HTTPTunnelPort_set
+ * rather than SocksPort_set.
+ *
+ * @{
+ */
+ unsigned int ORPort_set : 1;
+ unsigned int SocksPort_set : 1;
+ unsigned int TransPort_set : 1;
+ unsigned int NATDPort_set : 1;
+ unsigned int ControlPort_set : 1;
+ unsigned int DirPort_set : 1;
+ unsigned int DNSPort_set : 1;
+ unsigned int ExtORPort_set : 1;
+ unsigned int HTTPTunnelPort_set : 1;
+ /**@}*/
+
+ int AssumeReachable; /**< Whether to publish our descriptor regardless. */
+ int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */
+ int V3AuthoritativeDir; /**< Boolean: is this an authoritative directory
+ * for version 3 directories? */
+ int VersioningAuthoritativeDir; /**< Boolean: is this an authoritative
+ * directory that's willing to recommend
+ * versions? */
+ int BridgeAuthoritativeDir; /**< Boolean: is this an authoritative directory
+ * that aggregates bridge descriptors? */
+
+ /** If set on a bridge relay, it will include this value on a new
+ * "bridge-distribution-request" line in its bridge descriptor. */
+ char *BridgeDistribution;
+
+ /** If set on a bridge authority, it will answer requests on its dirport
+ * for bridge statuses -- but only if the requests use this password. */
+ char *BridgePassword;
+ /** If BridgePassword is set, this is a SHA256 digest of the basic http
+ * authenticator for it. Used so we can do a time-independent comparison. */
+ char *BridgePassword_AuthDigest_;
+
+ int UseBridges; /**< Boolean: should we start all circuits with a bridge? */
+ struct config_line_t *Bridges; /**< List of bootstrap bridge addresses. */
+
+ struct config_line_t *ClientTransportPlugin; /**< List of client
+ transport plugins. */
+
+ struct config_line_t *ServerTransportPlugin; /**< List of client
+ transport plugins. */
+
+ /** List of TCP/IP addresses that transports should listen at. */
+ struct config_line_t *ServerTransportListenAddr;
+
+ /** List of options that must be passed to pluggable transports. */
+ struct config_line_t *ServerTransportOptions;
+
+ int BridgeRelay; /**< Boolean: are we acting as a bridge relay? We make
+ * this explicit so we can change how we behave in the
+ * future. */
+
+ /** Boolean: if we know the bridge's digest, should we get new
+ * descriptors from the bridge authorities or from the bridge itself? */
+ int UpdateBridgesFromAuthority;
+
+ int AvoidDiskWrites; /**< Boolean: should we never cache things to disk?
+ * Not used yet. */
+ int ClientOnly; /**< Boolean: should we never evolve into a server role? */
+
+ int ReducedConnectionPadding; /**< Boolean: Should we try to keep connections
+ open shorter and pad them less against
+ connection-level traffic analysis? */
+ /** Autobool: if auto, then connection padding will be negotiated by client
+ * and server. If 0, it will be fully disabled. If 1, the client will still
+ * pad to the server regardless of server support. */
+ int ConnectionPadding;
+
+ /** To what authority types do we publish our descriptor? Choices are
+ * "v1", "v2", "v3", "bridge", or "". */
+ struct smartlist_t *PublishServerDescriptor;
+ /** A bitfield of authority types, derived from PublishServerDescriptor. */
+ dirinfo_type_t PublishServerDescriptor_;
+ /** Boolean: do we publish hidden service descriptors to the HS auths? */
+ int PublishHidServDescriptors;
+ int FetchServerDescriptors; /**< Do we fetch server descriptors as normal? */
+ int FetchHidServDescriptors; /**< and hidden service descriptors? */
+
+ int MinUptimeHidServDirectoryV2; /**< As directory authority, accept hidden
+ * service directories after what time? */
+
+ int FetchUselessDescriptors; /**< Do we fetch non-running descriptors too? */
+ int AllDirActionsPrivate; /**< Should every directory action be sent
+ * through a Tor circuit? */
+
+ /** Run in 'tor2web mode'? (I.e. only make client connections to hidden
+ * services, and use a single hop for all hidden-service-related
+ * circuits.) */
+ int Tor2webMode;
+
+ /** A routerset that should be used when picking RPs for HS circuits. */
+ routerset_t *Tor2webRendezvousPoints;
+
+ /** A routerset that should be used when picking middle nodes for HS
+ * circuits. */
+ routerset_t *HSLayer2Nodes;
+
+ /** A routerset that should be used when picking third-hop nodes for HS
+ * circuits. */
+ routerset_t *HSLayer3Nodes;
+
+ /** Onion Services in HiddenServiceSingleHopMode make one-hop (direct)
+ * circuits between the onion service server, and the introduction and
+ * rendezvous points. (Onion service descriptors are still posted using
+ * 3-hop paths, to avoid onion service directories blocking the service.)
+ * This option makes every hidden service instance hosted by
+ * this tor instance a Single Onion Service.
+ * HiddenServiceSingleHopMode requires HiddenServiceNonAnonymousMode to be
+ * set to 1.
+ * Use rend_service_allow_non_anonymous_connection() or
+ * rend_service_reveal_startup_time() instead of using this option directly.
+ */
+ int HiddenServiceSingleHopMode;
+ /* Makes hidden service clients and servers non-anonymous on this tor
+ * instance. Allows the non-anonymous HiddenServiceSingleHopMode. Enables
+ * non-anonymous behaviour in the hidden service protocol.
+ * Use rend_service_non_anonymous_mode_enabled() instead of using this option
+ * directly.
+ */
+ int HiddenServiceNonAnonymousMode;
+
+ int ConnLimit; /**< Demanded minimum number of simultaneous connections. */
+ int ConnLimit_; /**< Maximum allowed number of simultaneous connections. */
+ int ConnLimit_high_thresh; /**< start trying to lower socket usage if we
+ * have this many. */
+ int ConnLimit_low_thresh; /**< try to get down to here after socket
+ * exhaustion. */
+ int RunAsDaemon; /**< If true, run in the background. (Unix only) */
+ int FascistFirewall; /**< Whether to prefer ORs reachable on open ports. */
+ struct smartlist_t *FirewallPorts; /**< Which ports our firewall allows
+ * (strings). */
+ /** IP:ports our firewall allows. */
+ struct config_line_t *ReachableAddresses;
+ struct config_line_t *ReachableORAddresses; /**< IP:ports for OR conns. */
+ struct config_line_t *ReachableDirAddresses; /**< IP:ports for Dir conns. */
+
+ int ConstrainedSockets; /**< Shrink xmit and recv socket buffers. */
+ uint64_t ConstrainedSockSize; /**< Size of constrained buffers. */
+
+ /** Whether we should drop exit streams from Tors that we don't know are
+ * relays. One of "0" (never refuse), "1" (always refuse), or "-1" (do
+ * what the consensus says, defaulting to 'refuse' if the consensus says
+ * nothing). */
+ int RefuseUnknownExits;
+
+ /** Application ports that require all nodes in circ to have sufficient
+ * uptime. */
+ struct smartlist_t *LongLivedPorts;
+ /** Application ports that are likely to be unencrypted and
+ * unauthenticated; we reject requests for them to prevent the
+ * user from screwing up and leaking plaintext secrets to an
+ * observer somewhere on the Internet. */
+ struct smartlist_t *RejectPlaintextPorts;
+ /** Related to RejectPlaintextPorts above, except this config option
+ * controls whether we warn (in the log and via a controller status
+ * event) every time a risky connection is attempted. */
+ struct smartlist_t *WarnPlaintextPorts;
+ /** Should we try to reuse the same exit node for a given host */
+ struct smartlist_t *TrackHostExits;
+ int TrackHostExitsExpire; /**< Number of seconds until we expire an
+ * addressmap */
+ struct config_line_t *AddressMap; /**< List of address map directives. */
+ int AutomapHostsOnResolve; /**< If true, when we get a resolve request for a
+ * hostname ending with one of the suffixes in
+ * <b>AutomapHostsSuffixes</b>, map it to a
+ * virtual address. */
+ /** List of suffixes for <b>AutomapHostsOnResolve</b>. The special value
+ * "." means "match everything." */
+ struct smartlist_t *AutomapHostsSuffixes;
+ int RendPostPeriod; /**< How often do we post each rendezvous service
+ * descriptor? Remember to publish them independently. */
+ int KeepalivePeriod; /**< How often do we send padding cells to keep
+ * connections alive? */
+ int SocksTimeout; /**< How long do we let a socks connection wait
+ * unattached before we fail it? */
+ int LearnCircuitBuildTimeout; /**< If non-zero, we attempt to learn a value
+ * for CircuitBuildTimeout based on timeout
+ * history. Use circuit_build_times_disabled()
+ * rather than checking this value directly. */
+ int CircuitBuildTimeout; /**< Cull non-open circuits that were born at
+ * least this many seconds ago. Used until
+ * adaptive algorithm learns a new value. */
+ int CircuitsAvailableTimeout; /**< Try to have an open circuit for at
+ least this long after last activity */
+ int CircuitStreamTimeout; /**< If non-zero, detach streams from circuits
+ * and try a new circuit if the stream has been
+ * waiting for this many seconds. If zero, use
+ * our default internal timeout schedule. */
+ int MaxOnionQueueDelay; /*< DOCDOC */
+ int NewCircuitPeriod; /**< How long do we use a circuit before building
+ * a new one? */
+ int MaxCircuitDirtiness; /**< Never use circs that were first used more than
+ this interval ago. */
+ uint64_t BandwidthRate; /**< How much bandwidth, on average, are we willing
+ * to use in a second? */
+ uint64_t BandwidthBurst; /**< How much bandwidth, at maximum, are we willing
+ * to use in a second? */
+ uint64_t MaxAdvertisedBandwidth; /**< How much bandwidth are we willing to
+ * tell other nodes we have? */
+ uint64_t RelayBandwidthRate; /**< How much bandwidth, on average, are we
+ * willing to use for all relayed conns? */
+ uint64_t RelayBandwidthBurst; /**< How much bandwidth, at maximum, will we
+ * use in a second for all relayed conns? */
+ uint64_t PerConnBWRate; /**< Long-term bw on a single TLS conn, if set. */
+ uint64_t PerConnBWBurst; /**< Allowed burst on a single TLS conn, if set. */
+ int NumCPUs; /**< How many CPUs should we try to use? */
+ struct config_line_t *RendConfigLines; /**< List of configuration lines
+ * for rendezvous services. */
+ struct config_line_t *HidServAuth; /**< List of configuration lines for
+ * client-side authorizations for hidden
+ * services */
+ char *ContactInfo; /**< Contact info to be published in the directory. */
+
+ int HeartbeatPeriod; /**< Log heartbeat messages after this many seconds
+ * have passed. */
+ int MainloopStats; /**< Log main loop statistics as part of the
+ * heartbeat messages. */
+
+ char *HTTPProxy; /**< hostname[:port] to use as http proxy, if any. */
+ tor_addr_t HTTPProxyAddr; /**< Parsed IPv4 addr for http proxy, if any. */
+ uint16_t HTTPProxyPort; /**< Parsed port for http proxy, if any. */
+ char *HTTPProxyAuthenticator; /**< username:password string, if any. */
+
+ char *HTTPSProxy; /**< hostname[:port] to use as https proxy, if any. */
+ tor_addr_t HTTPSProxyAddr; /**< Parsed addr for https proxy, if any. */
+ uint16_t HTTPSProxyPort; /**< Parsed port for https proxy, if any. */
+ char *HTTPSProxyAuthenticator; /**< username:password string, if any. */
+
+ char *Socks4Proxy; /**< hostname:port to use as a SOCKS4 proxy, if any. */
+ tor_addr_t Socks4ProxyAddr; /**< Derived from Socks4Proxy. */
+ uint16_t Socks4ProxyPort; /**< Derived from Socks4Proxy. */
+
+ char *Socks5Proxy; /**< hostname:port to use as a SOCKS5 proxy, if any. */
+ tor_addr_t Socks5ProxyAddr; /**< Derived from Sock5Proxy. */
+ uint16_t Socks5ProxyPort; /**< Derived from Socks5Proxy. */
+ char *Socks5ProxyUsername; /**< Username for SOCKS5 authentication, if any */
+ char *Socks5ProxyPassword; /**< Password for SOCKS5 authentication, if any */
+
+ /** List of configuration lines for replacement directory authorities.
+ * If you just want to replace one class of authority at a time,
+ * use the "Alternate*Authority" options below instead. */
+ struct config_line_t *DirAuthorities;
+
+ /** List of fallback directory servers */
+ struct config_line_t *FallbackDir;
+ /** Whether to use the default hard-coded FallbackDirs */
+ int UseDefaultFallbackDirs;
+
+ /** Weight to apply to all directory authority rates if considering them
+ * along with fallbackdirs */
+ double DirAuthorityFallbackRate;
+
+ /** If set, use these main (currently v3) directory authorities and
+ * not the default ones. */
+ struct config_line_t *AlternateDirAuthority;
+
+ /** If set, use these bridge authorities and not the default one. */
+ struct config_line_t *AlternateBridgeAuthority;
+
+ struct config_line_t *MyFamily_lines; /**< Declared family for this OR. */
+ struct config_line_t *MyFamily; /**< Declared family for this OR,
+ normalized */
+ struct config_line_t *NodeFamilies; /**< List of config lines for
+ * node families */
+ /** List of parsed NodeFamilies values. */
+ struct smartlist_t *NodeFamilySets;
+ struct config_line_t *AuthDirBadExit; /**< Address policy for descriptors to
+ * mark as bad exits. */
+ struct config_line_t *AuthDirReject; /**< Address policy for descriptors to
+ * reject. */
+ struct config_line_t *AuthDirInvalid; /**< Address policy for descriptors to
+ * never mark as valid. */
+ /** @name AuthDir...CC
+ *
+ * Lists of country codes to mark as BadExit, or Invalid, or to
+ * reject entirely.
+ *
+ * @{
+ */
+ struct smartlist_t *AuthDirBadExitCCs;
+ struct smartlist_t *AuthDirInvalidCCs;
+ struct smartlist_t *AuthDirRejectCCs;
+ /**@}*/
+
+ int AuthDirListBadExits; /**< True iff we should list bad exits,
+ * and vote for all other exits as good. */
+ int AuthDirMaxServersPerAddr; /**< Do not permit more than this
+ * number of servers per IP address. */
+ int AuthDirHasIPv6Connectivity; /**< Boolean: are we on IPv6? */
+ int AuthDirPinKeys; /**< Boolean: Do we enforce key-pinning? */
+
+ /** If non-zero, always vote the Fast flag for any relay advertising
+ * this amount of capacity or more. */
+ uint64_t AuthDirFastGuarantee;
+
+ /** If non-zero, this advertised capacity or more is always sufficient
+ * to satisfy the bandwidth requirement for the Guard flag. */
+ uint64_t AuthDirGuardBWGuarantee;
+
+ char *AccountingStart; /**< How long is the accounting interval, and when
+ * does it start? */
+ uint64_t AccountingMax; /**< How many bytes do we allow per accounting
+ * interval before hibernation? 0 for "never
+ * hibernate." */
+ /** How do we determine when our AccountingMax has been reached?
+ * "max" for when in or out reaches AccountingMax
+ * "sum" for when in plus out reaches AccountingMax
+ * "in" for when in reaches AccountingMax
+ * "out" for when out reaches AccountingMax */
+ char *AccountingRule_option;
+ enum { ACCT_MAX, ACCT_SUM, ACCT_IN, ACCT_OUT } AccountingRule;
+
+ /** Base64-encoded hash of accepted passwords for the control system. */
+ struct config_line_t *HashedControlPassword;
+ /** As HashedControlPassword, but not saved. */
+ struct config_line_t *HashedControlSessionPassword;
+
+ int CookieAuthentication; /**< Boolean: do we enable cookie-based auth for
+ * the control system? */
+ char *CookieAuthFile; /**< Filesystem location of a ControlPort
+ * authentication cookie. */
+ char *ExtORPortCookieAuthFile; /**< Filesystem location of Extended
+ * ORPort authentication cookie. */
+ int CookieAuthFileGroupReadable; /**< Boolean: Is the CookieAuthFile g+r? */
+ int ExtORPortCookieAuthFileGroupReadable; /**< Boolean: Is the
+ * ExtORPortCookieAuthFile g+r? */
+ int LeaveStreamsUnattached; /**< Boolean: Does Tor attach new streams to
+ * circuits itself (0), or does it expect a controller
+ * to cope? (1) */
+ int DisablePredictedCircuits; /**< Boolean: does Tor preemptively
+ * make circuits in the background (0),
+ * or not (1)? */
+
+ /** Process specifier for a controller that ‘owns’ this Tor
+ * instance. Tor will terminate if its owning controller does. */
+ char *OwningControllerProcess;
+ /** FD specifier for a controller that owns this Tor instance. */
+ int OwningControllerFD;
+
+ int ShutdownWaitLength; /**< When we get a SIGINT and we're a server, how
+ * long do we wait before exiting? */
+ char *SafeLogging; /**< Contains "relay", "1", "0" (meaning no scrubbing). */
+
+ /* Derived from SafeLogging */
+ enum {
+ SAFELOG_SCRUB_ALL, SAFELOG_SCRUB_RELAY, SAFELOG_SCRUB_NONE
+ } SafeLogging_;
+
+ int Sandbox; /**< Boolean: should sandboxing be enabled? */
+ int SafeSocks; /**< Boolean: should we outright refuse application
+ * connections that use socks4 or socks5-with-local-dns? */
+ int ProtocolWarnings; /**< Boolean: when other parties screw up the Tor
+ * protocol, is it a warn or an info in our logs? */
+ int TestSocks; /**< Boolean: when we get a socks connection, do we loudly
+ * log whether it was DNS-leaking or not? */
+ int HardwareAccel; /**< Boolean: Should we enable OpenSSL hardware
+ * acceleration where available? */
+ /** Token Bucket Refill resolution in milliseconds. */
+ int TokenBucketRefillInterval;
+ char *AccelName; /**< Optional hardware acceleration engine name. */
+ char *AccelDir; /**< Optional hardware acceleration engine search dir. */
+
+ /** Boolean: Do we try to enter from a smallish number
+ * of fixed nodes? */
+ int UseEntryGuards_option;
+ /** Internal variable to remember whether we're actually acting on
+ * UseEntryGuards_option -- when we're a non-anonymous Tor2web client or
+ * Single Onion Service, it is always false, otherwise we use the value of
+ * UseEntryGuards_option. */
+ int UseEntryGuards;
+
+ int NumEntryGuards; /**< How many entry guards do we try to establish? */
+
+ /** If 1, we use any guardfraction information we see in the
+ * consensus. If 0, we don't. If -1, let the consensus parameter
+ * decide. */
+ int UseGuardFraction;
+
+ int NumDirectoryGuards; /**< How many dir guards do we try to establish?
+ * If 0, use value from NumEntryGuards. */
+ int NumPrimaryGuards; /**< How many primary guards do we want? */
+
+ int RephistTrackTime; /**< How many seconds do we keep rephist info? */
+ /** Should we always fetch our dir info on the mirror schedule (which
+ * means directly from the authorities) no matter our other config? */
+ int FetchDirInfoEarly;
+
+ /** Should we fetch our dir info at the start of the consensus period? */
+ int FetchDirInfoExtraEarly;
+
+ int DirCache; /**< Cache all directory documents and accept requests via
+ * tunnelled dir conns from clients. If 1, enabled (default);
+ * If 0, disabled. */
+
+ char *VirtualAddrNetworkIPv4; /**< Address and mask to hand out for virtual
+ * MAPADDRESS requests for IPv4 addresses */
+ char *VirtualAddrNetworkIPv6; /**< Address and mask to hand out for virtual
+ * MAPADDRESS requests for IPv6 addresses */
+ int ServerDNSSearchDomains; /**< Boolean: If set, we don't force exit
+ * addresses to be FQDNs, but rather search for them in
+ * the local domains. */
+ int ServerDNSDetectHijacking; /**< Boolean: If true, check for DNS failure
+ * hijacking. */
+ int ServerDNSRandomizeCase; /**< Boolean: Use the 0x20-hack to prevent
+ * DNS poisoning attacks. */
+ char *ServerDNSResolvConfFile; /**< If provided, we configure our internal
+ * resolver from the file here rather than from
+ * /etc/resolv.conf (Unix) or the registry (Windows). */
+ char *DirPortFrontPage; /**< This is a full path to a file with an html
+ disclaimer. This allows a server administrator to show
+ that they're running Tor and anyone visiting their server
+ will know this without any specialized knowledge. */
+ int DisableDebuggerAttachment; /**< Currently Linux only specific attempt to
+ disable ptrace; needs BSD testing. */
+ /** Boolean: if set, we start even if our resolv.conf file is missing
+ * or broken. */
+ int ServerDNSAllowBrokenConfig;
+ /** Boolean: if set, then even connections to private addresses will get
+ * rate-limited. */
+ int CountPrivateBandwidth;
+ /** A list of addresses that definitely should be resolvable. Used for
+ * testing our DNS server. */
+ struct smartlist_t *ServerDNSTestAddresses;
+ int EnforceDistinctSubnets; /**< If true, don't allow multiple routers in the
+ * same network zone in the same circuit. */
+ int AllowNonRFC953Hostnames; /**< If true, we allow connections to hostnames
+ * with weird characters. */
+ /** If true, we try resolving hostnames with weird characters. */
+ int ServerDNSAllowNonRFC953Hostnames;
+
+ /** If true, we try to download extra-info documents (and we serve them,
+ * if we are a cache). For authorities, this is always true. */
+ int DownloadExtraInfo;
+
+ /** If true, we're configured to collect statistics on clients
+ * requesting network statuses from us as directory. */
+ int DirReqStatistics_option;
+ /** Internal variable to remember whether we're actually acting on
+ * DirReqStatistics_option -- yes if it's set and we're a server, else no. */
+ int DirReqStatistics;
+
+ /** If true, the user wants us to collect statistics on port usage. */
+ int ExitPortStatistics;
+
+ /** If true, the user wants us to collect connection statistics. */
+ int ConnDirectionStatistics;
+
+ /** If true, the user wants us to collect cell statistics. */
+ int CellStatistics;
+
+ /** If true, the user wants us to collect padding statistics. */
+ int PaddingStatistics;
+
+ /** If true, the user wants us to collect statistics as entry node. */
+ int EntryStatistics;
+
+ /** If true, the user wants us to collect statistics as hidden service
+ * directory, introduction point, or rendezvous point. */
+ int HiddenServiceStatistics_option;
+ /** Internal variable to remember whether we're actually acting on
+ * HiddenServiceStatistics_option -- yes if it's set and we're a server,
+ * else no. */
+ int HiddenServiceStatistics;
+
+ /** If true, include statistics file contents in extra-info documents. */
+ int ExtraInfoStatistics;
+
+ /** If true, do not believe anybody who tells us that a domain resolves
+ * to an internal address, or that an internal address has a PTR mapping.
+ * Helps avoid some cross-site attacks. */
+ int ClientDNSRejectInternalAddresses;
+
+ /** If true, do not accept any requests to connect to internal addresses
+ * over randomly chosen exits. */
+ int ClientRejectInternalAddresses;
+
+ /** If true, clients may connect over IPv4. If false, they will avoid
+ * connecting over IPv4. We enforce this for OR and Dir connections. */
+ 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
+ * directly. */
+ int ClientUseIPv6;
+ /** If true, prefer an IPv6 OR port over an IPv4 one for entry node
+ * connections. If auto, bridge clients prefer IPv6, and other clients
+ * prefer IPv4. Use node_ipv6_or_preferred() instead of accessing this value
+ * directly. */
+ 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
+ * accessing this value directly. */
+ int ClientPreferIPv6DirPort;
+
+ /** The length of time that we think a consensus should be fresh. */
+ int V3AuthVotingInterval;
+ /** The length of time we think it will take to distribute votes. */
+ int V3AuthVoteDelay;
+ /** The length of time we think it will take to distribute signatures. */
+ int V3AuthDistDelay;
+ /** The number of intervals we think a consensus should be valid. */
+ int V3AuthNIntervalsValid;
+
+ /** Should advertise and sign consensuses with a legacy key, for key
+ * migration purposes? */
+ int V3AuthUseLegacyKey;
+
+ /** Location of bandwidth measurement file */
+ char *V3BandwidthsFile;
+
+ /** Location of guardfraction file */
+ char *GuardfractionFile;
+
+ /** Authority only: key=value pairs that we add to our networkstatus
+ * consensus vote on the 'params' line. */
+ char *ConsensusParams;
+
+ /** Authority only: minimum number of measured bandwidths we must see
+ * before we only believe measured bandwidths to assign flags. */
+ int MinMeasuredBWsForAuthToIgnoreAdvertised;
+
+ /** The length of time that we think an initial consensus should be fresh.
+ * Only altered on testing networks. */
+ int TestingV3AuthInitialVotingInterval;
+
+ /** The length of time we think it will take to distribute initial votes.
+ * Only altered on testing networks. */
+ int TestingV3AuthInitialVoteDelay;
+
+ /** The length of time we think it will take to distribute initial
+ * signatures. Only altered on testing networks.*/
+ int TestingV3AuthInitialDistDelay;
+
+ /** Offset in seconds added to the starting time for consensus
+ voting. Only altered on testing networks. */
+ int TestingV3AuthVotingStartOffset;
+
+ /** If an authority has been around for less than this amount of time, it
+ * does not believe its reachability information is accurate. Only
+ * altered on testing networks. */
+ int TestingAuthDirTimeToLearnReachability;
+
+ /** Clients don't download any descriptor this recent, since it will
+ * probably not have propagated to enough caches. Only altered on testing
+ * networks. */
+ int TestingEstimatedDescriptorPropagationTime;
+
+ /** Schedule for when servers should download things in general. Only
+ * altered on testing networks. */
+ int TestingServerDownloadInitialDelay;
+
+ /** Schedule for when clients should download things in general. Only
+ * altered on testing networks. */
+ int TestingClientDownloadInitialDelay;
+
+ /** Schedule for when servers should download consensuses. Only altered
+ * on testing networks. */
+ int TestingServerConsensusDownloadInitialDelay;
+
+ /** Schedule for when clients should download consensuses. Only altered
+ * on testing networks. */
+ int TestingClientConsensusDownloadInitialDelay;
+
+ /** Schedule for when clients should download consensuses from authorities
+ * if they are bootstrapping (that is, they don't have a usable, reasonably
+ * live consensus). Only used by clients fetching from a list of fallback
+ * directory mirrors.
+ *
+ * This schedule is incremented by (potentially concurrent) connection
+ * attempts, unlike other schedules, which are incremented by connection
+ * failures. Only altered on testing networks. */
+ int ClientBootstrapConsensusAuthorityDownloadInitialDelay;
+
+ /** Schedule for when clients should download consensuses from fallback
+ * directory mirrors if they are bootstrapping (that is, they don't have a
+ * usable, reasonably live consensus). Only used by clients fetching from a
+ * list of fallback directory mirrors.
+ *
+ * This schedule is incremented by (potentially concurrent) connection
+ * attempts, unlike other schedules, which are incremented by connection
+ * failures. Only altered on testing networks. */
+ int ClientBootstrapConsensusFallbackDownloadInitialDelay;
+
+ /** Schedule for when clients should download consensuses from authorities
+ * if they are bootstrapping (that is, they don't have a usable, reasonably
+ * live consensus). Only used by clients which don't have or won't fetch
+ * from a list of fallback directory mirrors.
+ *
+ * This schedule is incremented by (potentially concurrent) connection
+ * attempts, unlike other schedules, which are incremented by connection
+ * failures. Only altered on testing networks. */
+ int ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay;
+
+ /** Schedule for when clients should download bridge descriptors. Only
+ * altered on testing networks. */
+ int TestingBridgeDownloadInitialDelay;
+
+ /** Schedule for when clients should download bridge descriptors when they
+ * have no running bridges. Only altered on testing networks. */
+ int TestingBridgeBootstrapDownloadInitialDelay;
+
+ /** When directory clients have only a few descriptors to request, they
+ * batch them until they have more, or until this amount of time has
+ * passed. Only altered on testing networks. */
+ int TestingClientMaxIntervalWithoutRequest;
+
+ /** How long do we let a directory connection stall before expiring
+ * it? Only altered on testing networks. */
+ int TestingDirConnectionMaxStall;
+
+ /** How many simultaneous in-progress connections will we make when trying
+ * to fetch a consensus before we wait for one to complete, timeout, or
+ * error out? Only altered on testing networks. */
+ int ClientBootstrapConsensusMaxInProgressTries;
+
+ /** If true, we take part in a testing network. Change the defaults of a
+ * couple of other configuration options and allow to change the values
+ * of certain configuration options. */
+ int TestingTorNetwork;
+
+ /** Minimum value for the Exit flag threshold on testing networks. */
+ uint64_t TestingMinExitFlagThreshold;
+
+ /** Minimum value for the Fast flag threshold on testing networks. */
+ uint64_t TestingMinFastFlagThreshold;
+
+ /** Relays in a testing network which should be voted Exit
+ * regardless of exit policy. */
+ routerset_t *TestingDirAuthVoteExit;
+ int TestingDirAuthVoteExitIsStrict;
+
+ /** Relays in a testing network which should be voted Guard
+ * regardless of uptime and bandwidth. */
+ routerset_t *TestingDirAuthVoteGuard;
+ int TestingDirAuthVoteGuardIsStrict;
+
+ /** Relays in a testing network which should be voted HSDir
+ * regardless of uptime and DirPort. */
+ routerset_t *TestingDirAuthVoteHSDir;
+ int TestingDirAuthVoteHSDirIsStrict;
+
+ /** Enable CONN_BW events. Only altered on testing networks. */
+ int TestingEnableConnBwEvent;
+
+ /** Enable CELL_STATS events. Only altered on testing networks. */
+ int TestingEnableCellStatsEvent;
+
+ /** If true, and we have GeoIP data, and we're a bridge, keep a per-country
+ * count of how many client addresses have contacted us so that we can help
+ * the bridge authority guess which countries have blocked access to us. */
+ int BridgeRecordUsageByCountry;
+
+ /** Optionally, IPv4 and IPv6 GeoIP data. */
+ char *GeoIPFile;
+ char *GeoIPv6File;
+
+ /** Autobool: if auto, then any attempt to Exclude{Exit,}Nodes a particular
+ * country code will exclude all nodes in ?? and A1. If true, all nodes in
+ * ?? and A1 are excluded. Has no effect if we don't know any GeoIP data. */
+ int GeoIPExcludeUnknown;
+
+ /** If true, SIGHUP should reload the torrc. Sometimes controllers want
+ * to make this false. */
+ int ReloadTorrcOnSIGHUP;
+
+ /* The main parameter for picking circuits within a connection.
+ *
+ * If this value is positive, when picking a cell to relay on a connection,
+ * we always relay from the circuit whose weighted cell count is lowest.
+ * Cells are weighted exponentially such that if one cell is sent
+ * 'CircuitPriorityHalflife' seconds before another, it counts for half as
+ * much.
+ *
+ * If this value is zero, we're disabling the cell-EWMA algorithm.
+ *
+ * If this value is negative, we're using the default approach
+ * according to either Tor or a parameter set in the consensus.
+ */
+ double CircuitPriorityHalflife;
+
+ /** Set to true if the TestingTorNetwork configuration option is set.
+ * This is used so that options_validate() has a chance to realize that
+ * the defaults have changed. */
+ int UsingTestNetworkDefaults_;
+
+ /** If 1, we try to use microdescriptors to build circuits. If 0, we don't.
+ * If -1, Tor decides. */
+ int UseMicrodescriptors;
+
+ /** File where we should write the ControlPort. */
+ char *ControlPortWriteToFile;
+ /** Should that file be group-readable? */
+ int ControlPortFileGroupReadable;
+
+#define MAX_MAX_CLIENT_CIRCUITS_PENDING 1024
+ /** Maximum number of non-open general-purpose origin circuits to allow at
+ * 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;
+
+ /**
+ * Parameters for path-bias detection.
+ * @{
+ * These options override the default behavior of Tor's (**currently
+ * experimental**) path bias detection algorithm. To try to find broken or
+ * misbehaving guard nodes, Tor looks for nodes where more than a certain
+ * fraction of circuits through that guard fail to get built.
+ *
+ * The PathBiasCircThreshold option controls how many circuits we need to
+ * build through a guard before we make these checks. The
+ * PathBiasNoticeRate, PathBiasWarnRate and PathBiasExtremeRate options
+ * control what fraction of circuits must succeed through a guard so we
+ * won't write log messages. If less than PathBiasExtremeRate circuits
+ * succeed *and* PathBiasDropGuards is set to 1, we disable use of that
+ * guard.
+ *
+ * When we have seen more than PathBiasScaleThreshold circuits through a
+ * guard, we scale our observations by 0.5 (governed by the consensus) so
+ * that new observations don't get swamped by old ones.
+ *
+ * By default, or if a negative value is provided for one of these options,
+ * Tor uses reasonable defaults from the networkstatus consensus document.
+ * If no defaults are available there, these options default to 150, .70,
+ * .50, .30, 0, and 300 respectively.
+ */
+ int PathBiasCircThreshold;
+ double PathBiasNoticeRate;
+ double PathBiasWarnRate;
+ double PathBiasExtremeRate;
+ int PathBiasDropGuards;
+ int PathBiasScaleThreshold;
+ /** @} */
+
+ /**
+ * Parameters for path-bias use detection
+ * @{
+ * Similar to the above options, these options override the default behavior
+ * of Tor's (**currently experimental**) path use bias detection algorithm.
+ *
+ * Where as the path bias parameters govern thresholds for successfully
+ * building circuits, these four path use bias parameters govern thresholds
+ * only for circuit usage. Circuits which receive no stream usage are not
+ * counted by this detection algorithm. A used circuit is considered
+ * successful if it is capable of carrying streams or otherwise receiving
+ * well-formed responses to RELAY cells.
+ *
+ * By default, or if a negative value is provided for one of these options,
+ * Tor uses reasonable defaults from the networkstatus consensus document.
+ * If no defaults are available there, these options default to 20, .80,
+ * .60, and 100, respectively.
+ */
+ int PathBiasUseThreshold;
+ double PathBiasNoticeUseRate;
+ double PathBiasExtremeUseRate;
+ int PathBiasScaleUseThreshold;
+ /** @} */
+
+ int IPv6Exit; /**< Do we support exiting to IPv6 addresses? */
+
+ /** Fraction: */
+ double PathsNeededToBuildCircuits;
+
+ /** What expiry time shall we place on our SSL certs? "0" means we
+ * should guess a suitable value. */
+ int SSLKeyLifetime;
+
+ /** How long (seconds) do we keep a guard before picking a new one? */
+ int GuardLifetime;
+
+ /** Is this an exit node? This is a tristate, where "1" means "yes, and use
+ * the default exit policy if none is given" and "0" means "no; exit policy
+ * is 'reject *'" and "auto" (-1) means "same as 1, but warn the user."
+ *
+ * XXXX Eventually, the default will be 0. */
+ int ExitRelay;
+
+ /** For how long (seconds) do we declare our signing keys to be valid? */
+ int SigningKeyLifetime;
+ /** For how long (seconds) do we declare our link keys to be valid? */
+ int TestingLinkCertLifetime;
+ /** For how long (seconds) do we declare our auth keys to be valid? */
+ int TestingAuthKeyLifetime;
+
+ /** How long before signing keys expire will we try to make a new one? */
+ int TestingSigningKeySlop;
+ /** How long before link keys expire will we try to make a new one? */
+ int TestingLinkKeySlop;
+ /** How long before auth keys expire will we try to make a new one? */
+ int TestingAuthKeySlop;
+
+ /** Force use of offline master key features: never generate a master
+ * ed25519 identity key except from tor --keygen */
+ int OfflineMasterKey;
+
+ enum {
+ FORCE_PASSPHRASE_AUTO=0,
+ FORCE_PASSPHRASE_ON,
+ FORCE_PASSPHRASE_OFF
+ } keygen_force_passphrase;
+ int use_keygen_passphrase_fd;
+ int keygen_passphrase_fd;
+ int change_key_passphrase;
+ char *master_key_fname;
+
+ /** Autobool: Do we try to retain capabilities if we can? */
+ int KeepBindCapabilities;
+
+ /** Maximum total size of unparseable descriptors to log during the
+ * lifetime of this Tor process.
+ */
+ uint64_t MaxUnparseableDescSizeToLog;
+
+ /** Bool (default: 1): Switch for the shared random protocol. Only
+ * relevant to a directory authority. If off, the authority won't
+ * participate in the protocol. If on (default), a flag is added to the
+ * vote indicating participation. */
+ int AuthDirSharedRandomness;
+
+ /** If 1, we skip all OOS checks. */
+ int DisableOOSCheck;
+
+ /** Autobool: Should we include Ed25519 identities in extend2 cells?
+ * If -1, we should do whatever the consensus parameter says. */
+ int ExtendByEd25519ID;
+
+ /** Bool (default: 1): When testing routerinfos as a directory authority,
+ * do we enforce Ed25519 identity match? */
+ /* NOTE: remove this option someday. */
+ int AuthDirTestEd25519LinkKeys;
+
+ /** Bool (default: 0): Tells if a %include was used on torrc */
+ int IncludeUsed;
+
+ /** The seconds after expiration which we as a relay should keep old
+ * consensuses around so that we can generate diffs from them. If 0,
+ * use the default. */
+ int MaxConsensusAgeForDiffs;
+
+ /** Bool (default: 0). Tells Tor to never try to exec another program.
+ */
+ int NoExec;
+
+ /** Have the KIST scheduler run every X milliseconds. If less than zero, do
+ * not use the KIST scheduler but use the old vanilla scheduler instead. If
+ * zero, do what the consensus says and fall back to using KIST as if this is
+ * set to "10 msec" if the consensus doesn't say anything. */
+ int KISTSchedRunInterval;
+
+ /** A multiplier for the KIST per-socket limit calculation. */
+ double KISTSockBufSizeFactor;
+
+ /** The list of scheduler type string ordered by priority that is first one
+ * has to be tried first. Default: KIST,KISTLite,Vanilla */
+ struct smartlist_t *Schedulers;
+ /* An ordered list of scheduler_types mapped from Schedulers. */
+ struct smartlist_t *SchedulerTypes_;
+
+ /** List of files that were opened by %include in torrc and torrc-defaults */
+ struct smartlist_t *FilesOpenedByIncludes;
+
+ /** If true, Tor shouldn't install any posix signal handlers, since it is
+ * running embedded inside another process.
+ */
+ int DisableSignalHandlers;
+
+ /** Autobool: Is the circuit creation DoS mitigation subsystem enabled? */
+ int DoSCircuitCreationEnabled;
+ /** Minimum concurrent connection needed from one single address before any
+ * defense is used. */
+ int DoSCircuitCreationMinConnections;
+ /** Circuit rate used to refill the token bucket. */
+ int DoSCircuitCreationRate;
+ /** 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
+ * 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
+ * address. A random time delta is added to the defense time of an address
+ * which will be between 1 second and half of this value. */
+ int DoSCircuitCreationDefenseTimePeriod;
+
+ /** Autobool: Is the DoS connection mitigation subsystem enabled? */
+ int DoSConnectionEnabled;
+ /** Maximum concurrent connection allowed per address. */
+ int DoSConnectionMaxConcurrentCount;
+ /** When an address is reaches the maximum count, what defense should be
+ * used against it. See the dos_conn_defense_type_t enum. */
+ int DoSConnectionDefenseType;
+
+ /** Autobool: Do we refuse single hop client rendezvous? */
+ int DoSRefuseSingleHopClientRendezvous;
+};
+
+#endif
diff --git a/src/app/config/or_state_st.h b/src/app/config/or_state_st.h
new file mode 100644
index 0000000000..f1d5f981f1
--- /dev/null
+++ b/src/app/config/or_state_st.h
@@ -0,0 +1,86 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_OR_STATE_ST_H
+#define TOR_OR_STATE_ST_H
+
+#include "lib/cc/torint.h"
+struct smartlist_t;
+
+/** Persistent state for an onion router, as saved to disk. */
+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
+ * should be saved right away. */
+ time_t next_write;
+
+ /** When was the state last written to disk? */
+ time_t LastWritten;
+
+ /** Fields for accounting bandwidth use. */
+ time_t AccountingIntervalStart;
+ uint64_t AccountingBytesReadInInterval;
+ uint64_t AccountingBytesWrittenInInterval;
+ int AccountingSecondsActive;
+ int AccountingSecondsToReachSoftLimit;
+ time_t AccountingSoftLimitHitAt;
+ 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) */
+ 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,
+ * of the entries of Values. The "Values" lists hold decimal string
+ * representations of the number of bytes read or written in each
+ * interval. The "Maxima" list holds decimal strings describing the highest
+ * rate achieved during the interval.
+ */
+ time_t BWHistoryReadEnds;
+ int BWHistoryReadInterval;
+ struct smartlist_t *BWHistoryReadValues;
+ struct smartlist_t *BWHistoryReadMaxima;
+ time_t BWHistoryWriteEnds;
+ int BWHistoryWriteInterval;
+ struct smartlist_t *BWHistoryWriteValues;
+ struct smartlist_t *BWHistoryWriteMaxima;
+ time_t BWHistoryDirReadEnds;
+ int BWHistoryDirReadInterval;
+ struct smartlist_t *BWHistoryDirReadValues;
+ struct smartlist_t *BWHistoryDirReadMaxima;
+ time_t BWHistoryDirWriteEnds;
+ int BWHistoryDirWriteInterval;
+ struct smartlist_t *BWHistoryDirWriteValues;
+ struct smartlist_t *BWHistoryDirWriteMaxima;
+
+ /** Build time histogram */
+ struct config_line_t * BuildtimeHistogram;
+ int TotalBuildTimes;
+ int CircuitBuildAbandonedCount;
+
+ /** What version of Tor wrote this state file? */
+ char *TorVersion;
+
+ /** Holds any unrecognized values we found in the state file, in the order
+ * in which we found them. */
+ struct config_line_t *ExtraLines;
+
+ /** When did we last rotate our onion key? "0" for 'no idea'. */
+ time_t LastRotatedOnionKey;
+};
+
+#endif
diff --git a/src/or/statefile.c b/src/app/config/statefile.c
index c81ea44e06..8eeef45026 100644
--- a/src/or/statefile.c
+++ b/src/app/config/statefile.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -29,19 +29,26 @@
*/
#define STATEFILE_PRIVATE
-#include "or.h"
-#include "circuitstats.h"
-#include "config.h"
-#include "confparse.h"
-#include "connection.h"
-#include "control.h"
-#include "entrynodes.h"
-#include "hibernate.h"
-#include "main.h"
-#include "rephist.h"
-#include "router.h"
-#include "sandbox.h"
-#include "statefile.h"
+#include "core/or/or.h"
+#include "core/or/circuitstats.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "core/mainloop/connection.h"
+#include "feature/control/control.h"
+#include "feature/client/entrynodes.h"
+#include "feature/hibernate/hibernate.h"
+#include "core/mainloop/main.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "lib/sandbox/sandbox.h"
+#include "app/config/statefile.h"
+#include "lib/encoding/confline.h"
+
+#include "app/config/or_state_st.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
/** A list of state-file "abbreviations," for compatibility. */
static config_abbrev_t state_abbrevs_[] = {
@@ -708,4 +715,3 @@ or_state_free_all(void)
or_state_free(global_state);
global_state = NULL;
}
-
diff --git a/src/or/statefile.h b/src/app/config/statefile.h
index 5aa2ca9320..e996d5b6e6 100644
--- a/src/or/statefile.h
+++ b/src/app/config/statefile.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_STATEFILE_H
@@ -20,11 +20,11 @@ void or_state_free_all(void);
void or_state_mark_dirty(or_state_t *state, time_t when);
#ifdef STATEFILE_PRIVATE
-STATIC config_line_t *get_transport_in_state_by_name(const char *transport);
+STATIC struct config_line_t *get_transport_in_state_by_name(
+ const char *transport);
STATIC void or_state_free_(or_state_t *state);
#define or_state_free(st) FREE_AND_NULL(or_state_t, or_state_free_, (st))
STATIC or_state_t *or_state_new(void);
#endif
#endif /* !defined(TOR_STATEFILE_H) */
-
diff --git a/src/app/include.am b/src/app/include.am
new file mode 100644
index 0000000000..7cf20191ab
--- /dev/null
+++ b/src/app/include.am
@@ -0,0 +1,35 @@
+
+bin_PROGRAMS+= src/app/tor
+
+if COVERAGE_ENABLED
+noinst_PROGRAMS+= src/app/tor-cov
+endif
+
+noinst_HEADERS += \
+ src/app/main/ntmain.h
+
+src_app_tor_SOURCES = src/app/main/tor_main.c
+
+# -L flags need to go in LDFLAGS. -l flags need to go in LDADD.
+# 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_openssl@ @TOR_LDFLAGS_libevent@
+src_app_tor_LDADD = $(TOR_INTERNAL_LIBS) \
+ $(rust_ldadd) \
+ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
+ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
+ @CURVE25519_LIBS@ @TOR_SYSTEMD_LIBS@ \
+ @TOR_LZMA_LIBS@ @TOR_ZSTD_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_openssl@ @TOR_LDFLAGS_libevent@
+src_app_tor_cov_LDADD = $(TOR_INTERNAL_TESTING_LIBS) \
+ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
+ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ \
+ @CURVE25519_LIBS@ @TOR_SYSTEMD_LIBS@ \
+ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
+endif
diff --git a/src/or/ntmain.c b/src/app/main/ntmain.c
index e9a299807a..232529a803 100644
--- a/src/or/ntmain.c
+++ b/src/app/main/ntmain.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,10 +19,13 @@
#ifdef _WIN32
-#include "or.h"
-#include "config.h"
-#include "main.h"
-#include "ntmain.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "core/mainloop/main.h"
+#include "app/main/ntmain.h"
+#include "lib/log/win32err.h"
+#include "lib/fs/winlib.h"
+#include "lib/evloop/compat_libevent.h"
#include <windows.h>
#define GENSRV_SERVICENAME "tor"
@@ -778,4 +781,3 @@ nt_service_parse_options(int argc, char **argv, int *should_exit)
}
#endif /* defined(_WIN32) */
-
diff --git a/src/or/ntmain.h b/src/app/main/ntmain.h
index 81b7159855..223d9e318b 100644
--- a/src/or/ntmain.h
+++ b/src/app/main/ntmain.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/or/tor_main.c b/src/app/main/tor_main.c
index 703669ac99..8c497fff8a 100644
--- a/src/or/tor_main.c
+++ b/src/app/main/tor_main.c
@@ -1,6 +1,6 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/common/Makefile.nmake b/src/common/Makefile.nmake
deleted file mode 100644
index a1c819fffa..0000000000
--- a/src/common/Makefile.nmake
+++ /dev/null
@@ -1,28 +0,0 @@
-all: libor.lib libor-crypto.lib libor-event.lib
-
-CFLAGS = /O2 /MT /I ..\win32 /I ..\..\..\build-alpha\include /I ..\common \
- /I ..\ext
-
-LIBOR_OBJECTS = address.obj backtrace.obj compat.obj container.obj di_ops.obj \
- log.obj memarea.obj mempool.obj procmon.obj sandbox.obj util.obj \
- util_codedigest.obj
-
-LIBOR_CRYPTO_OBJECTS = aes.obj crypto.obj crypto_format.obj compress.obj compress_zlib.obj \
- tortls.obj crypto_curve25519.obj curve25519-donna.obj
-
-LIBOR_EVENT_OBJECTS = compat_libevent.obj
-
-curve25519-donna.obj: ..\ext\curve25519_donna\curve25519-donna.c
- $(CC) $(CFLAGS) /D inline=_inline /c ..\ext\curve25519_donna\curve25519-donna.c
-
-libor.lib: $(LIBOR_OBJECTS)
- lib $(LIBOR_OBJECTS) /out:libor.lib
-
-libor-crypto.lib: $(LIBOR_CRYPTO_OBJECTS)
- lib $(LIBOR_CRYPTO_OBJECTS) /out:libor-crypto.lib
-
-libor-event.lib: $(LIBOR_EVENT_OBJECTS)
- lib $(LIBOR_EVENT_OBJECTS) /out:libor-event.lib
-
-clean:
- del *.obj *.lib libor*.lib
diff --git a/src/common/address_set.c b/src/common/address_set.c
deleted file mode 100644
index b2f4bb4c95..0000000000
--- a/src/common/address_set.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file address_set.c
- * \brief Implementation for a set of addresses.
- *
- * This module was first written on a semi-emergency basis to improve the
- * robustness of the anti-DoS module. As such, it's written in a pretty
- * conservative way, and should be susceptible to improvement later on.
- **/
-
-#include "orconfig.h"
-#include "address_set.h"
-#include "address.h"
-#include "compat.h"
-#include "container.h"
-#include "crypto_rand.h"
-#include "util.h"
-#include "siphash.h"
-
-/** How many 64-bit siphash values to extract per address */
-#define N_HASHES 2
-/** How many bloom-filter bits we set per address. This is twice the N_HASHES
- * value, since we split the siphash output into two 32-bit values. */
-#define N_BITS_PER_ITEM (N_HASHES * 2)
-
-/* XXXX This code is largely duplicated with digestset_t. We should merge
- * them together into a common bloom-filter implementation. I'm keeping
- * them separate for now, though, since this module needs to be backported
- * all the way to 0.2.9.
- *
- * The main difference between digestset_t and this code is that we use
- * independent siphashes rather than messing around with bit-shifts. The
- * approach here is probably more sound, and we should prefer it if&when we
- * unify the implementations.
- */
-
-struct address_set_t {
- /** siphash keys to make N_HASHES independent hashes for each address. */
- struct sipkey key[N_HASHES];
- int mask; /**< One less than the number of bits in <b>ba</b>; always one less
- * than a power of two. */
- bitarray_t *ba; /**< A bit array to implement the Bloom filter. */
-};
-
-/**
- * Allocate and return an address_set, suitable for holding up to
- * <b>max_address_guess</b> distinct values.
- */
-address_set_t *
-address_set_new(int max_addresses_guess)
-{
- /* See digestset_new() for rationale on this equation. */
- int n_bits = 1u << (tor_log2(max_addresses_guess)+5);
-
- address_set_t *set = tor_malloc_zero(sizeof(address_set_t));
- set->mask = n_bits - 1;
- set->ba = bitarray_init_zero(n_bits);
- crypto_rand((char*) set->key, sizeof(set->key));
-
- return set;
-}
-
-/**
- * Release all storage associated with <b>set</b>.
- */
-void
-address_set_free(address_set_t *set)
-{
- if (! set)
- return;
-
- bitarray_free(set->ba);
- tor_free(set);
-}
-
-/** Yield the bit index corresponding to 'val' for set. */
-#define BIT(set, val) ((val) & (set)->mask)
-
-/**
- * Add <b>addr</b> to <b>set</b>.
- *
- * All future queries for <b>addr</b> in set will return true. Removing
- * items is not possible.
- */
-void
-address_set_add(address_set_t *set, const struct tor_addr_t *addr)
-{
- int i;
- for (i = 0; i < N_HASHES; ++i) {
- uint64_t h = tor_addr_keyed_hash(&set->key[i], addr);
- uint32_t high_bits = (uint32_t)(h >> 32);
- uint32_t low_bits = (uint32_t)(h);
- bitarray_set(set->ba, BIT(set, high_bits));
- bitarray_set(set->ba, BIT(set, low_bits));
- }
-}
-
-/** As address_set_add(), but take an ipv4 address in host order. */
-void
-address_set_add_ipv4h(address_set_t *set, uint32_t addr)
-{
- tor_addr_t a;
- tor_addr_from_ipv4h(&a, addr);
- address_set_add(set, &a);
-}
-
-/**
- * Return true if <b>addr</b> is a member of <b>set</b>. (And probably,
- * return false if <b>addr</b> is not a member of set.)
- */
-int
-address_set_probably_contains(address_set_t *set,
- const struct tor_addr_t *addr)
-{
- int i, matches = 0;
- for (i = 0; i < N_HASHES; ++i) {
- uint64_t h = tor_addr_keyed_hash(&set->key[i], addr);
- uint32_t high_bits = (uint32_t)(h >> 32);
- uint32_t low_bits = (uint32_t)(h);
- // Note that !! is necessary here, since bitarray_is_set does not
- // necessarily return 1 on true.
- matches += !! bitarray_is_set(set->ba, BIT(set, high_bits));
- matches += !! bitarray_is_set(set->ba, BIT(set, low_bits));
- }
- return matches == N_BITS_PER_ITEM;
-}
-
diff --git a/src/common/compat.c b/src/common/compat.c
deleted file mode 100644
index 6fdd6ecf00..0000000000
--- a/src/common/compat.c
+++ /dev/null
@@ -1,3531 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file compat.c
- * \brief Wrappers to make calls more portable. This code defines
- * functions such as tor_snprintf, get/set various data types,
- * renaming, setting socket options, switching user IDs. It is basically
- * where the non-portable items are conditionally included depending on
- * the platform.
- **/
-
-#define COMPAT_PRIVATE
-#include "compat.h"
-
-#ifdef _WIN32
-#include <winsock2.h>
-#include <windows.h>
-#include <sys/locking.h>
-#endif
-
-#ifdef HAVE_UNAME
-#include <sys/utsname.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_SYSCTL_H
-#include <sys/sysctl.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#endif
-#ifdef HAVE_SYS_UTIME_H
-#include <sys/utime.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_FCNTL_H
-#include <sys/fcntl.h>
-#endif
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-#ifdef HAVE_GRP_H
-#include <grp.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef HAVE_CRT_EXTERNS_H
-#include <crt_externs.h>
-#endif
-#ifdef HAVE_SYS_STATVFS_H
-#include <sys/statvfs.h>
-#endif
-#ifdef HAVE_SYS_CAPABILITY_H
-#include <sys/capability.h>
-#endif
-
-#ifdef _WIN32
-#include <conio.h>
-#include <wchar.h>
-/* Some mingw headers lack these. :p */
-#if defined(HAVE_DECL__GETWCH) && !HAVE_DECL__GETWCH
-wint_t _getwch(void);
-#endif
-#ifndef WEOF
-#define WEOF (wchar_t)(0xFFFF)
-#endif
-#if defined(HAVE_DECL_SECUREZEROMEMORY) && !HAVE_DECL_SECUREZEROMEMORY
-static inline void
-SecureZeroMemory(PVOID ptr, SIZE_T cnt)
-{
- volatile char *vcptr = (volatile char*)ptr;
- while (cnt--)
- *vcptr++ = 0;
-}
-#endif /* defined(HAVE_DECL_SECUREZEROMEMORY) && !HAVE_DECL_SECUREZEROMEMORY */
-#elif defined(HAVE_READPASSPHRASE_H)
-#include <readpassphrase.h>
-#else
-#include "tor_readpassphrase.h"
-#endif /* defined(_WIN32) || ... */
-
-/* Includes for the process attaching prevention */
-#if defined(HAVE_SYS_PRCTL_H) && defined(__linux__)
-/* Only use the linux prctl; the IRIX prctl is totally different */
-#include <sys/prctl.h>
-#elif defined(__APPLE__)
-#include <sys/ptrace.h>
-#endif /* defined(HAVE_SYS_PRCTL_H) && defined(__linux__) || ... */
-
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h> /* FreeBSD needs this to know what version it is */
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#ifdef HAVE_MMAP
-#include <sys/mman.h>
-#endif
-#ifdef HAVE_SYS_SYSLIMITS_H
-#include <sys/syslimits.h>
-#endif
-#ifdef HAVE_SYS_FILE_H
-#include <sys/file.h>
-#endif
-
-#include "torlog.h"
-#include "util.h"
-#include "container.h"
-#include "address.h"
-#include "sandbox.h"
-
-/* Inline the strl functions if the platform doesn't have them. */
-#ifndef HAVE_STRLCPY
-#include "strlcpy.c"
-#endif
-#ifndef HAVE_STRLCAT
-#include "strlcat.c"
-#endif
-
-/* When set_max_file_descriptors() is called, update this with the max file
- * descriptor value so we can use it to check the limit when opening a new
- * socket. Default value is what Debian sets as the default hard limit. */
-static int max_sockets = 1024;
-
-/** As open(path, flags, mode), but return an fd with the close-on-exec mode
- * set. */
-int
-tor_open_cloexec(const char *path, int flags, unsigned mode)
-{
- int fd;
- const char *p = sandbox_intern_string(path);
-#ifdef O_CLOEXEC
- fd = open(p, flags|O_CLOEXEC, mode);
- if (fd >= 0)
- return fd;
- /* If we got an error, see if it is EINVAL. EINVAL might indicate that,
- * even though we were built on a system with O_CLOEXEC support, we
- * are running on one without. */
- if (errno != EINVAL)
- return -1;
-#endif /* defined(O_CLOEXEC) */
-
- log_debug(LD_FS, "Opening %s with flags %x", p, flags);
- fd = open(p, flags, mode);
-#ifdef FD_CLOEXEC
- if (fd >= 0) {
- if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
- log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
- close(fd);
- return -1;
- }
- }
-#endif /* defined(FD_CLOEXEC) */
- return fd;
-}
-
-/** As fopen(path,mode), but ensures that the O_CLOEXEC bit is set on the
- * underlying file handle. */
-FILE *
-tor_fopen_cloexec(const char *path, const char *mode)
-{
- FILE *result = fopen(path, mode);
-#ifdef FD_CLOEXEC
- if (result != NULL) {
- if (fcntl(fileno(result), F_SETFD, FD_CLOEXEC) == -1) {
- log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
- fclose(result);
- return NULL;
- }
- }
-#endif /* defined(FD_CLOEXEC) */
- return result;
-}
-
-/** As rename(), but work correctly with the sandbox. */
-int
-tor_rename(const char *path_old, const char *path_new)
-{
- log_debug(LD_FS, "Renaming %s to %s", path_old, path_new);
- return rename(sandbox_intern_string(path_old),
- sandbox_intern_string(path_new));
-}
-
-#if defined(HAVE_MMAP) || defined(RUNNING_DOXYGEN)
-/** Try to create a memory mapping for <b>filename</b> and return it. On
- * failure, return NULL. Sets errno properly, using ERANGE to mean
- * "empty file". Must only be called on trusted Tor-owned files, as changing
- * the underlying file's size causes unspecified behavior. */
-tor_mmap_t *
-tor_mmap_file(const char *filename)
-{
- int fd; /* router file */
- char *string;
- int result;
- tor_mmap_t *res;
- size_t size, filesize;
- struct stat st;
-
- tor_assert(filename);
-
- fd = tor_open_cloexec(filename, O_RDONLY, 0);
- if (fd<0) {
- int save_errno = errno;
- int severity = (errno == ENOENT) ? LOG_INFO : LOG_WARN;
- log_fn(severity, LD_FS,"Could not open \"%s\" for mmap(): %s",filename,
- strerror(errno));
- errno = save_errno;
- return NULL;
- }
-
- /* Get the size of the file */
- result = fstat(fd, &st);
- if (result != 0) {
- int save_errno = errno;
- log_warn(LD_FS,
- "Couldn't fstat opened descriptor for \"%s\" during mmap: %s",
- filename, strerror(errno));
- close(fd);
- errno = save_errno;
- return NULL;
- }
- size = filesize = (size_t)(st.st_size);
-
- if (st.st_size > SSIZE_T_CEILING || (off_t)size < st.st_size) {
- log_warn(LD_FS, "File \"%s\" is too large. Ignoring.",filename);
- errno = EFBIG;
- close(fd);
- return NULL;
- }
- if (!size) {
- /* Zero-length file. If we call mmap on it, it will succeed but
- * return NULL, and bad things will happen. So just fail. */
- log_info(LD_FS,"File \"%s\" is empty. Ignoring.",filename);
- errno = ERANGE;
- close(fd);
- return NULL;
- }
-
- string = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
- close(fd);
- if (string == MAP_FAILED) {
- int save_errno = errno;
- log_warn(LD_FS,"Could not mmap file \"%s\": %s", filename,
- strerror(errno));
- errno = save_errno;
- return NULL;
- }
-
- res = tor_malloc_zero(sizeof(tor_mmap_t));
- res->data = string;
- res->size = filesize;
- res->mapping_size = size;
-
- return res;
-}
-/** Release storage held for a memory mapping; returns 0 on success,
- * or -1 on failure (and logs a warning). */
-int
-tor_munmap_file(tor_mmap_t *handle)
-{
- int res;
-
- if (handle == NULL)
- return 0;
-
- res = munmap((char*)handle->data, handle->mapping_size);
- if (res == 0) {
- /* munmap() succeeded */
- tor_free(handle);
- } else {
- log_warn(LD_FS, "Failed to munmap() in tor_munmap_file(): %s",
- strerror(errno));
- res = -1;
- }
-
- return res;
-}
-#elif defined(_WIN32)
-tor_mmap_t *
-tor_mmap_file(const char *filename)
-{
- TCHAR tfilename[MAX_PATH]= {0};
- tor_mmap_t *res = tor_malloc_zero(sizeof(tor_mmap_t));
- int empty = 0;
- HANDLE file_handle = INVALID_HANDLE_VALUE;
- DWORD size_low, size_high;
- uint64_t real_size;
- res->mmap_handle = NULL;
-#ifdef UNICODE
- mbstowcs(tfilename,filename,MAX_PATH);
-#else
- strlcpy(tfilename,filename,MAX_PATH);
-#endif
- file_handle = CreateFile(tfilename,
- GENERIC_READ, FILE_SHARE_READ,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- 0);
-
- if (file_handle == INVALID_HANDLE_VALUE)
- goto win_err;
-
- size_low = GetFileSize(file_handle, &size_high);
-
- if (size_low == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) {
- log_warn(LD_FS,"Error getting size of \"%s\".",filename);
- goto win_err;
- }
- if (size_low == 0 && size_high == 0) {
- log_info(LD_FS,"File \"%s\" is empty. Ignoring.",filename);
- empty = 1;
- goto err;
- }
- real_size = (((uint64_t)size_high)<<32) | size_low;
- if (real_size > SIZE_MAX) {
- log_warn(LD_FS,"File \"%s\" is too big to map; not trying.",filename);
- goto err;
- }
- res->size = real_size;
-
- res->mmap_handle = CreateFileMapping(file_handle,
- NULL,
- PAGE_READONLY,
- size_high,
- size_low,
- NULL);
- if (res->mmap_handle == NULL)
- goto win_err;
- res->data = (char*) MapViewOfFile(res->mmap_handle,
- FILE_MAP_READ,
- 0, 0, 0);
- if (!res->data)
- goto win_err;
-
- CloseHandle(file_handle);
- return res;
- win_err: {
- DWORD e = GetLastError();
- int severity = (e == ERROR_FILE_NOT_FOUND || e == ERROR_PATH_NOT_FOUND) ?
- LOG_INFO : LOG_WARN;
- char *msg = format_win32_error(e);
- log_fn(severity, LD_FS, "Couldn't mmap file \"%s\": %s", filename, msg);
- tor_free(msg);
- if (e == ERROR_FILE_NOT_FOUND || e == ERROR_PATH_NOT_FOUND)
- errno = ENOENT;
- else
- errno = EINVAL;
- }
- err:
- if (empty)
- errno = ERANGE;
- if (file_handle != INVALID_HANDLE_VALUE)
- CloseHandle(file_handle);
- tor_munmap_file(res);
- return NULL;
-}
-
-/* Unmap the file, and return 0 for success or -1 for failure */
-int
-tor_munmap_file(tor_mmap_t *handle)
-{
- if (handle == NULL)
- return 0;
-
- if (handle->data) {
- /* This is an ugly cast, but without it, "data" in struct tor_mmap_t would
- have to be redefined as non-const. */
- BOOL ok = UnmapViewOfFile( (LPVOID) handle->data);
- if (!ok) {
- log_warn(LD_FS, "Failed to UnmapViewOfFile() in tor_munmap_file(): %d",
- (int)GetLastError());
- }
- }
-
- if (handle->mmap_handle != NULL)
- CloseHandle(handle->mmap_handle);
- tor_free(handle);
-
- return 0;
-}
-#else
-#error "cannot implement tor_mmap_file"
-#endif /* defined(HAVE_MMAP) || ... || ... */
-
-/** Replacement for snprintf. Differs from platform snprintf in two
- * ways: First, always NUL-terminates its output. Second, always
- * returns -1 if the result is truncated. (Note that this return
- * behavior does <i>not</i> conform to C99; it just happens to be
- * easier to emulate "return -1" with conformant implementations than
- * it is to emulate "return number that would be written" with
- * non-conformant implementations.) */
-int
-tor_snprintf(char *str, size_t size, const char *format, ...)
-{
- va_list ap;
- int r;
- va_start(ap,format);
- r = tor_vsnprintf(str,size,format,ap);
- va_end(ap);
- return r;
-}
-
-/** Replacement for vsnprintf; behavior differs as tor_snprintf differs from
- * snprintf.
- */
-int
-tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
-{
- int r;
- if (size == 0)
- return -1; /* no place for the NUL */
- if (size > SIZE_T_CEILING)
- return -1;
-#ifdef _WIN32
- r = _vsnprintf(str, size, format, args);
-#else
- r = vsnprintf(str, size, format, args);
-#endif
- str[size-1] = '\0';
- if (r < 0 || r >= (ssize_t)size)
- return -1;
- return r;
-}
-
-/**
- * Portable asprintf implementation. Does a printf() into a newly malloc'd
- * string. Sets *<b>strp</b> to this string, and returns its length (not
- * including the terminating NUL character).
- *
- * You can treat this function as if its implementation were something like
- <pre>
- char buf[_INFINITY_];
- tor_snprintf(buf, sizeof(buf), fmt, args);
- *strp = tor_strdup(buf);
- return strlen(*strp):
- </pre>
- * Where _INFINITY_ is an imaginary constant so big that any string can fit
- * into it.
- */
-int
-tor_asprintf(char **strp, const char *fmt, ...)
-{
- int r;
- va_list args;
- va_start(args, fmt);
- r = tor_vasprintf(strp, fmt, args);
- va_end(args);
- if (!*strp || r < 0) {
- /* LCOV_EXCL_START */
- log_err(LD_BUG, "Internal error in asprintf");
- tor_assert(0);
- /* LCOV_EXCL_STOP */
- }
- return r;
-}
-
-/**
- * Portable vasprintf implementation. Does a printf() into a newly malloc'd
- * string. Differs from regular vasprintf in the same ways that
- * tor_asprintf() differs from regular asprintf.
- */
-int
-tor_vasprintf(char **strp, const char *fmt, va_list args)
-{
- /* use a temporary variable in case *strp is in args. */
- char *strp_tmp=NULL;
-#ifdef HAVE_VASPRINTF
- /* If the platform gives us one, use it. */
- int r = vasprintf(&strp_tmp, fmt, args);
- if (r < 0)
- *strp = NULL;
- else
- *strp = strp_tmp;
- return r;
-#elif defined(HAVE__VSCPRINTF)
- /* On Windows, _vsnprintf won't tell us the length of the string if it
- * overflows, so we need to use _vcsprintf to tell how much to allocate */
- int len, r;
- va_list tmp_args;
- va_copy(tmp_args, args);
- len = _vscprintf(fmt, tmp_args);
- va_end(tmp_args);
- if (len < 0) {
- *strp = NULL;
- return -1;
- }
- strp_tmp = tor_malloc(len + 1);
- r = _vsnprintf(strp_tmp, len+1, fmt, args);
- if (r != len) {
- tor_free(strp_tmp);
- *strp = NULL;
- return -1;
- }
- *strp = strp_tmp;
- return len;
-#else
- /* Everywhere else, we have a decent vsnprintf that tells us how many
- * characters we need. We give it a try on a short buffer first, since
- * it might be nice to avoid the second vsnprintf call.
- */
- char buf[128];
- int len, r;
- va_list tmp_args;
- va_copy(tmp_args, args);
- /* vsnprintf() was properly checked but tor_vsnprintf() available so
- * why not use it? */
- len = tor_vsnprintf(buf, sizeof(buf), fmt, tmp_args);
- va_end(tmp_args);
- if (len < (int)sizeof(buf)) {
- *strp = tor_strdup(buf);
- return len;
- }
- strp_tmp = tor_malloc(len+1);
- /* use of tor_vsnprintf() will ensure string is null terminated */
- r = tor_vsnprintf(strp_tmp, len+1, fmt, args);
- if (r != len) {
- tor_free(strp_tmp);
- *strp = NULL;
- return -1;
- }
- *strp = strp_tmp;
- return len;
-#endif /* defined(HAVE_VASPRINTF) || ... */
-}
-
-/** Given <b>hlen</b> bytes at <b>haystack</b> and <b>nlen</b> bytes at
- * <b>needle</b>, return a pointer to the first occurrence of the needle
- * within the haystack, or NULL if there is no such occurrence.
- *
- * This function is <em>not</em> timing-safe.
- *
- * Requires that <b>nlen</b> be greater than zero.
- */
-const void *
-tor_memmem(const void *_haystack, size_t hlen,
- const void *_needle, size_t nlen)
-{
-#if defined(HAVE_MEMMEM) && (!defined(__GNUC__) || __GNUC__ >= 2)
- tor_assert(nlen);
- return memmem(_haystack, hlen, _needle, nlen);
-#else
- /* This isn't as fast as the GLIBC implementation, but it doesn't need to
- * be. */
- const char *p, *last_possible_start;
- const char *haystack = (const char*)_haystack;
- const char *needle = (const char*)_needle;
- char first;
- tor_assert(nlen);
-
- if (nlen > hlen)
- return NULL;
-
- p = haystack;
- /* Last position at which the needle could start. */
- last_possible_start = haystack + hlen - nlen;
- first = *(const char*)needle;
- while ((p = memchr(p, first, last_possible_start + 1 - p))) {
- if (fast_memeq(p, needle, nlen))
- return p;
- if (++p > last_possible_start) {
- /* This comparison shouldn't be necessary, since if p was previously
- * equal to last_possible_start, the next memchr call would be
- * "memchr(p, first, 0)", which will return NULL. But it clarifies the
- * logic. */
- return NULL;
- }
- }
- return NULL;
-#endif /* defined(HAVE_MEMMEM) && (!defined(__GNUC__) || __GNUC__ >= 2) */
-}
-
-/**
- * Tables to implement ctypes-replacement TOR_IS*() functions. Each table
- * has 256 bits to look up whether a character is in some set or not. This
- * fails on non-ASCII platforms, but it is hard to find a platform whose
- * character set is not a superset of ASCII nowadays. */
-
-/**@{*/
-const uint32_t TOR_ISALPHA_TABLE[8] =
- { 0, 0, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 };
-const uint32_t TOR_ISALNUM_TABLE[8] =
- { 0, 0x3ff0000, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 };
-const uint32_t TOR_ISSPACE_TABLE[8] = { 0x3e00, 0x1, 0, 0, 0, 0, 0, 0 };
-const uint32_t TOR_ISXDIGIT_TABLE[8] =
- { 0, 0x3ff0000, 0x7e, 0x7e, 0, 0, 0, 0 };
-const uint32_t TOR_ISDIGIT_TABLE[8] = { 0, 0x3ff0000, 0, 0, 0, 0, 0, 0 };
-const uint32_t TOR_ISPRINT_TABLE[8] =
- { 0, 0xffffffff, 0xffffffff, 0x7fffffff, 0, 0, 0, 0x0 };
-const uint32_t TOR_ISUPPER_TABLE[8] = { 0, 0, 0x7fffffe, 0, 0, 0, 0, 0 };
-const uint32_t TOR_ISLOWER_TABLE[8] = { 0, 0, 0, 0x7fffffe, 0, 0, 0, 0 };
-
-/** Upper-casing and lowercasing tables to map characters to upper/lowercase
- * equivalents. Used by tor_toupper() and tor_tolower(). */
-/**@{*/
-const uint8_t TOR_TOUPPER_TABLE[256] = {
- 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
- 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
- 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
- 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
- 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
- 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
- 96,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
- 80,81,82,83,84,85,86,87,88,89,90,123,124,125,126,127,
- 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
- 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
- 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
- 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
- 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
- 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
- 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
- 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
-};
-const uint8_t TOR_TOLOWER_TABLE[256] = {
- 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
- 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
- 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
- 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
- 64,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
- 112,113,114,115,116,117,118,119,120,121,122,91,92,93,94,95,
- 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
- 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
- 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
- 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
- 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
- 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
- 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
- 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
- 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
- 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
-};
-/**@}*/
-
-/** Helper for tor_strtok_r_impl: Advances cp past all characters in
- * <b>sep</b>, and returns its new value. */
-static char *
-strtok_helper(char *cp, const char *sep)
-{
- if (sep[1]) {
- while (*cp && strchr(sep, *cp))
- ++cp;
- } else {
- while (*cp && *cp == *sep)
- ++cp;
- }
- return cp;
-}
-
-/** Implementation of strtok_r for platforms whose coders haven't figured out
- * how to write one. Hey, retrograde libc developers! You can use this code
- * here for free! */
-char *
-tor_strtok_r_impl(char *str, const char *sep, char **lasts)
-{
- char *cp, *start;
- tor_assert(*sep);
- if (str) {
- str = strtok_helper(str, sep);
- if (!*str)
- return NULL;
- start = cp = *lasts = str;
- } else if (!*lasts || !**lasts) {
- return NULL;
- } else {
- start = cp = *lasts;
- }
-
- if (sep[1]) {
- while (*cp && !strchr(sep, *cp))
- ++cp;
- } else {
- cp = strchr(cp, *sep);
- }
-
- if (!cp || !*cp) {
- *lasts = NULL;
- } else {
- *cp++ = '\0';
- *lasts = strtok_helper(cp, sep);
- }
- return start;
-}
-
-#ifdef _WIN32
-/** Take a filename and return a pointer to its final element. This
- * function is called on __FILE__ to fix a MSVC nit where __FILE__
- * contains the full path to the file. This is bad, because it
- * confuses users to find the home directory of the person who
- * compiled the binary in their warning messages.
- */
-const char *
-tor_fix_source_file(const char *fname)
-{
- const char *cp1, *cp2, *r;
- cp1 = strrchr(fname, '/');
- cp2 = strrchr(fname, '\\');
- if (cp1 && cp2) {
- r = (cp1<cp2)?(cp2+1):(cp1+1);
- } else if (cp1) {
- r = cp1+1;
- } else if (cp2) {
- r = cp2+1;
- } else {
- r = fname;
- }
- return r;
-}
-#endif /* defined(_WIN32) */
-
-/**
- * Read a 16-bit value beginning at <b>cp</b>. Equivalent to
- * *(uint16_t*)(cp), but will not cause segfaults on platforms that forbid
- * unaligned memory access.
- */
-uint16_t
-get_uint16(const void *cp)
-{
- uint16_t v;
- memcpy(&v,cp,2);
- return v;
-}
-/**
- * Read a 32-bit value beginning at <b>cp</b>. Equivalent to
- * *(uint32_t*)(cp), but will not cause segfaults on platforms that forbid
- * unaligned memory access.
- */
-uint32_t
-get_uint32(const void *cp)
-{
- uint32_t v;
- memcpy(&v,cp,4);
- return v;
-}
-/**
- * Read a 64-bit value beginning at <b>cp</b>. Equivalent to
- * *(uint64_t*)(cp), but will not cause segfaults on platforms that forbid
- * unaligned memory access.
- */
-uint64_t
-get_uint64(const void *cp)
-{
- uint64_t v;
- memcpy(&v,cp,8);
- return v;
-}
-
-/**
- * Set a 16-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
- * *(uint16_t*)(cp) = v, but will not cause segfaults on platforms that forbid
- * unaligned memory access. */
-void
-set_uint16(void *cp, uint16_t v)
-{
- memcpy(cp,&v,2);
-}
-/**
- * Set a 32-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
- * *(uint32_t*)(cp) = v, but will not cause segfaults on platforms that forbid
- * unaligned memory access. */
-void
-set_uint32(void *cp, uint32_t v)
-{
- memcpy(cp,&v,4);
-}
-/**
- * Set a 64-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
- * *(uint64_t*)(cp) = v, but will not cause segfaults on platforms that forbid
- * unaligned memory access. */
-void
-set_uint64(void *cp, uint64_t v)
-{
- memcpy(cp,&v,8);
-}
-
-/**
- * Rename the file <b>from</b> to the file <b>to</b>. On Unix, this is
- * the same as rename(2). On windows, this removes <b>to</b> first if
- * it already exists.
- * Returns 0 on success. Returns -1 and sets errno on failure.
- */
-int
-replace_file(const char *from, const char *to)
-{
-#ifndef _WIN32
- return tor_rename(from, to);
-#else
- switch (file_status(to))
- {
- case FN_NOENT:
- break;
- case FN_FILE:
- case FN_EMPTY:
- if (unlink(to)) return -1;
- break;
- case FN_ERROR:
- return -1;
- case FN_DIR:
- errno = EISDIR;
- return -1;
- }
- return tor_rename(from,to);
-#endif /* !defined(_WIN32) */
-}
-
-/** Change <b>fname</b>'s modification time to now. */
-int
-touch_file(const char *fname)
-{
- if (utime(fname, NULL)!=0)
- return -1;
- return 0;
-}
-
-/** Represents a lockfile on which we hold the lock. */
-struct tor_lockfile_t {
- /** Name of the file */
- char *filename;
- /** File descriptor used to hold the file open */
- int fd;
-};
-
-/** Try to get a lock on the lockfile <b>filename</b>, creating it as
- * necessary. If someone else has the lock and <b>blocking</b> is true,
- * wait until the lock is available. Otherwise return immediately whether
- * we succeeded or not.
- *
- * Set *<b>locked_out</b> to true if somebody else had the lock, and to false
- * otherwise.
- *
- * Return a <b>tor_lockfile_t</b> on success, NULL on failure.
- *
- * (Implementation note: because we need to fall back to fcntl on some
- * platforms, these locks are per-process, not per-thread. If you want
- * to do in-process locking, use tor_mutex_t like a normal person.
- * On Windows, when <b>blocking</b> is true, the maximum time that
- * is actually waited is 10 seconds, after which NULL is returned
- * and <b>locked_out</b> is set to 1.)
- */
-tor_lockfile_t *
-tor_lockfile_lock(const char *filename, int blocking, int *locked_out)
-{
- tor_lockfile_t *result;
- int fd;
- *locked_out = 0;
-
- log_info(LD_FS, "Locking \"%s\"", filename);
- fd = tor_open_cloexec(filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
- if (fd < 0) {
- log_warn(LD_FS,"Couldn't open \"%s\" for locking: %s", filename,
- strerror(errno));
- return NULL;
- }
-
-#ifdef _WIN32
- _lseek(fd, 0, SEEK_SET);
- if (_locking(fd, blocking ? _LK_LOCK : _LK_NBLCK, 1) < 0) {
- if (errno != EACCES && errno != EDEADLOCK)
- log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno));
- else
- *locked_out = 1;
- close(fd);
- return NULL;
- }
-#elif defined(HAVE_FLOCK)
- if (flock(fd, LOCK_EX|(blocking ? 0 : LOCK_NB)) < 0) {
- if (errno != EWOULDBLOCK)
- log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno));
- else
- *locked_out = 1;
- close(fd);
- return NULL;
- }
-#else
- {
- struct flock lock;
- memset(&lock, 0, sizeof(lock));
- lock.l_type = F_WRLCK;
- lock.l_whence = SEEK_SET;
- if (fcntl(fd, blocking ? F_SETLKW : F_SETLK, &lock) < 0) {
- if (errno != EACCES && errno != EAGAIN)
- log_warn(LD_FS, "Couldn't lock \"%s\": %s", filename, strerror(errno));
- else
- *locked_out = 1;
- close(fd);
- return NULL;
- }
- }
-#endif /* defined(_WIN32) || ... */
-
- result = tor_malloc(sizeof(tor_lockfile_t));
- result->filename = tor_strdup(filename);
- result->fd = fd;
- return result;
-}
-
-/** Release the lock held as <b>lockfile</b>. */
-void
-tor_lockfile_unlock(tor_lockfile_t *lockfile)
-{
- tor_assert(lockfile);
-
- log_info(LD_FS, "Unlocking \"%s\"", lockfile->filename);
-#ifdef _WIN32
- _lseek(lockfile->fd, 0, SEEK_SET);
- if (_locking(lockfile->fd, _LK_UNLCK, 1) < 0) {
- log_warn(LD_FS,"Error unlocking \"%s\": %s", lockfile->filename,
- strerror(errno));
- }
-#elif defined(HAVE_FLOCK)
- if (flock(lockfile->fd, LOCK_UN) < 0) {
- log_warn(LD_FS, "Error unlocking \"%s\": %s", lockfile->filename,
- strerror(errno));
- }
-#else
- /* Closing the lockfile is sufficient. */
-#endif /* defined(_WIN32) || ... */
-
- close(lockfile->fd);
- lockfile->fd = -1;
- tor_free(lockfile->filename);
- tor_free(lockfile);
-}
-
-/** @{ */
-/** Some old versions of Unix didn't define constants for these values,
- * and instead expect you to say 0, 1, or 2. */
-#ifndef SEEK_SET
-#define SEEK_SET 0
-#endif
-#ifndef SEEK_CUR
-#define SEEK_CUR 1
-#endif
-#ifndef SEEK_END
-#define SEEK_END 2
-#endif
-/** @} */
-
-/** Return the position of <b>fd</b> with respect to the start of the file. */
-off_t
-tor_fd_getpos(int fd)
-{
-#ifdef _WIN32
- return (off_t) _lseek(fd, 0, SEEK_CUR);
-#else
- return (off_t) lseek(fd, 0, SEEK_CUR);
-#endif
-}
-
-/** Move <b>fd</b> to the end of the file. Return -1 on error, 0 on success.
- * If the file is a pipe, do nothing and succeed.
- **/
-int
-tor_fd_seekend(int fd)
-{
-#ifdef _WIN32
- return _lseek(fd, 0, SEEK_END) < 0 ? -1 : 0;
-#else
- off_t rc = lseek(fd, 0, SEEK_END) < 0 ? -1 : 0;
-#ifdef ESPIPE
- /* If we get an error and ESPIPE, then it's a pipe or a socket of a fifo:
- * no need to worry. */
- if (rc < 0 && errno == ESPIPE)
- rc = 0;
-#endif /* defined(ESPIPE) */
- return (rc < 0) ? -1 : 0;
-#endif /* defined(_WIN32) */
-}
-
-/** Move <b>fd</b> to position <b>pos</b> in the file. Return -1 on error, 0
- * on success. */
-int
-tor_fd_setpos(int fd, off_t pos)
-{
-#ifdef _WIN32
- return _lseek(fd, pos, SEEK_SET) < 0 ? -1 : 0;
-#else
- return lseek(fd, pos, SEEK_SET) < 0 ? -1 : 0;
-#endif
-}
-
-/** Replacement for ftruncate(fd, 0): move to the front of the file and remove
- * all the rest of the file. Return -1 on error, 0 on success. */
-int
-tor_ftruncate(int fd)
-{
- /* Rumor has it that some versions of ftruncate do not move the file pointer.
- */
- if (tor_fd_setpos(fd, 0) < 0)
- return -1;
-
-#ifdef _WIN32
- return _chsize(fd, 0);
-#else
- return ftruncate(fd, 0);
-#endif
-}
-
-#undef DEBUG_SOCKET_COUNTING
-#ifdef DEBUG_SOCKET_COUNTING
-/** A bitarray of all fds that should be passed to tor_socket_close(). Only
- * used if DEBUG_SOCKET_COUNTING is defined. */
-static bitarray_t *open_sockets = NULL;
-/** The size of <b>open_sockets</b>, in bits. */
-static int max_socket = -1;
-#endif /* defined(DEBUG_SOCKET_COUNTING) */
-
-/** Count of number of sockets currently open. (Undercounts sockets opened by
- * eventdns and libevent.) */
-static int n_sockets_open = 0;
-
-/** Mutex to protect open_sockets, max_socket, and n_sockets_open. */
-static tor_mutex_t *socket_accounting_mutex = NULL;
-
-/** Helper: acquire the socket accounting lock. */
-static inline void
-socket_accounting_lock(void)
-{
- if (PREDICT_UNLIKELY(!socket_accounting_mutex))
- socket_accounting_mutex = tor_mutex_new();
- tor_mutex_acquire(socket_accounting_mutex);
-}
-
-/** Helper: release the socket accounting lock. */
-static inline void
-socket_accounting_unlock(void)
-{
- tor_mutex_release(socket_accounting_mutex);
-}
-
-/** As close(), but guaranteed to work for sockets across platforms (including
- * Windows, where close()ing a socket doesn't work. Returns 0 on success and
- * the socket error code on failure. */
-int
-tor_close_socket_simple(tor_socket_t s)
-{
- int r = 0;
-
- /* On Windows, you have to call close() on fds returned by open(),
- * and closesocket() on fds returned by socket(). On Unix, everything
- * gets close()'d. We abstract this difference by always using
- * tor_close_socket to close sockets, and always using close() on
- * files.
- */
- #if defined(_WIN32)
- r = closesocket(s);
- #else
- r = close(s);
- #endif
-
- if (r != 0) {
- int err = tor_socket_errno(-1);
- log_info(LD_NET, "Close returned an error: %s", tor_socket_strerror(err));
- return err;
- }
-
- return r;
-}
-
-/** As tor_close_socket_simple(), but keeps track of the number
- * of open sockets. Returns 0 on success, -1 on failure. */
-MOCK_IMPL(int,
-tor_close_socket,(tor_socket_t s))
-{
- int r = tor_close_socket_simple(s);
-
- socket_accounting_lock();
-#ifdef DEBUG_SOCKET_COUNTING
- if (s > max_socket || ! bitarray_is_set(open_sockets, s)) {
- log_warn(LD_BUG, "Closing a socket (%d) that wasn't returned by tor_open_"
- "socket(), or that was already closed or something.", s);
- } else {
- tor_assert(open_sockets && s <= max_socket);
- bitarray_clear(open_sockets, s);
- }
-#endif /* defined(DEBUG_SOCKET_COUNTING) */
- if (r == 0) {
- --n_sockets_open;
- } else {
-#ifdef _WIN32
- if (r != WSAENOTSOCK)
- --n_sockets_open;
-#else
- if (r != EBADF)
- --n_sockets_open; // LCOV_EXCL_LINE -- EIO and EINTR too hard to force.
-#endif /* defined(_WIN32) */
- r = -1;
- }
-
- tor_assert_nonfatal(n_sockets_open >= 0);
- socket_accounting_unlock();
- return r;
-}
-
-/** @{ */
-#ifdef DEBUG_SOCKET_COUNTING
-/** Helper: if DEBUG_SOCKET_COUNTING is enabled, remember that <b>s</b> is
- * now an open socket. */
-static inline void
-mark_socket_open(tor_socket_t s)
-{
- /* XXXX This bitarray business will NOT work on windows: sockets aren't
- small ints there. */
- if (s > max_socket) {
- if (max_socket == -1) {
- open_sockets = bitarray_init_zero(s+128);
- max_socket = s+128;
- } else {
- open_sockets = bitarray_expand(open_sockets, max_socket, s+128);
- max_socket = s+128;
- }
- }
- if (bitarray_is_set(open_sockets, s)) {
- log_warn(LD_BUG, "I thought that %d was already open, but socket() just "
- "gave it to me!", s);
- }
- bitarray_set(open_sockets, s);
-}
-#else /* !(defined(DEBUG_SOCKET_COUNTING)) */
-#define mark_socket_open(s) ((void) (s))
-#endif /* defined(DEBUG_SOCKET_COUNTING) */
-/** @} */
-
-/** As socket(), but counts the number of open sockets. */
-MOCK_IMPL(tor_socket_t,
-tor_open_socket,(int domain, int type, int protocol))
-{
- return tor_open_socket_with_extensions(domain, type, protocol, 1, 0);
-}
-
-/** Mockable wrapper for connect(). */
-MOCK_IMPL(tor_socket_t,
-tor_connect_socket,(tor_socket_t sock, const struct sockaddr *address,
- socklen_t address_len))
-{
- return connect(sock,address,address_len);
-}
-
-/** As socket(), but creates a nonblocking socket and
- * counts the number of open sockets. */
-tor_socket_t
-tor_open_socket_nonblocking(int domain, int type, int protocol)
-{
- return tor_open_socket_with_extensions(domain, type, protocol, 1, 1);
-}
-
-/** As socket(), but counts the number of open sockets and handles
- * socket creation with either of SOCK_CLOEXEC and SOCK_NONBLOCK specified.
- * <b>cloexec</b> and <b>nonblock</b> should be either 0 or 1 to indicate
- * if the corresponding extension should be used.*/
-tor_socket_t
-tor_open_socket_with_extensions(int domain, int type, int protocol,
- int cloexec, int nonblock)
-{
- tor_socket_t s;
-
- /* We are about to create a new file descriptor so make sure we have
- * enough of them. */
- if (get_n_open_sockets() >= max_sockets - 1) {
-#ifdef _WIN32
- WSASetLastError(WSAEMFILE);
-#else
- errno = EMFILE;
-#endif
- return TOR_INVALID_SOCKET;
- }
-
-#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
- int ext_flags = (cloexec ? SOCK_CLOEXEC : 0) |
- (nonblock ? SOCK_NONBLOCK : 0);
- s = socket(domain, type|ext_flags, protocol);
- if (SOCKET_OK(s))
- goto socket_ok;
- /* If we got an error, see if it is EINVAL. EINVAL might indicate that,
- * even though we were built on a system with SOCK_CLOEXEC and SOCK_NONBLOCK
- * support, we are running on one without. */
- if (errno != EINVAL)
- return s;
-#endif /* defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK) */
-
- s = socket(domain, type, protocol);
- if (! SOCKET_OK(s))
- return s;
-
-#if defined(FD_CLOEXEC)
- if (cloexec) {
- if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) {
- log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
- tor_close_socket_simple(s);
- return TOR_INVALID_SOCKET;
- }
- }
-#else /* !(defined(FD_CLOEXEC)) */
- (void)cloexec;
-#endif /* defined(FD_CLOEXEC) */
-
- if (nonblock) {
- if (set_socket_nonblocking(s) == -1) {
- tor_close_socket_simple(s);
- return TOR_INVALID_SOCKET;
- }
- }
-
- goto socket_ok; /* So that socket_ok will not be unused. */
-
- socket_ok:
- tor_take_socket_ownership(s);
- return s;
-}
-
-/**
- * For socket accounting: remember that we are the owner of the socket
- * <b>s</b>. This will prevent us from overallocating sockets, and prevent us
- * from asserting later when we close the socket <b>s</b>.
- */
-void
-tor_take_socket_ownership(tor_socket_t s)
-{
- socket_accounting_lock();
- ++n_sockets_open;
- mark_socket_open(s);
- socket_accounting_unlock();
-}
-
-/** As accept(), but counts the number of open sockets. */
-tor_socket_t
-tor_accept_socket(tor_socket_t sockfd, struct sockaddr *addr, socklen_t *len)
-{
- return tor_accept_socket_with_extensions(sockfd, addr, len, 1, 0);
-}
-
-/** As accept(), but returns a nonblocking socket and
- * counts the number of open sockets. */
-tor_socket_t
-tor_accept_socket_nonblocking(tor_socket_t sockfd, struct sockaddr *addr,
- socklen_t *len)
-{
- return tor_accept_socket_with_extensions(sockfd, addr, len, 1, 1);
-}
-
-/** As accept(), but counts the number of open sockets and handles
- * socket creation with either of SOCK_CLOEXEC and SOCK_NONBLOCK specified.
- * <b>cloexec</b> and <b>nonblock</b> should be either 0 or 1 to indicate
- * if the corresponding extension should be used.*/
-tor_socket_t
-tor_accept_socket_with_extensions(tor_socket_t sockfd, struct sockaddr *addr,
- socklen_t *len, int cloexec, int nonblock)
-{
- tor_socket_t s;
-
- /* We are about to create a new file descriptor so make sure we have
- * enough of them. */
- if (get_n_open_sockets() >= max_sockets - 1) {
-#ifdef _WIN32
- WSASetLastError(WSAEMFILE);
-#else
- errno = EMFILE;
-#endif
- return TOR_INVALID_SOCKET;
- }
-
-#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) \
- && defined(SOCK_NONBLOCK)
- int ext_flags = (cloexec ? SOCK_CLOEXEC : 0) |
- (nonblock ? SOCK_NONBLOCK : 0);
- s = accept4(sockfd, addr, len, ext_flags);
- if (SOCKET_OK(s))
- goto socket_ok;
- /* If we got an error, see if it is ENOSYS. ENOSYS indicates that,
- * even though we were built on a system with accept4 support, we
- * are running on one without. Also, check for EINVAL, which indicates that
- * we are missing SOCK_CLOEXEC/SOCK_NONBLOCK support. */
- if (errno != EINVAL && errno != ENOSYS)
- return s;
-#endif /* defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) ... */
-
- s = accept(sockfd, addr, len);
- if (!SOCKET_OK(s))
- return s;
-
-#if defined(FD_CLOEXEC)
- if (cloexec) {
- if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) {
- log_warn(LD_NET, "Couldn't set FD_CLOEXEC: %s", strerror(errno));
- tor_close_socket_simple(s);
- return TOR_INVALID_SOCKET;
- }
- }
-#else /* !(defined(FD_CLOEXEC)) */
- (void)cloexec;
-#endif /* defined(FD_CLOEXEC) */
-
- if (nonblock) {
- if (set_socket_nonblocking(s) == -1) {
- tor_close_socket_simple(s);
- return TOR_INVALID_SOCKET;
- }
- }
-
- goto socket_ok; /* So that socket_ok will not be unused. */
-
- socket_ok:
- tor_take_socket_ownership(s);
- return s;
-}
-
-/** Return the number of sockets we currently have opened. */
-int
-get_n_open_sockets(void)
-{
- int n;
- socket_accounting_lock();
- n = n_sockets_open;
- socket_accounting_unlock();
- return n;
-}
-
-/** Mockable wrapper for getsockname(). */
-MOCK_IMPL(int,
-tor_getsockname,(tor_socket_t sock, struct sockaddr *address,
- socklen_t *address_len))
-{
- return getsockname(sock, address, address_len);
-}
-
-/**
- * Find the local address associated with the socket <b>sock</b>, and
- * place it in *<b>addr_out</b>. Return 0 on success, -1 on failure.
- *
- * (As tor_getsockname, but instead places the result in a tor_addr_t.) */
-int
-tor_addr_from_getsockname(tor_addr_t *addr_out, tor_socket_t sock)
-{
- struct sockaddr_storage ss;
- socklen_t ss_len = sizeof(ss);
- memset(&ss, 0, sizeof(ss));
-
- if (tor_getsockname(sock, (struct sockaddr *) &ss, &ss_len) < 0)
- return -1;
-
- return tor_addr_from_sockaddr(addr_out, (struct sockaddr *)&ss, NULL);
-}
-
-/** Turn <b>socket</b> into a nonblocking socket. Return 0 on success, -1
- * on failure.
- */
-int
-set_socket_nonblocking(tor_socket_t sock)
-{
-#if defined(_WIN32)
- unsigned long nonblocking = 1;
- ioctlsocket(sock, FIONBIO, (unsigned long*) &nonblocking);
-#else
- int flags;
-
- flags = fcntl(sock, F_GETFL, 0);
- if (flags == -1) {
- log_warn(LD_NET, "Couldn't get file status flags: %s", strerror(errno));
- return -1;
- }
- flags |= O_NONBLOCK;
- if (fcntl(sock, F_SETFL, flags) == -1) {
- log_warn(LD_NET, "Couldn't set file status flags: %s", strerror(errno));
- return -1;
- }
-#endif /* defined(_WIN32) */
-
- return 0;
-}
-
-/**
- * Allocate a pair of connected sockets. (Like socketpair(family,
- * type,protocol,fd), but works on systems that don't have
- * socketpair.)
- *
- * Currently, only (AF_UNIX, SOCK_STREAM, 0) sockets are supported.
- *
- * Note that on systems without socketpair, this call will fail if
- * localhost is inaccessible (for example, if the networking
- * stack is down). And even if it succeeds, the socket pair will not
- * be able to read while localhost is down later (the socket pair may
- * even close, depending on OS-specific timeouts).
- *
- * Returns 0 on success and -errno on failure; do not rely on the value
- * of errno or WSAGetLastError().
- **/
-/* It would be nicer just to set errno, but that won't work for windows. */
-int
-tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
-{
-//don't use win32 socketpairs (they are always bad)
-#if defined(HAVE_SOCKETPAIR) && !defined(_WIN32)
- int r;
-
-#ifdef SOCK_CLOEXEC
- r = socketpair(family, type|SOCK_CLOEXEC, protocol, fd);
- if (r == 0)
- goto sockets_ok;
- /* If we got an error, see if it is EINVAL. EINVAL might indicate that,
- * even though we were built on a system with SOCK_CLOEXEC support, we
- * are running on one without. */
- if (errno != EINVAL)
- return -errno;
-#endif /* defined(SOCK_CLOEXEC) */
-
- r = socketpair(family, type, protocol, fd);
- if (r < 0)
- return -errno;
-
-#if defined(FD_CLOEXEC)
- if (SOCKET_OK(fd[0])) {
- r = fcntl(fd[0], F_SETFD, FD_CLOEXEC);
- if (r == -1) {
- close(fd[0]);
- close(fd[1]);
- return -errno;
- }
- }
- if (SOCKET_OK(fd[1])) {
- r = fcntl(fd[1], F_SETFD, FD_CLOEXEC);
- if (r == -1) {
- close(fd[0]);
- close(fd[1]);
- return -errno;
- }
- }
-#endif /* defined(FD_CLOEXEC) */
- goto sockets_ok; /* So that sockets_ok will not be unused. */
-
- sockets_ok:
- socket_accounting_lock();
- if (SOCKET_OK(fd[0])) {
- ++n_sockets_open;
- mark_socket_open(fd[0]);
- }
- if (SOCKET_OK(fd[1])) {
- ++n_sockets_open;
- mark_socket_open(fd[1]);
- }
- socket_accounting_unlock();
-
- return 0;
-#else /* !(defined(HAVE_SOCKETPAIR) && !defined(_WIN32)) */
- return tor_ersatz_socketpair(family, type, protocol, fd);
-#endif /* defined(HAVE_SOCKETPAIR) && !defined(_WIN32) */
-}
-
-#ifdef NEED_ERSATZ_SOCKETPAIR
-
-static inline socklen_t
-SIZEOF_SOCKADDR(int domain)
-{
- switch (domain) {
- case AF_INET:
- return sizeof(struct sockaddr_in);
- case AF_INET6:
- return sizeof(struct sockaddr_in6);
- default:
- return 0;
- }
-}
-
-/**
- * Helper used to implement socketpair on systems that lack it, by
- * making a direct connection to localhost.
- */
-STATIC int
-tor_ersatz_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
-{
- /* This socketpair does not work when localhost is down. So
- * it's really not the same thing at all. But it's close enough
- * for now, and really, when localhost is down sometimes, we
- * have other problems too.
- */
- tor_socket_t listener = TOR_INVALID_SOCKET;
- tor_socket_t connector = TOR_INVALID_SOCKET;
- tor_socket_t acceptor = TOR_INVALID_SOCKET;
- tor_addr_t listen_tor_addr;
- struct sockaddr_storage connect_addr_ss, listen_addr_ss;
- struct sockaddr *listen_addr = (struct sockaddr *) &listen_addr_ss;
- uint16_t listen_port = 0;
- tor_addr_t connect_tor_addr;
- uint16_t connect_port = 0;
- struct sockaddr *connect_addr = (struct sockaddr *) &connect_addr_ss;
- socklen_t size;
- int saved_errno = -1;
- int ersatz_domain = AF_INET;
-
- memset(&connect_tor_addr, 0, sizeof(connect_tor_addr));
- memset(&connect_addr_ss, 0, sizeof(connect_addr_ss));
- memset(&listen_tor_addr, 0, sizeof(listen_tor_addr));
- memset(&listen_addr_ss, 0, sizeof(listen_addr_ss));
-
- if (protocol
-#ifdef AF_UNIX
- || family != AF_UNIX
-#endif
- ) {
-#ifdef _WIN32
- return -WSAEAFNOSUPPORT;
-#else
- return -EAFNOSUPPORT;
-#endif
- }
- if (!fd) {
- return -EINVAL;
- }
-
- listener = tor_open_socket(ersatz_domain, type, 0);
- if (!SOCKET_OK(listener)) {
- int first_errno = tor_socket_errno(-1);
- if (first_errno == SOCK_ERRNO(EPROTONOSUPPORT)
- && ersatz_domain == AF_INET) {
- /* Assume we're on an IPv6-only system */
- ersatz_domain = AF_INET6;
- listener = tor_open_socket(ersatz_domain, type, 0);
- if (!SOCKET_OK(listener)) {
- /* Keep the previous behaviour, which was to return the IPv4 error.
- * (This may be less informative on IPv6-only systems.)
- * XX/teor - is there a better way to decide which errno to return?
- * (I doubt we care much either way, once there is an error.)
- */
- return -first_errno;
- }
- }
- }
- /* If there is no 127.0.0.1 or ::1, this will and must fail. Otherwise, we
- * risk exposing a socketpair on a routable IP address. (Some BSD jails
- * use a routable address for localhost. Fortunately, they have the real
- * AF_UNIX socketpair.) */
- if (ersatz_domain == AF_INET) {
- tor_addr_from_ipv4h(&listen_tor_addr, INADDR_LOOPBACK);
- } else {
- tor_addr_parse(&listen_tor_addr, "[::1]");
- }
- tor_assert(tor_addr_is_loopback(&listen_tor_addr));
- size = tor_addr_to_sockaddr(&listen_tor_addr,
- 0 /* kernel chooses port. */,
- listen_addr,
- sizeof(listen_addr_ss));
- if (bind(listener, listen_addr, size) == -1)
- goto tidy_up_and_fail;
- if (listen(listener, 1) == -1)
- goto tidy_up_and_fail;
-
- connector = tor_open_socket(ersatz_domain, type, 0);
- if (!SOCKET_OK(connector))
- goto tidy_up_and_fail;
- /* We want to find out the port number to connect to. */
- size = sizeof(connect_addr_ss);
- if (getsockname(listener, connect_addr, &size) == -1)
- goto tidy_up_and_fail;
- if (size != SIZEOF_SOCKADDR (connect_addr->sa_family))
- goto abort_tidy_up_and_fail;
- if (connect(connector, connect_addr, size) == -1)
- goto tidy_up_and_fail;
-
- size = sizeof(listen_addr_ss);
- acceptor = tor_accept_socket(listener, listen_addr, &size);
- if (!SOCKET_OK(acceptor))
- goto tidy_up_and_fail;
- if (size != SIZEOF_SOCKADDR(listen_addr->sa_family))
- goto abort_tidy_up_and_fail;
- /* Now check we are talking to ourself by matching port and host on the
- two sockets. */
- if (getsockname(connector, connect_addr, &size) == -1)
- goto tidy_up_and_fail;
- /* Set *_tor_addr and *_port to the address and port that was used */
- tor_addr_from_sockaddr(&listen_tor_addr, listen_addr, &listen_port);
- tor_addr_from_sockaddr(&connect_tor_addr, connect_addr, &connect_port);
- if (size != SIZEOF_SOCKADDR (connect_addr->sa_family)
- || tor_addr_compare(&listen_tor_addr, &connect_tor_addr, CMP_SEMANTIC)
- || listen_port != connect_port) {
- goto abort_tidy_up_and_fail;
- }
- tor_close_socket(listener);
- fd[0] = connector;
- fd[1] = acceptor;
-
- return 0;
-
- abort_tidy_up_and_fail:
-#ifdef _WIN32
- saved_errno = WSAECONNABORTED;
-#else
- saved_errno = ECONNABORTED; /* I hope this is portable and appropriate. */
-#endif
- tidy_up_and_fail:
- if (saved_errno < 0)
- saved_errno = errno;
- if (SOCKET_OK(listener))
- tor_close_socket(listener);
- if (SOCKET_OK(connector))
- tor_close_socket(connector);
- if (SOCKET_OK(acceptor))
- tor_close_socket(acceptor);
- return -saved_errno;
-}
-
-#undef SIZEOF_SOCKADDR
-
-#endif /* defined(NEED_ERSATZ_SOCKETPAIR) */
-
-/* Return the maximum number of allowed sockets. */
-int
-get_max_sockets(void)
-{
- return max_sockets;
-}
-
-/** Number of extra file descriptors to keep in reserve beyond those that we
- * tell Tor it's allowed to use. */
-#define ULIMIT_BUFFER 32 /* keep 32 extra fd's beyond ConnLimit_ */
-
-/** Learn the maximum allowed number of file descriptors, and tell the
- * system we want to use up to that number. (Some systems have a low soft
- * limit, and let us set it higher.) We compute this by finding the largest
- * number that we can use.
- *
- * If the limit is below the reserved file descriptor value (ULIMIT_BUFFER),
- * return -1 and <b>max_out</b> is untouched.
- *
- * If we can't find a number greater than or equal to <b>limit</b>, then we
- * fail by returning -1 and <b>max_out</b> is untouched.
- *
- * If we are unable to set the limit value because of setrlimit() failing,
- * return 0 and <b>max_out</b> is set to the current maximum value returned
- * by getrlimit().
- *
- * Otherwise, return 0 and store the maximum we found inside <b>max_out</b>
- * and set <b>max_sockets</b> with that value as well.*/
-int
-set_max_file_descriptors(rlim_t limit, int *max_out)
-{
- if (limit < ULIMIT_BUFFER) {
- log_warn(LD_CONFIG,
- "ConnLimit must be at least %d. Failing.", ULIMIT_BUFFER);
- return -1;
- }
-
- /* Define some maximum connections values for systems where we cannot
- * automatically determine a limit. Re Cygwin, see
- * http://archives.seul.org/or/talk/Aug-2006/msg00210.html
- * For an iPhone, 9999 should work. For Windows and all other unknown
- * systems we use 15000 as the default. */
-#ifndef HAVE_GETRLIMIT
-#if defined(CYGWIN) || defined(__CYGWIN__)
- const char *platform = "Cygwin";
- const unsigned long MAX_CONNECTIONS = 3200;
-#elif defined(_WIN32)
- const char *platform = "Windows";
- const unsigned long MAX_CONNECTIONS = 15000;
-#else
- const char *platform = "unknown platforms with no getrlimit()";
- const unsigned long MAX_CONNECTIONS = 15000;
-#endif /* defined(CYGWIN) || defined(__CYGWIN__) || ... */
- log_fn(LOG_INFO, LD_NET,
- "This platform is missing getrlimit(). Proceeding.");
- if (limit > MAX_CONNECTIONS) {
- log_warn(LD_CONFIG,
- "We do not support more than %lu file descriptors "
- "on %s. Tried to raise to %lu.",
- (unsigned long)MAX_CONNECTIONS, platform, (unsigned long)limit);
- return -1;
- }
- limit = MAX_CONNECTIONS;
-#else /* !(!defined(HAVE_GETRLIMIT)) */
- struct rlimit rlim;
-
- if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
- log_warn(LD_NET, "Could not get maximum number of file descriptors: %s",
- strerror(errno));
- return -1;
- }
- if (rlim.rlim_max < limit) {
- log_warn(LD_CONFIG,"We need %lu file descriptors available, and we're "
- "limited to %lu. Please change your ulimit -n.",
- (unsigned long)limit, (unsigned long)rlim.rlim_max);
- return -1;
- }
-
- if (rlim.rlim_max > rlim.rlim_cur) {
- log_info(LD_NET,"Raising max file descriptors from %lu to %lu.",
- (unsigned long)rlim.rlim_cur, (unsigned long)rlim.rlim_max);
- }
- /* Set the current limit value so if the attempt to set the limit to the
- * max fails at least we'll have a valid value of maximum sockets. */
- *max_out = max_sockets = (int)rlim.rlim_cur - ULIMIT_BUFFER;
- rlim.rlim_cur = rlim.rlim_max;
-
- if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
- int couldnt_set = 1;
- const int setrlimit_errno = errno;
-#ifdef OPEN_MAX
- uint64_t try_limit = OPEN_MAX - ULIMIT_BUFFER;
- if (errno == EINVAL && try_limit < (uint64_t) rlim.rlim_cur) {
- /* On some platforms, OPEN_MAX is the real limit, and getrlimit() is
- * full of nasty lies. I'm looking at you, OSX 10.5.... */
- rlim.rlim_cur = MIN((rlim_t) try_limit, rlim.rlim_cur);
- if (setrlimit(RLIMIT_NOFILE, &rlim) == 0) {
- if (rlim.rlim_cur < (rlim_t)limit) {
- log_warn(LD_CONFIG, "We are limited to %lu file descriptors by "
- "OPEN_MAX (%lu), and ConnLimit is %lu. Changing "
- "ConnLimit; sorry.",
- (unsigned long)try_limit, (unsigned long)OPEN_MAX,
- (unsigned long)limit);
- } else {
- log_info(LD_CONFIG, "Dropped connection limit to %lu based on "
- "OPEN_MAX (%lu); Apparently, %lu was too high and rlimit "
- "lied to us.",
- (unsigned long)try_limit, (unsigned long)OPEN_MAX,
- (unsigned long)rlim.rlim_max);
- }
- couldnt_set = 0;
- }
- }
-#endif /* defined(OPEN_MAX) */
- if (couldnt_set) {
- log_warn(LD_CONFIG,"Couldn't set maximum number of file descriptors: %s",
- strerror(setrlimit_errno));
- }
- }
- /* leave some overhead for logs, etc, */
- limit = rlim.rlim_cur;
-#endif /* !defined(HAVE_GETRLIMIT) */
-
- if (limit > INT_MAX)
- limit = INT_MAX;
- tor_assert(max_out);
- *max_out = max_sockets = (int)limit - ULIMIT_BUFFER;
- return 0;
-}
-
-#ifndef _WIN32
-/** Log details of current user and group credentials. Return 0 on
- * success. Logs and return -1 on failure.
- */
-static int
-log_credential_status(void)
-{
-/** Log level to use when describing non-error UID/GID status. */
-#define CREDENTIAL_LOG_LEVEL LOG_INFO
- /* Real, effective and saved UIDs */
- uid_t ruid, euid, suid;
- /* Read, effective and saved GIDs */
- gid_t rgid, egid, sgid;
- /* Supplementary groups */
- gid_t *sup_gids = NULL;
- int sup_gids_size;
- /* Number of supplementary groups */
- int ngids;
-
- /* log UIDs */
-#ifdef HAVE_GETRESUID
- if (getresuid(&ruid, &euid, &suid) != 0 ) {
- log_warn(LD_GENERAL, "Error getting changed UIDs: %s", strerror(errno));
- return -1;
- } else {
- log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL,
- "UID is %u (real), %u (effective), %u (saved)",
- (unsigned)ruid, (unsigned)euid, (unsigned)suid);
- }
-#else /* !(defined(HAVE_GETRESUID)) */
- /* getresuid is not present on MacOS X, so we can't get the saved (E)UID */
- ruid = getuid();
- euid = geteuid();
- (void)suid;
-
- log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL,
- "UID is %u (real), %u (effective), unknown (saved)",
- (unsigned)ruid, (unsigned)euid);
-#endif /* defined(HAVE_GETRESUID) */
-
- /* log GIDs */
-#ifdef HAVE_GETRESGID
- if (getresgid(&rgid, &egid, &sgid) != 0 ) {
- log_warn(LD_GENERAL, "Error getting changed GIDs: %s", strerror(errno));
- return -1;
- } else {
- log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL,
- "GID is %u (real), %u (effective), %u (saved)",
- (unsigned)rgid, (unsigned)egid, (unsigned)sgid);
- }
-#else /* !(defined(HAVE_GETRESGID)) */
- /* getresgid is not present on MacOS X, so we can't get the saved (E)GID */
- rgid = getgid();
- egid = getegid();
- (void)sgid;
- log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL,
- "GID is %u (real), %u (effective), unknown (saved)",
- (unsigned)rgid, (unsigned)egid);
-#endif /* defined(HAVE_GETRESGID) */
-
- /* log supplementary groups */
- sup_gids_size = 64;
- sup_gids = tor_calloc(64, sizeof(gid_t));
- while ((ngids = getgroups(sup_gids_size, sup_gids)) < 0 &&
- errno == EINVAL &&
- sup_gids_size < NGROUPS_MAX) {
- sup_gids_size *= 2;
- sup_gids = tor_reallocarray(sup_gids, sizeof(gid_t), sup_gids_size);
- }
-
- if (ngids < 0) {
- log_warn(LD_GENERAL, "Error getting supplementary GIDs: %s",
- strerror(errno));
- tor_free(sup_gids);
- return -1;
- } else {
- int i, retval = 0;
- char *s = NULL;
- smartlist_t *elts = smartlist_new();
-
- for (i = 0; i<ngids; i++) {
- smartlist_add_asprintf(elts, "%u", (unsigned)sup_gids[i]);
- }
-
- s = smartlist_join_strings(elts, " ", 0, NULL);
-
- log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL, "Supplementary groups are: %s",s);
-
- tor_free(s);
- SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
- smartlist_free(elts);
- tor_free(sup_gids);
-
- return retval;
- }
-
- return 0;
-}
-#endif /* !defined(_WIN32) */
-
-#ifndef _WIN32
-/** Cached struct from the last getpwname() call we did successfully. */
-static struct passwd *passwd_cached = NULL;
-
-/** Helper: copy a struct passwd object.
- *
- * We only copy the fields pw_uid, pw_gid, pw_name, pw_dir. Tor doesn't use
- * any others, and I don't want to run into incompatibilities.
- */
-static struct passwd *
-tor_passwd_dup(const struct passwd *pw)
-{
- struct passwd *new_pw = tor_malloc_zero(sizeof(struct passwd));
- if (pw->pw_name)
- new_pw->pw_name = tor_strdup(pw->pw_name);
- if (pw->pw_dir)
- new_pw->pw_dir = tor_strdup(pw->pw_dir);
- new_pw->pw_uid = pw->pw_uid;
- new_pw->pw_gid = pw->pw_gid;
-
- return new_pw;
-}
-
-#define tor_passwd_free(pw) \
- FREE_AND_NULL(struct passwd, tor_passwd_free_, (pw))
-
-/** Helper: free one of our cached 'struct passwd' values. */
-static void
-tor_passwd_free_(struct passwd *pw)
-{
- if (!pw)
- return;
-
- tor_free(pw->pw_name);
- tor_free(pw->pw_dir);
- tor_free(pw);
-}
-
-/** Wrapper around getpwnam() that caches result. Used so that we don't need
- * to give the sandbox access to /etc/passwd.
- *
- * The following fields alone will definitely be copied in the output: pw_uid,
- * pw_gid, pw_name, pw_dir. Other fields are not present in cached values.
- *
- * When called with a NULL argument, this function clears storage associated
- * with static variables it uses.
- **/
-const struct passwd *
-tor_getpwnam(const char *username)
-{
- struct passwd *pw;
-
- if (username == NULL) {
- tor_passwd_free(passwd_cached);
- passwd_cached = NULL;
- return NULL;
- }
-
- if ((pw = getpwnam(username))) {
- tor_passwd_free(passwd_cached);
- passwd_cached = tor_passwd_dup(pw);
- log_info(LD_GENERAL, "Caching new entry %s for %s",
- passwd_cached->pw_name, username);
- return pw;
- }
-
- /* Lookup failed */
- if (! passwd_cached || ! passwd_cached->pw_name)
- return NULL;
-
- if (! strcmp(username, passwd_cached->pw_name))
- return passwd_cached; // LCOV_EXCL_LINE - would need to make getpwnam flaky
-
- return NULL;
-}
-
-/** Wrapper around getpwnam() that can use cached result from
- * tor_getpwnam(). Used so that we don't need to give the sandbox access to
- * /etc/passwd.
- *
- * The following fields alone will definitely be copied in the output: pw_uid,
- * pw_gid, pw_name, pw_dir. Other fields are not present in cached values.
- */
-const struct passwd *
-tor_getpwuid(uid_t uid)
-{
- struct passwd *pw;
-
- if ((pw = getpwuid(uid))) {
- return pw;
- }
-
- /* Lookup failed */
- if (! passwd_cached)
- return NULL;
-
- if (uid == passwd_cached->pw_uid)
- return passwd_cached; // LCOV_EXCL_LINE - would need to make getpwnam flaky
-
- return NULL;
-}
-#endif /* !defined(_WIN32) */
-
-/** Return true iff we were compiled with capability support, and capabilities
- * seem to work. **/
-int
-have_capability_support(void)
-{
-#ifdef HAVE_LINUX_CAPABILITIES
- cap_t caps = cap_get_proc();
- if (caps == NULL)
- return 0;
- cap_free(caps);
- return 1;
-#else /* !(defined(HAVE_LINUX_CAPABILITIES)) */
- return 0;
-#endif /* defined(HAVE_LINUX_CAPABILITIES) */
-}
-
-#ifdef HAVE_LINUX_CAPABILITIES
-/** Helper. Drop all capabilities but a small set, and set PR_KEEPCAPS as
- * appropriate.
- *
- * If pre_setuid, retain only CAP_NET_BIND_SERVICE, CAP_SETUID, and
- * CAP_SETGID, and use PR_KEEPCAPS to ensure that capabilities persist across
- * setuid().
- *
- * If not pre_setuid, retain only CAP_NET_BIND_SERVICE, and disable
- * PR_KEEPCAPS.
- *
- * Return 0 on success, and -1 on failure.
- */
-static int
-drop_capabilities(int pre_setuid)
-{
- /* We keep these three capabilities, and these only, as we setuid.
- * After we setuid, we drop all but the first. */
- const cap_value_t caplist[] = {
- CAP_NET_BIND_SERVICE, CAP_SETUID, CAP_SETGID
- };
- const char *where = pre_setuid ? "pre-setuid" : "post-setuid";
- const int n_effective = pre_setuid ? 3 : 1;
- const int n_permitted = pre_setuid ? 3 : 1;
- const int n_inheritable = 1;
- const int keepcaps = pre_setuid ? 1 : 0;
-
- /* Sets whether we keep capabilities across a setuid. */
- if (prctl(PR_SET_KEEPCAPS, keepcaps) < 0) {
- log_warn(LD_CONFIG, "Unable to call prctl() %s: %s",
- where, strerror(errno));
- return -1;
- }
-
- cap_t caps = cap_get_proc();
- if (!caps) {
- log_warn(LD_CONFIG, "Unable to call cap_get_proc() %s: %s",
- where, strerror(errno));
- return -1;
- }
- cap_clear(caps);
-
- cap_set_flag(caps, CAP_EFFECTIVE, n_effective, caplist, CAP_SET);
- cap_set_flag(caps, CAP_PERMITTED, n_permitted, caplist, CAP_SET);
- cap_set_flag(caps, CAP_INHERITABLE, n_inheritable, caplist, CAP_SET);
-
- int r = cap_set_proc(caps);
- cap_free(caps);
- if (r < 0) {
- log_warn(LD_CONFIG, "No permission to set capabilities %s: %s",
- where, strerror(errno));
- return -1;
- }
-
- return 0;
-}
-#endif /* defined(HAVE_LINUX_CAPABILITIES) */
-
-/** Call setuid and setgid to run as <b>user</b> and switch to their
- * primary group. Return 0 on success. On failure, log and return -1.
- *
- * If SWITCH_ID_KEEP_BINDLOW is set in 'flags', try to use the capability
- * system to retain the abilitity to bind low ports.
- *
- * If SWITCH_ID_WARN_IF_NO_CAPS is set in flags, also warn if we have
- * don't have capability support.
- */
-int
-switch_id(const char *user, const unsigned flags)
-{
-#ifndef _WIN32
- const struct passwd *pw = NULL;
- uid_t old_uid;
- gid_t old_gid;
- static int have_already_switched_id = 0;
- const int keep_bindlow = !!(flags & SWITCH_ID_KEEP_BINDLOW);
- const int warn_if_no_caps = !!(flags & SWITCH_ID_WARN_IF_NO_CAPS);
-
- tor_assert(user);
-
- if (have_already_switched_id)
- return 0;
-
- /* Log the initial credential state */
- if (log_credential_status())
- return -1;
-
- log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL, "Changing user and groups");
-
- /* Get old UID/GID to check if we changed correctly */
- old_uid = getuid();
- old_gid = getgid();
-
- /* Lookup the user and group information, if we have a problem, bail out. */
- pw = tor_getpwnam(user);
- if (pw == NULL) {
- log_warn(LD_CONFIG, "Error setting configured user: %s not found", user);
- return -1;
- }
-
-#ifdef HAVE_LINUX_CAPABILITIES
- (void) warn_if_no_caps;
- if (keep_bindlow) {
- if (drop_capabilities(1))
- return -1;
- }
-#else /* !(defined(HAVE_LINUX_CAPABILITIES)) */
- (void) keep_bindlow;
- if (warn_if_no_caps) {
- log_warn(LD_CONFIG, "KeepBindCapabilities set, but no capability support "
- "on this system.");
- }
-#endif /* defined(HAVE_LINUX_CAPABILITIES) */
-
- /* Properly switch egid,gid,euid,uid here or bail out */
- if (setgroups(1, &pw->pw_gid)) {
- log_warn(LD_GENERAL, "Error setting groups to gid %d: \"%s\".",
- (int)pw->pw_gid, strerror(errno));
- if (old_uid == pw->pw_uid) {
- log_warn(LD_GENERAL, "Tor is already running as %s. You do not need "
- "the \"User\" option if you are already running as the user "
- "you want to be. (If you did not set the User option in your "
- "torrc, check whether it was specified on the command line "
- "by a startup script.)", user);
- } else {
- log_warn(LD_GENERAL, "If you set the \"User\" option, you must start Tor"
- " as root.");
- }
- return -1;
- }
-
- if (setegid(pw->pw_gid)) {
- log_warn(LD_GENERAL, "Error setting egid to %d: %s",
- (int)pw->pw_gid, strerror(errno));
- return -1;
- }
-
- if (setgid(pw->pw_gid)) {
- log_warn(LD_GENERAL, "Error setting gid to %d: %s",
- (int)pw->pw_gid, strerror(errno));
- return -1;
- }
-
- if (setuid(pw->pw_uid)) {
- log_warn(LD_GENERAL, "Error setting configured uid to %s (%d): %s",
- user, (int)pw->pw_uid, strerror(errno));
- return -1;
- }
-
- if (seteuid(pw->pw_uid)) {
- log_warn(LD_GENERAL, "Error setting configured euid to %s (%d): %s",
- user, (int)pw->pw_uid, strerror(errno));
- return -1;
- }
-
- /* This is how OpenBSD rolls:
- if (setgroups(1, &pw->pw_gid) || setegid(pw->pw_gid) ||
- setgid(pw->pw_gid) || setuid(pw->pw_uid) || seteuid(pw->pw_uid)) {
- setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) {
- log_warn(LD_GENERAL, "Error setting configured UID/GID: %s",
- strerror(errno));
- return -1;
- }
- */
-
- /* We've properly switched egid, gid, euid, uid, and supplementary groups if
- * we're here. */
-#ifdef HAVE_LINUX_CAPABILITIES
- if (keep_bindlow) {
- if (drop_capabilities(0))
- return -1;
- }
-#endif /* defined(HAVE_LINUX_CAPABILITIES) */
-
-#if !defined(CYGWIN) && !defined(__CYGWIN__)
- /* If we tried to drop privilege to a group/user other than root, attempt to
- * restore root (E)(U|G)ID, and abort if the operation succeeds */
-
- /* Only check for privilege dropping if we were asked to be non-root */
- if (pw->pw_uid) {
- /* Try changing GID/EGID */
- if (pw->pw_gid != old_gid &&
- (setgid(old_gid) != -1 || setegid(old_gid) != -1)) {
- log_warn(LD_GENERAL, "Was able to restore group credentials even after "
- "switching GID: this means that the setgid code didn't work.");
- return -1;
- }
-
- /* Try changing UID/EUID */
- if (pw->pw_uid != old_uid &&
- (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) {
- log_warn(LD_GENERAL, "Was able to restore user credentials even after "
- "switching UID: this means that the setuid code didn't work.");
- return -1;
- }
- }
-#endif /* !defined(CYGWIN) && !defined(__CYGWIN__) */
-
- /* Check what really happened */
- if (log_credential_status()) {
- return -1;
- }
-
- have_already_switched_id = 1; /* mark success so we never try again */
-
-#if defined(__linux__) && defined(HAVE_SYS_PRCTL_H) && \
- defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
- if (pw->pw_uid) {
- /* Re-enable core dumps if we're not running as root. */
- log_info(LD_CONFIG, "Re-enabling coredumps");
- if (prctl(PR_SET_DUMPABLE, 1)) {
- log_warn(LD_CONFIG, "Unable to re-enable coredumps: %s",strerror(errno));
- }
- }
-#endif /* defined(__linux__) && defined(HAVE_SYS_PRCTL_H) && ... */
- return 0;
-
-#else /* !(!defined(_WIN32)) */
- (void)user;
- (void)flags;
-
- log_warn(LD_CONFIG, "Switching users is unsupported on your OS.");
- return -1;
-#endif /* !defined(_WIN32) */
-}
-
-/* We only use the linux prctl for now. There is no Win32 support; this may
- * also work on various BSD systems and Mac OS X - send testing feedback!
- *
- * On recent Gnu/Linux kernels it is possible to create a system-wide policy
- * that will prevent non-root processes from attaching to other processes
- * unless they are the parent process; thus gdb can attach to programs that
- * they execute but they cannot attach to other processes running as the same
- * user. The system wide policy may be set with the sysctl
- * kernel.yama.ptrace_scope or by inspecting
- * /proc/sys/kernel/yama/ptrace_scope and it is 1 by default on Ubuntu 11.04.
- *
- * This ptrace scope will be ignored on Gnu/Linux for users with
- * CAP_SYS_PTRACE and so it is very likely that root will still be able to
- * attach to the Tor process.
- */
-/** Attempt to disable debugger attachment: return 1 on success, -1 on
- * failure, and 0 if we don't know how to try on this platform. */
-int
-tor_disable_debugger_attach(void)
-{
- int r = -1;
- log_debug(LD_CONFIG,
- "Attemping to disable debugger attachment to Tor for "
- "unprivileged users.");
-#if defined(__linux__) && defined(HAVE_SYS_PRCTL_H) \
- && defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
-#define TRIED_TO_DISABLE
- r = prctl(PR_SET_DUMPABLE, 0);
-#elif defined(__APPLE__) && defined(PT_DENY_ATTACH)
-#define TRIED_TO_ATTACH
- r = ptrace(PT_DENY_ATTACH, 0, 0, 0);
-#endif /* defined(__linux__) && defined(HAVE_SYS_PRCTL_H) ... || ... */
-
- // XXX: TODO - Mac OS X has dtrace and this may be disabled.
- // XXX: TODO - Windows probably has something similar
-#ifdef TRIED_TO_DISABLE
- if (r == 0) {
- log_debug(LD_CONFIG,"Debugger attachment disabled for "
- "unprivileged users.");
- return 1;
- } else {
- log_warn(LD_CONFIG, "Unable to disable debugger attaching: %s",
- strerror(errno));
- }
-#endif /* defined(TRIED_TO_DISABLE) */
-#undef TRIED_TO_DISABLE
- return r;
-}
-
-#ifdef HAVE_PWD_H
-/** Allocate and return a string containing the home directory for the
- * user <b>username</b>. Only works on posix-like systems. */
-char *
-get_user_homedir(const char *username)
-{
- const struct passwd *pw;
- tor_assert(username);
-
- if (!(pw = tor_getpwnam(username))) {
- log_err(LD_CONFIG,"User \"%s\" not found.", username);
- return NULL;
- }
- return tor_strdup(pw->pw_dir);
-}
-#endif /* defined(HAVE_PWD_H) */
-
-/** 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.
- *
- * Path separators are the forward slash (/) everywhere and additionally
- * the backslash (\) on Win32.
- *
- * Cuts off any number of trailing path separators but otherwise ignores
- * them for purposes of finding the parent directory.
- *
- * Returns 0 if a parent directory was successfully found, -1 otherwise (fname
- * did not have any path separators or only had them at the end).
- * */
-int
-get_parent_directory(char *fname)
-{
- char *cp;
- int at_end = 1;
- tor_assert(fname);
-#ifdef _WIN32
- /* If we start with, say, c:, then don't consider that the start of the path
- */
- if (fname[0] && fname[1] == ':') {
- fname += 2;
- }
-#endif /* defined(_WIN32) */
- /* Now we want to remove all path-separators at the end of the string,
- * and to remove the end of the string starting with the path separator
- * before the last non-path-separator. In perl, this would be
- * s#[/]*$##; s#/[^/]*$##;
- * on a unixy platform.
- */
- cp = fname + strlen(fname);
- at_end = 1;
- while (--cp >= fname) {
- int is_sep = (*cp == '/'
-#ifdef _WIN32
- || *cp == '\\'
-#endif
- );
- if (is_sep) {
- if (cp == fname) {
- /* This is the first separator in the file name; don't remove it! */
- cp[1] = '\0';
- return 0;
- }
- *cp = '\0';
- if (! at_end)
- return 0;
- } else {
- at_end = 0;
- }
- }
- return -1;
-}
-
-#ifndef _WIN32
-/** Return a newly allocated string containing the output of getcwd(). Return
- * NULL on failure. (We can't just use getcwd() into a PATH_MAX buffer, since
- * Hurd hasn't got a PATH_MAX.)
- */
-static char *
-alloc_getcwd(void)
-{
-#ifdef HAVE_GET_CURRENT_DIR_NAME
- /* Glibc makes this nice and simple for us. */
- char *cwd = get_current_dir_name();
- char *result = NULL;
- if (cwd) {
- /* We make a copy here, in case tor_malloc() is not malloc(). */
- result = tor_strdup(cwd);
- raw_free(cwd); // alias for free to avoid tripping check-spaces.
- }
- return result;
-#else /* !(defined(HAVE_GET_CURRENT_DIR_NAME)) */
- size_t size = 1024;
- char *buf = NULL;
- char *ptr = NULL;
-
- while (ptr == NULL) {
- buf = tor_realloc(buf, size);
- ptr = getcwd(buf, size);
-
- if (ptr == NULL && errno != ERANGE) {
- tor_free(buf);
- return NULL;
- }
-
- size *= 2;
- }
- return buf;
-#endif /* defined(HAVE_GET_CURRENT_DIR_NAME) */
-}
-#endif /* !defined(_WIN32) */
-
-/** Expand possibly relative path <b>fname</b> to an absolute path.
- * Return a newly allocated string, possibly equal to <b>fname</b>. */
-char *
-make_path_absolute(char *fname)
-{
-#ifdef _WIN32
- char *absfname_malloced = _fullpath(NULL, fname, 1);
-
- /* We don't want to assume that tor_free can free a string allocated
- * with malloc. On failure, return fname (it's better than nothing). */
- char *absfname = tor_strdup(absfname_malloced ? absfname_malloced : fname);
- if (absfname_malloced) raw_free(absfname_malloced);
-
- return absfname;
-#else /* !(defined(_WIN32)) */
- char *absfname = NULL, *path = NULL;
-
- tor_assert(fname);
-
- if (fname[0] == '/') {
- absfname = tor_strdup(fname);
- } else {
- path = alloc_getcwd();
- if (path) {
- tor_asprintf(&absfname, "%s/%s", path, fname);
- tor_free(path);
- } else {
- /* LCOV_EXCL_START Can't make getcwd fail. */
- /* If getcwd failed, the best we can do here is keep using the
- * relative path. (Perhaps / isn't readable by this UID/GID.) */
- log_warn(LD_GENERAL, "Unable to find current working directory: %s",
- strerror(errno));
- absfname = tor_strdup(fname);
- /* LCOV_EXCL_STOP */
- }
- }
- return absfname;
-#endif /* defined(_WIN32) */
-}
-
-#ifndef HAVE__NSGETENVIRON
-#ifndef HAVE_EXTERN_ENVIRON_DECLARED
-/* Some platforms declare environ under some circumstances, others don't. */
-#ifndef RUNNING_DOXYGEN
-extern char **environ;
-#endif
-#endif /* !defined(HAVE_EXTERN_ENVIRON_DECLARED) */
-#endif /* !defined(HAVE__NSGETENVIRON) */
-
-/** Return the current environment. This is a portable replacement for
- * 'environ'. */
-char **
-get_environment(void)
-{
-#ifdef HAVE__NSGETENVIRON
- /* This is for compatibility between OSX versions. Otherwise (for example)
- * when we do a mostly-static build on OSX 10.7, the resulting binary won't
- * work on OSX 10.6. */
- return *_NSGetEnviron();
-#else /* !(defined(HAVE__NSGETENVIRON)) */
- return environ;
-#endif /* defined(HAVE__NSGETENVIRON) */
-}
-
-/** Get name of current host and write it to <b>name</b> array, whose
- * length is specified by <b>namelen</b> argument. Return 0 upon
- * successful completion; otherwise return return -1. (Currently,
- * this function is merely a mockable wrapper for POSIX gethostname().)
- */
-MOCK_IMPL(int,
-tor_gethostname,(char *name, size_t namelen))
-{
- return gethostname(name,namelen);
-}
-
-/** Set *addr to the IP address (in dotted-quad notation) stored in *str.
- * Return 1 on success, 0 if *str is badly formatted.
- * (Like inet_aton(str,addr), but works on Windows and Solaris.)
- */
-int
-tor_inet_aton(const char *str, struct in_addr* addr)
-{
- unsigned a,b,c,d;
- char more;
- if (tor_sscanf(str, "%3u.%3u.%3u.%3u%c", &a,&b,&c,&d,&more) != 4)
- return 0;
- if (a > 255) return 0;
- if (b > 255) return 0;
- if (c > 255) return 0;
- if (d > 255) return 0;
- addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d);
- return 1;
-}
-
-/** Given <b>af</b>==AF_INET and <b>src</b> a struct in_addr, or
- * <b>af</b>==AF_INET6 and <b>src</b> a struct in6_addr, try to format the
- * address and store it in the <b>len</b>-byte buffer <b>dst</b>. Returns
- * <b>dst</b> on success, NULL on failure.
- *
- * (Like inet_ntop(af,src,dst,len), but works on platforms that don't have it:
- * Tor sometimes needs to format ipv6 addresses even on platforms without ipv6
- * support.) */
-const char *
-tor_inet_ntop(int af, const void *src, char *dst, size_t len)
-{
- if (af == AF_INET) {
- if (tor_inet_ntoa(src, dst, len) < 0)
- return NULL;
- else
- return dst;
- } else if (af == AF_INET6) {
- const struct in6_addr *addr = src;
- char buf[64], *cp;
- int longestGapLen = 0, longestGapPos = -1, i,
- curGapPos = -1, curGapLen = 0;
- uint16_t words[8];
- for (i = 0; i < 8; ++i) {
- words[i] = (((uint16_t)addr->s6_addr[2*i])<<8) + addr->s6_addr[2*i+1];
- }
- if (words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
- words[4] == 0 && ((words[5] == 0 && words[6] && words[7]) ||
- (words[5] == 0xffff))) {
- /* This is an IPv4 address. */
- if (words[5] == 0) {
- tor_snprintf(buf, sizeof(buf), "::%d.%d.%d.%d",
- addr->s6_addr[12], addr->s6_addr[13],
- addr->s6_addr[14], addr->s6_addr[15]);
- } else {
- tor_snprintf(buf, sizeof(buf), "::%x:%d.%d.%d.%d", words[5],
- addr->s6_addr[12], addr->s6_addr[13],
- addr->s6_addr[14], addr->s6_addr[15]);
- }
- if ((strlen(buf) + 1) > len) /* +1 for \0 */
- return NULL;
- strlcpy(dst, buf, len);
- return dst;
- }
- i = 0;
- while (i < 8) {
- if (words[i] == 0) {
- curGapPos = i++;
- curGapLen = 1;
- while (i<8 && words[i] == 0) {
- ++i; ++curGapLen;
- }
- if (curGapLen > longestGapLen) {
- longestGapPos = curGapPos;
- longestGapLen = curGapLen;
- }
- } else {
- ++i;
- }
- }
- if (longestGapLen<=1)
- longestGapPos = -1;
-
- cp = buf;
- for (i = 0; i < 8; ++i) {
- if (words[i] == 0 && longestGapPos == i) {
- if (i == 0)
- *cp++ = ':';
- *cp++ = ':';
- while (i < 8 && words[i] == 0)
- ++i;
- --i; /* to compensate for loop increment. */
- } else {
- tor_snprintf(cp, sizeof(buf)-(cp-buf), "%x", (unsigned)words[i]);
- cp += strlen(cp);
- if (i != 7)
- *cp++ = ':';
- }
- }
- *cp = '\0';
- if ((strlen(buf) + 1) > len) /* +1 for \0 */
- return NULL;
- strlcpy(dst, buf, len);
- return dst;
- } else {
- return NULL;
- }
-}
-
-/** Given <b>af</b>==AF_INET or <b>af</b>==AF_INET6, and a string <b>src</b>
- * encoding an IPv4 address or IPv6 address correspondingly, try to parse the
- * address and store the result in <b>dst</b> (which must have space for a
- * struct in_addr or a struct in6_addr, as appropriate). Return 1 on success,
- * 0 on a bad parse, and -1 on a bad <b>af</b>.
- *
- * (Like inet_pton(af,src,dst) but works on platforms that don't have it: Tor
- * sometimes needs to format ipv6 addresses even on platforms without ipv6
- * support.) */
-int
-tor_inet_pton(int af, const char *src, void *dst)
-{
- if (af == AF_INET) {
- return tor_inet_aton(src, dst);
- } else if (af == AF_INET6) {
- struct in6_addr *out = dst;
- uint16_t words[8];
- int gapPos = -1, i, setWords=0;
- const char *dot = strchr(src, '.');
- const char *eow; /* end of words. */
- memset(words, 0xf8, sizeof(words));
- if (dot == src)
- return 0;
- else if (!dot)
- eow = src+strlen(src);
- else {
- unsigned byte1,byte2,byte3,byte4;
- char more;
- for (eow = dot-1; eow > src && TOR_ISDIGIT(*eow); --eow)
- ;
- if (*eow != ':')
- return 0;
- ++eow;
-
- /* We use "scanf" because some platform inet_aton()s are too lax
- * about IPv4 addresses of the form "1.2.3" */
- if (tor_sscanf(eow, "%3u.%3u.%3u.%3u%c",
- &byte1,&byte2,&byte3,&byte4,&more) != 4)
- return 0;
-
- if (byte1 > 255 || byte2 > 255 || byte3 > 255 || byte4 > 255)
- return 0;
-
- words[6] = (byte1<<8) | byte2;
- words[7] = (byte3<<8) | byte4;
- setWords += 2;
- }
-
- i = 0;
- while (src < eow) {
- if (i > 7)
- return 0;
- if (TOR_ISXDIGIT(*src)) {
- char *next;
- ssize_t len;
- long r = strtol(src, &next, 16);
- if (next == NULL || next == src) {
- /* The 'next == src' error case can happen on versions of openbsd
- * which treat "0xfoo" as an error, rather than as "0" followed by
- * "xfoo". */
- return 0;
- }
-
- len = *next == '\0' ? eow - src : next - src;
- if (len > 4)
- return 0;
- if (len > 1 && !TOR_ISXDIGIT(src[1]))
- return 0; /* 0x is not valid */
-
- tor_assert(r >= 0);
- tor_assert(r < 65536);
- words[i++] = (uint16_t)r;
- setWords++;
- src = next;
- if (*src != ':' && src != eow)
- return 0;
- ++src;
- } else if (*src == ':' && i > 0 && gapPos == -1) {
- gapPos = i;
- ++src;
- } else if (*src == ':' && i == 0 && src+1 < eow && src[1] == ':' &&
- gapPos == -1) {
- gapPos = i;
- src += 2;
- } else {
- return 0;
- }
- }
-
- if (setWords > 8 ||
- (setWords == 8 && gapPos != -1) ||
- (setWords < 8 && gapPos == -1))
- return 0;
-
- if (gapPos >= 0) {
- int nToMove = setWords - (dot ? 2 : 0) - gapPos;
- int gapLen = 8 - setWords;
- tor_assert(nToMove >= 0);
- memmove(&words[gapPos+gapLen], &words[gapPos],
- sizeof(uint16_t)*nToMove);
- memset(&words[gapPos], 0, sizeof(uint16_t)*gapLen);
- }
- for (i = 0; i < 8; ++i) {
- out->s6_addr[2*i ] = words[i] >> 8;
- out->s6_addr[2*i+1] = words[i] & 0xff;
- }
-
- return 1;
- } else {
- return -1;
- }
-}
-
-/** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
- * *<b>addr</b> to the proper IP address, in host byte order. Returns 0
- * on success, -1 on failure; 1 on transient failure.
- *
- * (This function exists because standard windows gethostbyname
- * doesn't treat raw IP addresses properly.)
- */
-
-MOCK_IMPL(int,
-tor_lookup_hostname,(const char *name, uint32_t *addr))
-{
- tor_addr_t myaddr;
- int ret;
-
- if ((ret = tor_addr_lookup(name, AF_INET, &myaddr)))
- return ret;
-
- if (tor_addr_family(&myaddr) == AF_INET) {
- *addr = tor_addr_to_ipv4h(&myaddr);
- return ret;
- }
-
- return -1;
-}
-
-/** Hold the result of our call to <b>uname</b>. */
-static char uname_result[256];
-/** True iff uname_result is set. */
-static int uname_result_is_set = 0;
-
-/** Return a pointer to a description of our platform.
- */
-MOCK_IMPL(const char *,
-get_uname,(void))
-{
-#ifdef HAVE_UNAME
- struct utsname u;
-#endif
- if (!uname_result_is_set) {
-#ifdef HAVE_UNAME
- if (uname(&u) != -1) {
- /* (Linux says 0 is success, Solaris says 1 is success) */
- strlcpy(uname_result, u.sysname, sizeof(uname_result));
- } else
-#endif /* defined(HAVE_UNAME) */
- {
-#ifdef _WIN32
- OSVERSIONINFOEX info;
- int i;
- const char *plat = NULL;
- static struct {
- unsigned major; unsigned minor; const char *version;
- } win_version_table[] = {
- { 6, 2, "Windows 8" },
- { 6, 1, "Windows 7" },
- { 6, 0, "Windows Vista" },
- { 5, 2, "Windows Server 2003" },
- { 5, 1, "Windows XP" },
- { 5, 0, "Windows 2000" },
- /* { 4, 0, "Windows NT 4.0" }, */
- { 4, 90, "Windows Me" },
- { 4, 10, "Windows 98" },
- /* { 4, 0, "Windows 95" } */
- { 3, 51, "Windows NT 3.51" },
- { 0, 0, NULL }
- };
- memset(&info, 0, sizeof(info));
- info.dwOSVersionInfoSize = sizeof(info);
- if (! GetVersionEx((LPOSVERSIONINFO)&info)) {
- strlcpy(uname_result, "Bizarre version of Windows where GetVersionEx"
- " doesn't work.", sizeof(uname_result));
- uname_result_is_set = 1;
- return uname_result;
- }
- if (info.dwMajorVersion == 4 && info.dwMinorVersion == 0) {
- if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
- plat = "Windows NT 4.0";
- else
- plat = "Windows 95";
- } else {
- for (i=0; win_version_table[i].major>0; ++i) {
- if (win_version_table[i].major == info.dwMajorVersion &&
- win_version_table[i].minor == info.dwMinorVersion) {
- plat = win_version_table[i].version;
- break;
- }
- }
- }
- if (plat) {
- strlcpy(uname_result, plat, sizeof(uname_result));
- } else {
- if (info.dwMajorVersion > 6 ||
- (info.dwMajorVersion==6 && info.dwMinorVersion>2))
- tor_snprintf(uname_result, sizeof(uname_result),
- "Very recent version of Windows [major=%d,minor=%d]",
- (int)info.dwMajorVersion,(int)info.dwMinorVersion);
- else
- tor_snprintf(uname_result, sizeof(uname_result),
- "Unrecognized version of Windows [major=%d,minor=%d]",
- (int)info.dwMajorVersion,(int)info.dwMinorVersion);
- }
-#ifdef VER_NT_SERVER
- if (info.wProductType == VER_NT_SERVER ||
- info.wProductType == VER_NT_DOMAIN_CONTROLLER) {
- strlcat(uname_result, " [server]", sizeof(uname_result));
- }
-#endif /* defined(VER_NT_SERVER) */
-#else /* !(defined(_WIN32)) */
- /* LCOV_EXCL_START -- can't provoke uname failure */
- strlcpy(uname_result, "Unknown platform", sizeof(uname_result));
- /* LCOV_EXCL_STOP */
-#endif /* defined(_WIN32) */
- }
- uname_result_is_set = 1;
- }
- return uname_result;
-}
-
-/*
- * Process control
- */
-
-/** Implementation logic for compute_num_cpus(). */
-static int
-compute_num_cpus_impl(void)
-{
-#ifdef _WIN32
- SYSTEM_INFO info;
- memset(&info, 0, sizeof(info));
- GetSystemInfo(&info);
- if (info.dwNumberOfProcessors >= 1 && info.dwNumberOfProcessors < INT_MAX)
- return (int)info.dwNumberOfProcessors;
- else
- return -1;
-#elif defined(HAVE_SYSCONF)
-#ifdef _SC_NPROCESSORS_CONF
- long cpus_conf = sysconf(_SC_NPROCESSORS_CONF);
-#else
- long cpus_conf = -1;
-#endif
-#ifdef _SC_NPROCESSORS_ONLN
- long cpus_onln = sysconf(_SC_NPROCESSORS_ONLN);
-#else
- long cpus_onln = -1;
-#endif
- long cpus = -1;
-
- if (cpus_conf > 0 && cpus_onln < 0) {
- cpus = cpus_conf;
- } else if (cpus_onln > 0 && cpus_conf < 0) {
- cpus = cpus_onln;
- } else if (cpus_onln > 0 && cpus_conf > 0) {
- if (cpus_onln < cpus_conf) {
- log_notice(LD_GENERAL, "I think we have %ld CPUS, but only %ld of them "
- "are available. Telling Tor to only use %ld. You can over"
- "ride this with the NumCPUs option",
- cpus_conf, cpus_onln, cpus_onln);
- }
- cpus = cpus_onln;
- }
-
- if (cpus >= 1 && cpus < INT_MAX)
- return (int)cpus;
- else
- return -1;
-#else
- return -1;
-#endif /* defined(_WIN32) || ... */
-}
-
-#define MAX_DETECTABLE_CPUS 16
-
-/** Return how many CPUs we are running with. We assume that nobody is
- * using hot-swappable CPUs, so we don't recompute this after the first
- * time. Return -1 if we don't know how to tell the number of CPUs on this
- * system.
- */
-int
-compute_num_cpus(void)
-{
- static int num_cpus = -2;
- if (num_cpus == -2) {
- num_cpus = compute_num_cpus_impl();
- tor_assert(num_cpus != -2);
- if (num_cpus > MAX_DETECTABLE_CPUS) {
- /* LCOV_EXCL_START */
- log_notice(LD_GENERAL, "Wow! I detected that you have %d CPUs. I "
- "will not autodetect any more than %d, though. If you "
- "want to configure more, set NumCPUs in your torrc",
- num_cpus, MAX_DETECTABLE_CPUS);
- num_cpus = MAX_DETECTABLE_CPUS;
- /* LCOV_EXCL_STOP */
- }
- }
- return num_cpus;
-}
-
-#if !defined(_WIN32)
-/** Defined iff we need to add locks when defining fake versions of reentrant
- * versions of time-related functions. */
-#define TIME_FNS_NEED_LOCKS
-#endif
-
-/** Helper: Deal with confused or out-of-bounds values from localtime_r and
- * friends. (On some platforms, they can give out-of-bounds values or can
- * return NULL.) If <b>islocal</b>, this is a localtime result; otherwise
- * it's from gmtime. The function returns <b>r</b>, when given <b>timep</b>
- * as its input. If we need to store new results, store them in
- * <b>resultbuf</b>. */
-static struct tm *
-correct_tm(int islocal, const time_t *timep, struct tm *resultbuf,
- struct tm *r)
-{
- const char *outcome;
-
- if (PREDICT_LIKELY(r)) {
- /* We can't strftime dates after 9999 CE, and we want to avoid dates
- * before 1 CE (avoiding the year 0 issue and negative years). */
- if (r->tm_year > 8099) {
- r->tm_year = 8099;
- r->tm_mon = 11;
- r->tm_mday = 31;
- r->tm_yday = 364;
- r->tm_wday = 6;
- r->tm_hour = 23;
- r->tm_min = 59;
- r->tm_sec = 59;
- } else if (r->tm_year < (1-1900)) {
- r->tm_year = (1-1900);
- r->tm_mon = 0;
- r->tm_mday = 1;
- r->tm_yday = 0;
- r->tm_wday = 0;
- r->tm_hour = 0;
- r->tm_min = 0;
- r->tm_sec = 0;
- }
- return r;
- }
-
- /* If we get here, gmtime or localtime returned NULL. It might have done
- * this because of overrun or underrun, or it might have done it because of
- * some other weird issue. */
- if (timep) {
- if (*timep < 0) {
- r = resultbuf;
- r->tm_year = 70; /* 1970 CE */
- r->tm_mon = 0;
- r->tm_mday = 1;
- r->tm_yday = 0;
- r->tm_wday = 0;
- r->tm_hour = 0;
- r->tm_min = 0 ;
- r->tm_sec = 0;
- outcome = "Rounding up to 1970";
- goto done;
- } else if (*timep >= INT32_MAX) {
- /* Rounding down to INT32_MAX isn't so great, but keep in mind that we
- * only do it if gmtime/localtime tells us NULL. */
- r = resultbuf;
- r->tm_year = 137; /* 2037 CE */
- r->tm_mon = 11;
- r->tm_mday = 31;
- r->tm_yday = 364;
- r->tm_wday = 6;
- r->tm_hour = 23;
- r->tm_min = 59;
- r->tm_sec = 59;
- outcome = "Rounding down to 2037";
- goto done;
- }
- }
-
- /* If we get here, then gmtime/localtime failed without getting an extreme
- * value for *timep */
- /* LCOV_EXCL_START */
- tor_fragile_assert();
- r = resultbuf;
- memset(resultbuf, 0, sizeof(struct tm));
- outcome="can't recover";
- /* LCOV_EXCL_STOP */
- done:
- log_warn(LD_BUG, "%s("I64_FORMAT") failed with error %s: %s",
- islocal?"localtime":"gmtime",
- timep?I64_PRINTF_ARG(*timep):0,
- strerror(errno),
- outcome);
- return r;
-}
-
-/** @{ */
-/** As localtime_r, but defined for platforms that don't have it:
- *
- * Convert *<b>timep</b> to a struct tm in local time, and store the value in
- * *<b>result</b>. Return the result on success, or NULL on failure.
- */
-#ifdef HAVE_LOCALTIME_R
-struct tm *
-tor_localtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *r;
- r = localtime_r(timep, result);
- return correct_tm(1, timep, result, r);
-}
-#elif defined(TIME_FNS_NEED_LOCKS)
-struct tm *
-tor_localtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *r;
- static tor_mutex_t *m=NULL;
- if (!m) { m=tor_mutex_new(); }
- tor_assert(result);
- tor_mutex_acquire(m);
- r = localtime(timep);
- if (r)
- memcpy(result, r, sizeof(struct tm));
- tor_mutex_release(m);
- return correct_tm(1, timep, result, r);
-}
-#else
-struct tm *
-tor_localtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *r;
- tor_assert(result);
- r = localtime(timep);
- if (r)
- memcpy(result, r, sizeof(struct tm));
- return correct_tm(1, timep, result, r);
-}
-#endif /* defined(HAVE_LOCALTIME_R) || ... */
-/** @} */
-
-/** @{ */
-/** As gmtime_r, but defined for platforms that don't have it:
- *
- * Convert *<b>timep</b> to a struct tm in UTC, and store the value in
- * *<b>result</b>. Return the result on success, or NULL on failure.
- */
-#ifdef HAVE_GMTIME_R
-struct tm *
-tor_gmtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *r;
- r = gmtime_r(timep, result);
- return correct_tm(0, timep, result, r);
-}
-#elif defined(TIME_FNS_NEED_LOCKS)
-struct tm *
-tor_gmtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *r;
- static tor_mutex_t *m=NULL;
- if (!m) { m=tor_mutex_new(); }
- tor_assert(result);
- tor_mutex_acquire(m);
- r = gmtime(timep);
- if (r)
- memcpy(result, r, sizeof(struct tm));
- tor_mutex_release(m);
- return correct_tm(0, timep, result, r);
-}
-#else
-struct tm *
-tor_gmtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *r;
- tor_assert(result);
- r = gmtime(timep);
- if (r)
- memcpy(result, r, sizeof(struct tm));
- return correct_tm(0, timep, result, r);
-}
-#endif /* defined(HAVE_GMTIME_R) || ... */
-
-#if defined(HAVE_MLOCKALL) && HAVE_DECL_MLOCKALL && defined(RLIMIT_MEMLOCK)
-#define HAVE_UNIX_MLOCKALL
-#endif
-
-#ifdef HAVE_UNIX_MLOCKALL
-/** Attempt to raise the current and max rlimit to infinity for our process.
- * This only needs to be done once and can probably only be done when we have
- * not already dropped privileges.
- */
-static int
-tor_set_max_memlock(void)
-{
- /* Future consideration for Windows is probably SetProcessWorkingSetSize
- * This is similar to setting the memory rlimit of RLIMIT_MEMLOCK
- * http://msdn.microsoft.com/en-us/library/ms686234(VS.85).aspx
- */
-
- struct rlimit limit;
-
- /* RLIM_INFINITY is -1 on some platforms. */
- limit.rlim_cur = RLIM_INFINITY;
- limit.rlim_max = RLIM_INFINITY;
-
- if (setrlimit(RLIMIT_MEMLOCK, &limit) == -1) {
- if (errno == EPERM) {
- log_warn(LD_GENERAL, "You appear to lack permissions to change memory "
- "limits. Are you root?");
- }
- log_warn(LD_GENERAL, "Unable to raise RLIMIT_MEMLOCK: %s",
- strerror(errno));
- return -1;
- }
-
- return 0;
-}
-#endif /* defined(HAVE_UNIX_MLOCKALL) */
-
-/** Attempt to lock all current and all future memory pages.
- * This should only be called once and while we're privileged.
- * Like mlockall() we return 0 when we're successful and -1 when we're not.
- * Unlike mlockall() we return 1 if we've already attempted to lock memory.
- */
-int
-tor_mlockall(void)
-{
- static int memory_lock_attempted = 0;
-
- if (memory_lock_attempted) {
- return 1;
- }
-
- memory_lock_attempted = 1;
-
- /*
- * Future consideration for Windows may be VirtualLock
- * VirtualLock appears to implement mlock() but not mlockall()
- *
- * http://msdn.microsoft.com/en-us/library/aa366895(VS.85).aspx
- */
-
-#ifdef HAVE_UNIX_MLOCKALL
- if (tor_set_max_memlock() == 0) {
- log_debug(LD_GENERAL, "RLIMIT_MEMLOCK is now set to RLIM_INFINITY.");
- }
-
- if (mlockall(MCL_CURRENT|MCL_FUTURE) == 0) {
- log_info(LD_GENERAL, "Insecure OS paging is effectively disabled.");
- return 0;
- } else {
- if (errno == ENOSYS) {
- /* Apple - it's 2009! I'm looking at you. Grrr. */
- log_notice(LD_GENERAL, "It appears that mlockall() is not available on "
- "your platform.");
- } else if (errno == EPERM) {
- log_notice(LD_GENERAL, "It appears that you lack the permissions to "
- "lock memory. Are you root?");
- }
- log_notice(LD_GENERAL, "Unable to lock all current and future memory "
- "pages: %s", strerror(errno));
- return -1;
- }
-#else /* !(defined(HAVE_UNIX_MLOCKALL)) */
- log_warn(LD_GENERAL, "Unable to lock memory pages. mlockall() unsupported?");
- return -1;
-#endif /* defined(HAVE_UNIX_MLOCKALL) */
-}
-
-/**
- * On Windows, WSAEWOULDBLOCK is not always correct: when you see it,
- * you need to ask the socket for its actual errno. Also, you need to
- * get your errors from WSAGetLastError, not errno. (If you supply a
- * socket of -1, we check WSAGetLastError, but don't correct
- * WSAEWOULDBLOCKs.)
- *
- * The upshot of all of this is that when a socket call fails, you
- * should call tor_socket_errno <em>at most once</em> on the failing
- * socket to get the error.
- */
-#if defined(_WIN32)
-int
-tor_socket_errno(tor_socket_t sock)
-{
- int optval, optvallen=sizeof(optval);
- int err = WSAGetLastError();
- if (err == WSAEWOULDBLOCK && SOCKET_OK(sock)) {
- if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, &optvallen))
- return err;
- if (optval)
- return optval;
- }
- return err;
-}
-#endif /* defined(_WIN32) */
-
-#if defined(_WIN32)
-#define E(code, s) { code, (s " [" #code " ]") }
-struct { int code; const char *msg; } windows_socket_errors[] = {
- E(WSAEINTR, "Interrupted function call"),
- E(WSAEACCES, "Permission denied"),
- E(WSAEFAULT, "Bad address"),
- E(WSAEINVAL, "Invalid argument"),
- E(WSAEMFILE, "Too many open files"),
- E(WSAEWOULDBLOCK, "Resource temporarily unavailable"),
- E(WSAEINPROGRESS, "Operation now in progress"),
- E(WSAEALREADY, "Operation already in progress"),
- E(WSAENOTSOCK, "Socket operation on nonsocket"),
- E(WSAEDESTADDRREQ, "Destination address required"),
- E(WSAEMSGSIZE, "Message too long"),
- E(WSAEPROTOTYPE, "Protocol wrong for socket"),
- E(WSAENOPROTOOPT, "Bad protocol option"),
- E(WSAEPROTONOSUPPORT, "Protocol not supported"),
- E(WSAESOCKTNOSUPPORT, "Socket type not supported"),
- /* What's the difference between NOTSUPP and NOSUPPORT? :) */
- E(WSAEOPNOTSUPP, "Operation not supported"),
- E(WSAEPFNOSUPPORT, "Protocol family not supported"),
- E(WSAEAFNOSUPPORT, "Address family not supported by protocol family"),
- E(WSAEADDRINUSE, "Address already in use"),
- E(WSAEADDRNOTAVAIL, "Cannot assign requested address"),
- E(WSAENETDOWN, "Network is down"),
- E(WSAENETUNREACH, "Network is unreachable"),
- E(WSAENETRESET, "Network dropped connection on reset"),
- E(WSAECONNABORTED, "Software caused connection abort"),
- E(WSAECONNRESET, "Connection reset by peer"),
- E(WSAENOBUFS, "No buffer space available"),
- E(WSAEISCONN, "Socket is already connected"),
- E(WSAENOTCONN, "Socket is not connected"),
- E(WSAESHUTDOWN, "Cannot send after socket shutdown"),
- E(WSAETIMEDOUT, "Connection timed out"),
- E(WSAECONNREFUSED, "Connection refused"),
- E(WSAEHOSTDOWN, "Host is down"),
- E(WSAEHOSTUNREACH, "No route to host"),
- E(WSAEPROCLIM, "Too many processes"),
- /* Yes, some of these start with WSA, not WSAE. No, I don't know why. */
- E(WSASYSNOTREADY, "Network subsystem is unavailable"),
- E(WSAVERNOTSUPPORTED, "Winsock.dll out of range"),
- E(WSANOTINITIALISED, "Successful WSAStartup not yet performed"),
- E(WSAEDISCON, "Graceful shutdown now in progress"),
-#ifdef WSATYPE_NOT_FOUND
- E(WSATYPE_NOT_FOUND, "Class type not found"),
-#endif
- E(WSAHOST_NOT_FOUND, "Host not found"),
- E(WSATRY_AGAIN, "Nonauthoritative host not found"),
- E(WSANO_RECOVERY, "This is a nonrecoverable error"),
- E(WSANO_DATA, "Valid name, no data record of requested type)"),
-
- /* There are some more error codes whose numeric values are marked
- * <b>OS dependent</b>. They start with WSA_, apparently for the same
- * reason that practitioners of some craft traditions deliberately
- * introduce imperfections into their baskets and rugs "to allow the
- * evil spirits to escape." If we catch them, then our binaries
- * might not report consistent results across versions of Windows.
- * Thus, I'm going to let them all fall through.
- */
- { -1, NULL },
-};
-/** There does not seem to be a strerror equivalent for Winsock errors.
- * Naturally, we have to roll our own.
- */
-const char *
-tor_socket_strerror(int e)
-{
- int i;
- for (i=0; windows_socket_errors[i].code >= 0; ++i) {
- if (e == windows_socket_errors[i].code)
- return windows_socket_errors[i].msg;
- }
- return strerror(e);
-}
-#endif /* defined(_WIN32) */
-
-/** Called before we make any calls to network-related functions.
- * (Some operating systems require their network libraries to be
- * initialized.) */
-int
-network_init(void)
-{
-#ifdef _WIN32
- /* This silly exercise is necessary before windows will allow
- * gethostbyname to work. */
- WSADATA WSAData;
- int r;
- r = WSAStartup(0x101,&WSAData);
- if (r) {
- log_warn(LD_NET,"Error initializing windows network layer: code was %d",r);
- return -1;
- }
- if (sizeof(SOCKET) != sizeof(tor_socket_t)) {
- log_warn(LD_BUG,"The tor_socket_t type does not match SOCKET in size; Tor "
- "might not work. (Sizes are %d and %d respectively.)",
- (int)sizeof(tor_socket_t), (int)sizeof(SOCKET));
- }
- /* WSAData.iMaxSockets might show the max sockets we're allowed to use.
- * We might use it to complain if we're trying to be a server but have
- * too few sockets available. */
-#endif /* defined(_WIN32) */
- return 0;
-}
-
-#ifdef _WIN32
-/** Return a newly allocated string describing the windows system error code
- * <b>err</b>. Note that error codes are different from errno. Error codes
- * come from GetLastError() when a winapi call fails. errno is set only when
- * ANSI functions fail. Whee. */
-char *
-format_win32_error(DWORD err)
-{
- TCHAR *str = NULL;
- char *result;
- DWORD n;
-
- /* Somebody once decided that this interface was better than strerror(). */
- n = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, err,
- MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
- (LPVOID)&str,
- 0, NULL);
-
- if (str && n) {
-#ifdef UNICODE
- size_t len;
- if (n > 128*1024)
- len = (128 * 1024) * 2 + 1; /* This shouldn't be possible, but let's
- * make sure. */
- else
- len = n * 2 + 1;
- result = tor_malloc(len);
- wcstombs(result,str,len);
- result[len-1] = '\0';
-#else /* !(defined(UNICODE)) */
- result = tor_strdup(str);
-#endif /* defined(UNICODE) */
- } else {
- result = tor_strdup("<unformattable error>");
- }
- if (str) {
- LocalFree(str); /* LocalFree != free() */
- }
- return result;
-}
-#endif /* defined(_WIN32) */
-
-#if defined(HW_PHYSMEM64)
-/* This appears to be an OpenBSD thing */
-#define INT64_HW_MEM HW_PHYSMEM64
-#elif defined(HW_MEMSIZE)
-/* OSX defines this one */
-#define INT64_HW_MEM HW_MEMSIZE
-#endif /* defined(HW_PHYSMEM64) || ... */
-
-/**
- * Helper: try to detect the total system memory, and return it. On failure,
- * return 0.
- */
-static uint64_t
-get_total_system_memory_impl(void)
-{
-#if defined(__linux__)
- /* On linux, sysctl is deprecated. Because proc is so awesome that you
- * shouldn't _want_ to write portable code, I guess? */
- unsigned long long result=0;
- int fd = -1;
- char *s = NULL;
- const char *cp;
- size_t file_size=0;
- if (-1 == (fd = tor_open_cloexec("/proc/meminfo",O_RDONLY,0)))
- return 0;
- s = read_file_to_str_until_eof(fd, 65536, &file_size);
- if (!s)
- goto err;
- cp = strstr(s, "MemTotal:");
- if (!cp)
- goto err;
- /* Use the system sscanf so that space will match a wider number of space */
- if (sscanf(cp, "MemTotal: %llu kB\n", &result) != 1)
- goto err;
-
- close(fd);
- tor_free(s);
- return result * 1024;
-
- /* LCOV_EXCL_START Can't reach this unless proc is broken. */
- err:
- tor_free(s);
- close(fd);
- return 0;
- /* LCOV_EXCL_STOP */
-#elif defined (_WIN32)
- /* Windows has MEMORYSTATUSEX; pretty straightforward. */
- MEMORYSTATUSEX ms;
- memset(&ms, 0, sizeof(ms));
- ms.dwLength = sizeof(ms);
- if (! GlobalMemoryStatusEx(&ms))
- return 0;
-
- return ms.ullTotalPhys;
-
-#elif defined(HAVE_SYSCTL) && defined(INT64_HW_MEM)
- /* On many systems, HW_PYHSMEM is clipped to 32 bits; let's use a better
- * variant if we know about it. */
- uint64_t memsize = 0;
- size_t len = sizeof(memsize);
- int mib[2] = {CTL_HW, INT64_HW_MEM};
- if (sysctl(mib,2,&memsize,&len,NULL,0))
- return 0;
-
- return memsize;
-
-#elif defined(HAVE_SYSCTL) && defined(HW_PHYSMEM)
- /* On some systems (like FreeBSD I hope) you can use a size_t with
- * HW_PHYSMEM. */
- size_t memsize=0;
- size_t len = sizeof(memsize);
- int mib[2] = {CTL_HW, HW_USERMEM};
- if (sysctl(mib,2,&memsize,&len,NULL,0))
- return 0;
-
- return memsize;
-
-#else
- /* I have no clue. */
- return 0;
-#endif /* defined(__linux__) || ... */
-}
-
-/**
- * Try to find out how much physical memory the system has. On success,
- * return 0 and set *<b>mem_out</b> to that value. On failure, return -1.
- */
-MOCK_IMPL(int,
-get_total_system_memory, (size_t *mem_out))
-{
- static size_t mem_cached=0;
- uint64_t m = get_total_system_memory_impl();
- if (0 == m) {
- /* LCOV_EXCL_START -- can't make this happen without mocking. */
- /* We couldn't find our memory total */
- if (0 == mem_cached) {
- /* We have no cached value either */
- *mem_out = 0;
- return -1;
- }
-
- *mem_out = mem_cached;
- return 0;
- /* LCOV_EXCL_STOP */
- }
-
-#if SIZE_MAX != UINT64_MAX
- if (m > SIZE_MAX) {
- /* I think this could happen if we're a 32-bit Tor running on a 64-bit
- * system: we could have more system memory than would fit in a
- * size_t. */
- m = SIZE_MAX;
- }
-#endif /* SIZE_MAX != UINT64_MAX */
-
- *mem_out = mem_cached = (size_t) m;
-
- return 0;
-}
-
-/** Emit the password prompt <b>prompt</b>, then read up to <b>buflen</b>
- * bytes of passphrase into <b>output</b>. Return the number of bytes in
- * the passphrase, excluding terminating NUL.
- */
-ssize_t
-tor_getpass(const char *prompt, char *output, size_t buflen)
-{
- tor_assert(buflen <= SSIZE_MAX);
- tor_assert(buflen >= 1);
-#if defined(HAVE_READPASSPHRASE)
- char *pwd = readpassphrase(prompt, output, buflen, RPP_ECHO_OFF);
- if (pwd == NULL)
- return -1;
- return strlen(pwd);
-#elif defined(_WIN32)
- int r = -1;
- while (*prompt) {
- _putch(*prompt++);
- }
-
- tor_assert(buflen <= INT_MAX);
- wchar_t *buf = tor_calloc(buflen, sizeof(wchar_t));
-
- wchar_t *ptr = buf, *lastch = buf + buflen - 1;
- while (ptr < lastch) {
- wint_t ch = _getwch();
- switch (ch) {
- case '\r':
- case '\n':
- case WEOF:
- goto done_reading;
- case 3:
- goto done; /* Can't actually read ctrl-c this way. */
- case '\b':
- if (ptr > buf)
- --ptr;
- continue;
- case 0:
- case 0xe0:
- ch = _getwch(); /* Ignore; this is a function or arrow key */
- break;
- default:
- *ptr++ = ch;
- break;
- }
- }
- done_reading:
- ;
-
-#ifndef WC_ERR_INVALID_CHARS
-#define WC_ERR_INVALID_CHARS 0x80
-#endif
-
- /* Now convert it to UTF-8 */
- r = WideCharToMultiByte(CP_UTF8,
- WC_NO_BEST_FIT_CHARS|WC_ERR_INVALID_CHARS,
- buf, (int)(ptr-buf),
- output, (int)(buflen-1),
- NULL, NULL);
- if (r <= 0) {
- r = -1;
- goto done;
- }
-
- tor_assert(r < (int)buflen);
-
- output[r] = 0;
-
- done:
- SecureZeroMemory(buf, sizeof(wchar_t)*buflen);
- tor_free(buf);
- return r;
-#else
-#error "No implementation for tor_getpass found!"
-#endif /* defined(HAVE_READPASSPHRASE) || ... */
-}
-
-/** Return the amount of free disk space we have permission to use, in
- * bytes. Return -1 if the amount of free space can't be determined. */
-int64_t
-tor_get_avail_disk_space(const char *path)
-{
-#ifdef HAVE_STATVFS
- struct statvfs st;
- int r;
- memset(&st, 0, sizeof(st));
-
- r = statvfs(path, &st);
- if (r < 0)
- return -1;
-
- int64_t result = st.f_bavail;
- if (st.f_frsize) {
- result *= st.f_frsize;
- } else if (st.f_bsize) {
- result *= st.f_bsize;
- } else {
- return -1;
- }
-
- return result;
-#elif defined(_WIN32)
- ULARGE_INTEGER freeBytesAvail;
- BOOL ok;
-
- ok = GetDiskFreeSpaceEx(path, &freeBytesAvail, NULL, NULL);
- if (!ok) {
- return -1;
- }
- return (int64_t)freeBytesAvail.QuadPart;
-#else
- (void)path;
- errno = ENOSYS;
- return -1;
-#endif /* defined(HAVE_STATVFS) || ... */
-}
-
diff --git a/src/common/compat.h b/src/common/compat.h
deleted file mode 100644
index c7e7f8d9ef..0000000000
--- a/src/common/compat.h
+++ /dev/null
@@ -1,757 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_COMPAT_H
-#define TOR_COMPAT_H
-
-#include "orconfig.h"
-#ifdef _WIN32
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#ifndef SIO_IDEAL_SEND_BACKLOG_QUERY
-#define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747b
-#endif
-#endif
-#include "torint.h"
-#include "testsupport.h"
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#include <stdarg.h>
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_NETINET6_IN6_H
-#include <netinet6/in6.h>
-#endif
-
-#include "compat_time.h"
-
-#if defined(__has_feature)
-# if __has_feature(address_sanitizer)
-/* Some of the fancy glibc strcmp() macros include references to memory that
- * clang rejects because it is off the end of a less-than-3. Clang hates this,
- * even though those references never actually happen. */
-# undef strcmp
-#endif /* __has_feature(address_sanitizer) */
-#endif /* defined(__has_feature) */
-
-#include <stdio.h>
-#include <errno.h>
-
-#ifndef NULL_REP_IS_ZERO_BYTES
-#error "It seems your platform does not represent NULL as zero. We can't cope."
-#endif
-
-#ifndef DOUBLE_0_REP_IS_ZERO_BYTES
-#error "It seems your platform does not represent 0.0 as zeros. We can't cope."
-#endif
-
-#if 'a'!=97 || 'z'!=122 || 'A'!=65 || ' '!=32
-#error "It seems that you encode characters in something other than ASCII."
-#endif
-
-/* ===== Compiler compatibility */
-
-/* GCC can check printf and scanf types on arbitrary functions. */
-#ifdef __GNUC__
-#define CHECK_PRINTF(formatIdx, firstArg) \
- __attribute__ ((format(printf, formatIdx, firstArg)))
-#else
-#define CHECK_PRINTF(formatIdx, firstArg)
-#endif /* defined(__GNUC__) */
-#ifdef __GNUC__
-#define CHECK_SCANF(formatIdx, firstArg) \
- __attribute__ ((format(scanf, formatIdx, firstArg)))
-#else
-#define CHECK_SCANF(formatIdx, firstArg)
-#endif /* defined(__GNUC__) */
-
-/* What GCC do we have? */
-#ifdef __GNUC__
-#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-#else
-#define GCC_VERSION 0
-#endif
-
-/* Temporarily enable and disable warnings. */
-#ifdef __GNUC__
-# define PRAGMA_STRINGIFY_(s) #s
-# define PRAGMA_JOIN_STRINGIFY_(a,b) PRAGMA_STRINGIFY_(a ## b)
-/* Support for macro-generated pragmas (c99) */
-# define PRAGMA_(x) _Pragma (#x)
-# ifdef __clang__
-# define PRAGMA_DIAGNOSTIC_(x) PRAGMA_(clang diagnostic x)
-# else
-# define PRAGMA_DIAGNOSTIC_(x) PRAGMA_(GCC diagnostic x)
-# endif
-# if defined(__clang__) || GCC_VERSION >= 406
-/* we have push/pop support */
-# define DISABLE_GCC_WARNING(warningopt) \
- PRAGMA_DIAGNOSTIC_(push) \
- PRAGMA_DIAGNOSTIC_(ignored PRAGMA_JOIN_STRINGIFY_(-W,warningopt))
-# define ENABLE_GCC_WARNING(warningopt) \
- PRAGMA_DIAGNOSTIC_(pop)
-#else /* !(defined(__clang__) || GCC_VERSION >= 406) */
-/* older version of gcc: no push/pop support. */
-# define DISABLE_GCC_WARNING(warningopt) \
- PRAGMA_DIAGNOSTIC_(ignored PRAGMA_JOIN_STRINGIFY_(-W,warningopt))
-# define ENABLE_GCC_WARNING(warningopt) \
- PRAGMA_DIAGNOSTIC_(warning PRAGMA_JOIN_STRINGIFY_(-W,warningopt))
-#endif /* defined(__clang__) || GCC_VERSION >= 406 */
-#else /* !(defined(__GNUC__)) */
-/* not gcc at all */
-# define DISABLE_GCC_WARNING(warning)
-# define ENABLE_GCC_WARNING(warning)
-#endif /* defined(__GNUC__) */
-
-/* inline is __inline on windows. */
-#ifdef _WIN32
-#define inline __inline
-#endif
-
-/* Try to get a reasonable __func__ substitute in place. */
-#if defined(_MSC_VER)
-
-#define __func__ __FUNCTION__
-
-#else
-/* For platforms where autoconf works, make sure __func__ is defined
- * sanely. */
-#ifndef HAVE_MACRO__func__
-#ifdef HAVE_MACRO__FUNCTION__
-#define __func__ __FUNCTION__
-#elif HAVE_MACRO__FUNC__
-#define __func__ __FUNC__
-#else
-#define __func__ "???"
-#endif /* defined(HAVE_MACRO__FUNCTION__) || ... */
-#endif /* !defined(HAVE_MACRO__func__) */
-#endif /* defined(_MSC_VER) */
-
-#define U64_TO_DBL(x) ((double) (x))
-#define DBL_TO_U64(x) ((uint64_t) (x))
-
-#ifdef ENUM_VALS_ARE_SIGNED
-#define ENUM_BF(t) unsigned
-#else
-/** Wrapper for having a bitfield of an enumerated type. Where possible, we
- * just use the enumerated type (so the compiler can help us and notice
- * problems), but if enumerated types are unsigned, we must use unsigned,
- * so that the loss of precision doesn't make large values negative. */
-#define ENUM_BF(t) t
-#endif /* defined(ENUM_VALS_ARE_SIGNED) */
-
-/* GCC has several useful attributes. */
-#if defined(__GNUC__) && __GNUC__ >= 3
-#define ATTR_NORETURN __attribute__((noreturn))
-#define ATTR_CONST __attribute__((const))
-#define ATTR_MALLOC __attribute__((malloc))
-#define ATTR_NORETURN __attribute__((noreturn))
-#define ATTR_WUR __attribute__((warn_unused_result))
-/* Alas, nonnull is not at present a good idea for us. We'd like to get
- * warnings when we pass NULL where we shouldn't (which nonnull does, albeit
- * spottily), but we don't want to tell the compiler to make optimizations
- * with the assumption that the argument can't be NULL (since this would make
- * many of our checks go away, and make our code less robust against
- * programming errors). Unfortunately, nonnull currently does both of these
- * things, and there's no good way to split them up.
- *
- * #define ATTR_NONNULL(x) __attribute__((nonnull x)) */
-#define ATTR_NONNULL(x)
-#define ATTR_UNUSED __attribute__ ((unused))
-
-/** Macro: Evaluates to <b>exp</b> and hints the compiler that the value
- * of <b>exp</b> will probably be true.
- *
- * In other words, "if (PREDICT_LIKELY(foo))" is the same as "if (foo)",
- * except that it tells the compiler that the branch will be taken most of the
- * time. This can generate slightly better code with some CPUs.
- */
-#define PREDICT_LIKELY(exp) __builtin_expect(!!(exp), 1)
-/** Macro: Evaluates to <b>exp</b> and hints the compiler that the value
- * of <b>exp</b> will probably be false.
- *
- * In other words, "if (PREDICT_UNLIKELY(foo))" is the same as "if (foo)",
- * except that it tells the compiler that the branch will usually not be
- * taken. This can generate slightly better code with some CPUs.
- */
-#define PREDICT_UNLIKELY(exp) __builtin_expect(!!(exp), 0)
-#else /* !(defined(__GNUC__) && __GNUC__ >= 3) */
-#define ATTR_NORETURN
-#define ATTR_CONST
-#define ATTR_MALLOC
-#define ATTR_NORETURN
-#define ATTR_NONNULL(x)
-#define ATTR_UNUSED
-#define ATTR_WUR
-#define PREDICT_LIKELY(exp) (exp)
-#define PREDICT_UNLIKELY(exp) (exp)
-#endif /* defined(__GNUC__) && __GNUC__ >= 3 */
-
-/** Expands to a syntactically valid empty statement. */
-#define STMT_NIL (void)0
-
-/** Expands to a syntactically valid empty statement, explicitly (void)ing its
- * argument. */
-#define STMT_VOID(a) while (0) { (void)(a); }
-
-#ifdef __GNUC__
-/** STMT_BEGIN and STMT_END are used to wrap blocks inside macros so that
- * the macro can be used as if it were a single C statement. */
-#define STMT_BEGIN (void) ({
-#define STMT_END })
-#elif defined(sun) || defined(__sun__)
-#define STMT_BEGIN if (1) {
-#define STMT_END } else STMT_NIL
-#else
-#define STMT_BEGIN do {
-#define STMT_END } while (0)
-#endif /* defined(__GNUC__) || ... */
-
-/* Some tools (like coccinelle) don't like to see operators as macro
- * arguments. */
-#define OP_LT <
-#define OP_GT >
-#define OP_GE >=
-#define OP_LE <=
-#define OP_EQ ==
-#define OP_NE !=
-
-/* ===== String compatibility */
-#ifdef _WIN32
-/* Windows names string functions differently from most other platforms. */
-#define strncasecmp _strnicmp
-#define strcasecmp _stricmp
-#endif
-
-#if defined __APPLE__
-/* On OSX 10.9 and later, the overlap-checking code for strlcat would
- * appear to have a severe bug that can sometimes cause aborts in Tor.
- * Instead, use the non-checking variants. This is sad.
- *
- * See https://trac.torproject.org/projects/tor/ticket/15205
- */
-#undef strlcat
-#undef strlcpy
-#endif /* defined __APPLE__ */
-
-#ifndef HAVE_STRLCAT
-size_t strlcat(char *dst, const char *src, size_t siz) ATTR_NONNULL((1,2));
-#endif
-#ifndef HAVE_STRLCPY
-size_t strlcpy(char *dst, const char *src, size_t siz) ATTR_NONNULL((1,2));
-#endif
-
-#ifdef _MSC_VER
-/** Casts the uint64_t value in <b>a</b> to the right type for an argument
- * to printf. */
-#define U64_PRINTF_ARG(a) (a)
-/** Casts the uint64_t* value in <b>a</b> to the right type for an argument
- * to scanf. */
-#define U64_SCANF_ARG(a) (a)
-/** Expands to a literal uint64_t-typed constant for the value <b>n</b>. */
-#define U64_LITERAL(n) (n ## ui64)
-#define I64_PRINTF_ARG(a) (a)
-#define I64_SCANF_ARG(a) (a)
-#define I64_LITERAL(n) (n ## i64)
-#else /* !(defined(_MSC_VER)) */
-#define U64_PRINTF_ARG(a) ((long long unsigned int)(a))
-#define U64_SCANF_ARG(a) ((long long unsigned int*)(a))
-#define U64_LITERAL(n) (n ## llu)
-#define I64_PRINTF_ARG(a) ((long long signed int)(a))
-#define I64_SCANF_ARG(a) ((long long signed int*)(a))
-#define I64_LITERAL(n) (n ## ll)
-#endif /* defined(_MSC_VER) */
-
-#if defined(__MINGW32__) || defined(__MINGW64__)
-#define MINGW_ANY
-#endif
-
-#if defined(_MSC_VER) || defined(MINGW_ANY)
-/** The formatting string used to put a uint64_t value in a printf() or
- * scanf() function. See also U64_PRINTF_ARG and U64_SCANF_ARG. */
-#define U64_FORMAT "%I64u"
-#define I64_FORMAT "%I64d"
-#else /* !(defined(_MSC_VER) || defined(MINGW_ANY)) */
-#define U64_FORMAT "%llu"
-#define I64_FORMAT "%lld"
-#endif /* defined(_MSC_VER) || defined(MINGW_ANY) */
-
-#if (SIZEOF_INTPTR_T == SIZEOF_INT)
-#define INTPTR_T_FORMAT "%d"
-#define INTPTR_PRINTF_ARG(x) ((int)(x))
-#elif (SIZEOF_INTPTR_T == SIZEOF_LONG)
-#define INTPTR_T_FORMAT "%ld"
-#define INTPTR_PRINTF_ARG(x) ((long)(x))
-#elif (SIZEOF_INTPTR_T == 8)
-#define INTPTR_T_FORMAT I64_FORMAT
-#define INTPTR_PRINTF_ARG(x) I64_PRINTF_ARG(x)
-#else
-#error Unknown: SIZEOF_INTPTR_T
-#endif /* (SIZEOF_INTPTR_T == SIZEOF_INT) || ... */
-
-/** Represents an mmaped file. Allocated via tor_mmap_file; freed with
- * tor_munmap_file. */
-typedef struct tor_mmap_t {
- const char *data; /**< Mapping of the file's contents. */
- size_t size; /**< Size of the file. */
-
- /* None of the fields below should be accessed from outside compat.c */
-#ifdef HAVE_MMAP
- size_t mapping_size; /**< Size of the actual mapping. (This is this file
- * size, rounded up to the nearest page.) */
-#elif defined _WIN32
- HANDLE mmap_handle;
-#endif /* defined(HAVE_MMAP) || ... */
-
-} tor_mmap_t;
-
-tor_mmap_t *tor_mmap_file(const char *filename) ATTR_NONNULL((1));
-int tor_munmap_file(tor_mmap_t *handle) ATTR_NONNULL((1));
-
-int tor_snprintf(char *str, size_t size, const char *format, ...)
- CHECK_PRINTF(3,4) ATTR_NONNULL((1,3));
-int tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
- CHECK_PRINTF(3,0) ATTR_NONNULL((1,3));
-
-int tor_asprintf(char **strp, const char *fmt, ...)
- CHECK_PRINTF(2,3);
-int tor_vasprintf(char **strp, const char *fmt, va_list args)
- CHECK_PRINTF(2,0);
-
-const void *tor_memmem(const void *haystack, size_t hlen, const void *needle,
- size_t nlen) ATTR_NONNULL((1,3));
-static const void *tor_memstr(const void *haystack, size_t hlen,
- const char *needle) ATTR_NONNULL((1,3));
-static inline const void *
-tor_memstr(const void *haystack, size_t hlen, const char *needle)
-{
- return tor_memmem(haystack, hlen, needle, strlen(needle));
-}
-
-/* Much of the time when we're checking ctypes, we're doing spec compliance,
- * which all assumes we're doing ASCII. */
-#define DECLARE_CTYPE_FN(name) \
- static int TOR_##name(char c); \
- extern const uint32_t TOR_##name##_TABLE[]; \
- static inline int TOR_##name(char c) { \
- uint8_t u = c; \
- return !!(TOR_##name##_TABLE[(u >> 5) & 7] & (1u << (u & 31))); \
- }
-DECLARE_CTYPE_FN(ISALPHA)
-DECLARE_CTYPE_FN(ISALNUM)
-DECLARE_CTYPE_FN(ISSPACE)
-DECLARE_CTYPE_FN(ISDIGIT)
-DECLARE_CTYPE_FN(ISXDIGIT)
-DECLARE_CTYPE_FN(ISPRINT)
-DECLARE_CTYPE_FN(ISLOWER)
-DECLARE_CTYPE_FN(ISUPPER)
-extern const uint8_t TOR_TOUPPER_TABLE[];
-extern const uint8_t TOR_TOLOWER_TABLE[];
-#define TOR_TOLOWER(c) (TOR_TOLOWER_TABLE[(uint8_t)c])
-#define TOR_TOUPPER(c) (TOR_TOUPPER_TABLE[(uint8_t)c])
-
-char *tor_strtok_r_impl(char *str, const char *sep, char **lasts);
-#ifdef HAVE_STRTOK_R
-#define tor_strtok_r(str, sep, lasts) strtok_r(str, sep, lasts)
-#else
-#define tor_strtok_r(str, sep, lasts) tor_strtok_r_impl(str, sep, lasts)
-#endif
-
-#ifdef _WIN32
-#define SHORT_FILE__ (tor_fix_source_file(__FILE__))
-const char *tor_fix_source_file(const char *fname);
-#else
-#define SHORT_FILE__ (__FILE__)
-#define tor_fix_source_file(s) (s)
-#endif /* defined(_WIN32) */
-
-/* ===== Time compatibility */
-
-struct tm *tor_localtime_r(const time_t *timep, struct tm *result);
-struct tm *tor_gmtime_r(const time_t *timep, struct tm *result);
-
-#ifndef timeradd
-/** Replacement for timeradd on platforms that do not have it: sets tvout to
- * the sum of tv1 and tv2. */
-#define timeradd(tv1,tv2,tvout) \
- do { \
- (tvout)->tv_sec = (tv1)->tv_sec + (tv2)->tv_sec; \
- (tvout)->tv_usec = (tv1)->tv_usec + (tv2)->tv_usec; \
- if ((tvout)->tv_usec >= 1000000) { \
- (tvout)->tv_usec -= 1000000; \
- (tvout)->tv_sec++; \
- } \
- } while (0)
-#endif /* !defined(timeradd) */
-
-#ifndef timersub
-/** Replacement for timersub on platforms that do not have it: sets tvout to
- * tv1 minus tv2. */
-#define timersub(tv1,tv2,tvout) \
- do { \
- (tvout)->tv_sec = (tv1)->tv_sec - (tv2)->tv_sec; \
- (tvout)->tv_usec = (tv1)->tv_usec - (tv2)->tv_usec; \
- if ((tvout)->tv_usec < 0) { \
- (tvout)->tv_usec += 1000000; \
- (tvout)->tv_sec--; \
- } \
- } while (0)
-#endif /* !defined(timersub) */
-
-#ifndef timercmp
-/** Replacement for timercmp on platforms that do not have it: returns true
- * iff the relational operator "op" makes the expression tv1 op tv2 true.
- *
- * Note that while this definition should work for all boolean operators, some
- * platforms' native timercmp definitions do not support >=, <=, or ==. So
- * don't use those.
- */
-#define timercmp(tv1,tv2,op) \
- (((tv1)->tv_sec == (tv2)->tv_sec) ? \
- ((tv1)->tv_usec op (tv2)->tv_usec) : \
- ((tv1)->tv_sec op (tv2)->tv_sec))
-#endif /* !defined(timercmp) */
-
-/* ===== File compatibility */
-int tor_open_cloexec(const char *path, int flags, unsigned mode);
-FILE *tor_fopen_cloexec(const char *path, const char *mode);
-int tor_rename(const char *path_old, const char *path_new);
-
-int replace_file(const char *from, const char *to);
-int touch_file(const char *fname);
-
-typedef struct tor_lockfile_t tor_lockfile_t;
-tor_lockfile_t *tor_lockfile_lock(const char *filename, int blocking,
- int *locked_out);
-void tor_lockfile_unlock(tor_lockfile_t *lockfile);
-
-off_t tor_fd_getpos(int fd);
-int tor_fd_setpos(int fd, off_t pos);
-int tor_fd_seekend(int fd);
-int tor_ftruncate(int fd);
-
-int64_t tor_get_avail_disk_space(const char *path);
-
-#ifdef _WIN32
-#define PATH_SEPARATOR "\\"
-#else
-#define PATH_SEPARATOR "/"
-#endif
-
-/* ===== Net compatibility */
-
-#if (SIZEOF_SOCKLEN_T == 0)
-typedef int socklen_t;
-#endif
-
-#ifdef _WIN32
-/* XXX Actually, this should arguably be SOCKET; we use intptr_t here so that
- * any inadvertent checks for the socket being <= 0 or > 0 will probably
- * still work. */
-#define tor_socket_t intptr_t
-#define TOR_SOCKET_T_FORMAT INTPTR_T_FORMAT
-#define SOCKET_OK(s) ((SOCKET)(s) != INVALID_SOCKET)
-#define TOR_INVALID_SOCKET INVALID_SOCKET
-#else /* !(defined(_WIN32)) */
-/** Type used for a network socket. */
-#define tor_socket_t int
-#define TOR_SOCKET_T_FORMAT "%d"
-/** Macro: true iff 's' is a possible value for a valid initialized socket. */
-#define SOCKET_OK(s) ((s) >= 0)
-/** Error/uninitialized value for a tor_socket_t. */
-#define TOR_INVALID_SOCKET (-1)
-#endif /* defined(_WIN32) */
-
-int tor_close_socket_simple(tor_socket_t s);
-MOCK_DECL(int, tor_close_socket, (tor_socket_t s));
-void tor_take_socket_ownership(tor_socket_t s);
-tor_socket_t tor_open_socket_with_extensions(
- int domain, int type, int protocol,
- int cloexec, int nonblock);
-MOCK_DECL(tor_socket_t,
-tor_open_socket,(int domain, int type, int protocol));
-tor_socket_t tor_open_socket_nonblocking(int domain, int type, int protocol);
-tor_socket_t tor_accept_socket(tor_socket_t sockfd, struct sockaddr *addr,
- socklen_t *len);
-tor_socket_t tor_accept_socket_nonblocking(tor_socket_t sockfd,
- struct sockaddr *addr,
- socklen_t *len);
-tor_socket_t tor_accept_socket_with_extensions(tor_socket_t sockfd,
- struct sockaddr *addr,
- socklen_t *len,
- int cloexec, int nonblock);
-MOCK_DECL(tor_socket_t,
-tor_connect_socket,(tor_socket_t socket,const struct sockaddr *address,
- socklen_t address_len));
-int get_n_open_sockets(void);
-
-MOCK_DECL(int,
-tor_getsockname,(tor_socket_t socket, struct sockaddr *address,
- socklen_t *address_len));
-struct tor_addr_t;
-int tor_addr_from_getsockname(struct tor_addr_t *addr_out, tor_socket_t sock);
-
-#define tor_socket_send(s, buf, len, flags) send(s, buf, len, flags)
-#define tor_socket_recv(s, buf, len, flags) recv(s, buf, len, flags)
-
-/** Implementation of struct in6_addr for platforms that do not have it.
- * Generally, these platforms are ones without IPv6 support, but we want to
- * have a working in6_addr there anyway, so we can use it to parse IPv6
- * addresses. */
-#if !defined(HAVE_STRUCT_IN6_ADDR)
-struct in6_addr
-{
- union {
- uint8_t u6_addr8[16];
- uint16_t u6_addr16[8];
- uint32_t u6_addr32[4];
- } in6_u;
-#define s6_addr in6_u.u6_addr8
-#define s6_addr16 in6_u.u6_addr16
-#define s6_addr32 in6_u.u6_addr32
-};
-#endif /* !defined(HAVE_STRUCT_IN6_ADDR) */
-
-/** @{ */
-/** Many BSD variants seem not to define these. */
-#if defined(__APPLE__) || defined(__darwin__) || \
- defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
-#ifndef s6_addr16
-#define s6_addr16 __u6_addr.__u6_addr16
-#endif
-#ifndef s6_addr32
-#define s6_addr32 __u6_addr.__u6_addr32
-#endif
-#endif /* defined(__APPLE__) || defined(__darwin__) || ... */
-/** @} */
-
-#ifndef HAVE_SA_FAMILY_T
-typedef uint16_t sa_family_t;
-#endif
-
-/** @{ */
-/** Apparently, MS and Solaris don't define s6_addr16 or s6_addr32; these
- * macros get you a pointer to s6_addr32 or local equivalent. */
-#ifdef HAVE_STRUCT_IN6_ADDR_S6_ADDR32
-#define S6_ADDR32(x) ((uint32_t*)(x).s6_addr32)
-#else
-#define S6_ADDR32(x) ((uint32_t*)((char*)&(x).s6_addr))
-#endif
-#ifdef HAVE_STRUCT_IN6_ADDR_S6_ADDR16
-#define S6_ADDR16(x) ((uint16_t*)(x).s6_addr16)
-#else
-#define S6_ADDR16(x) ((uint16_t*)((char*)&(x).s6_addr))
-#endif
-/** @} */
-
-/** Implementation of struct sockaddr_in6 on platforms that do not have
- * it. See notes on struct in6_addr. */
-#if !defined(HAVE_STRUCT_SOCKADDR_IN6)
-struct sockaddr_in6 {
- sa_family_t sin6_family;
- uint16_t sin6_port;
- // uint32_t sin6_flowinfo;
- struct in6_addr sin6_addr;
- // uint32_t sin6_scope_id;
-};
-#endif /* !defined(HAVE_STRUCT_SOCKADDR_IN6) */
-
-MOCK_DECL(int,tor_gethostname,(char *name, size_t namelen));
-int tor_inet_aton(const char *cp, struct in_addr *addr) ATTR_NONNULL((1,2));
-const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len);
-int tor_inet_pton(int af, const char *src, void *dst);
-MOCK_DECL(int,tor_lookup_hostname,(const char *name, uint32_t *addr));
-int set_socket_nonblocking(tor_socket_t socket);
-int tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]);
-int network_init(void);
-
-/* For stupid historical reasons, windows sockets have an independent
- * set of errnos, and an independent way to get them. Also, you can't
- * always believe WSAEWOULDBLOCK. Use the macros below to compare
- * errnos against expected values, and use tor_socket_errno to find
- * the actual errno after a socket operation fails.
- */
-#if defined(_WIN32)
-/** Expands to WSA<b>e</b> on Windows, and to <b>e</b> elsewhere. */
-#define SOCK_ERRNO(e) WSA##e
-/** Return true if e is EAGAIN or the local equivalent. */
-#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN || (e) == WSAEWOULDBLOCK)
-/** Return true if e is EINPROGRESS or the local equivalent. */
-#define ERRNO_IS_EINPROGRESS(e) ((e) == WSAEINPROGRESS)
-/** Return true if e is EINPROGRESS or the local equivalent as returned by
- * a call to connect(). */
-#define ERRNO_IS_CONN_EINPROGRESS(e) \
- ((e) == WSAEINPROGRESS || (e)== WSAEINVAL || (e) == WSAEWOULDBLOCK)
-/** Return true if e is EAGAIN or another error indicating that a call to
- * accept() has no pending connections to return. */
-#define ERRNO_IS_ACCEPT_EAGAIN(e) ERRNO_IS_EAGAIN(e)
-/** Return true if e is EMFILE or another error indicating that a call to
- * accept() has failed because we're out of fds or something. */
-#define ERRNO_IS_RESOURCE_LIMIT(e) \
- ((e) == WSAEMFILE || (e) == WSAENOBUFS)
-/** Return true if e is EADDRINUSE or the local equivalent. */
-#define ERRNO_IS_EADDRINUSE(e) ((e) == WSAEADDRINUSE)
-/** Return true if e is EINTR or the local equivalent */
-#define ERRNO_IS_EINTR(e) ((e) == WSAEINTR || 0)
-int tor_socket_errno(tor_socket_t sock);
-const char *tor_socket_strerror(int e);
-#else /* !(defined(_WIN32)) */
-#define SOCK_ERRNO(e) e
-#if EAGAIN == EWOULDBLOCK
-/* || 0 is for -Wparentheses-equality (-Wall?) appeasement under clang */
-#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN || 0)
-#else
-#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN || (e) == EWOULDBLOCK)
-#endif /* EAGAIN == EWOULDBLOCK */
-#define ERRNO_IS_EINTR(e) ((e) == EINTR || 0)
-#define ERRNO_IS_EINPROGRESS(e) ((e) == EINPROGRESS || 0)
-#define ERRNO_IS_CONN_EINPROGRESS(e) ((e) == EINPROGRESS || 0)
-#define ERRNO_IS_ACCEPT_EAGAIN(e) \
- (ERRNO_IS_EAGAIN(e) || (e) == ECONNABORTED)
-#define ERRNO_IS_RESOURCE_LIMIT(e) \
- ((e) == EMFILE || (e) == ENFILE || (e) == ENOBUFS || (e) == ENOMEM)
-#define ERRNO_IS_EADDRINUSE(e) (((e) == EADDRINUSE) || 0)
-#define tor_socket_errno(sock) (errno)
-#define tor_socket_strerror(e) strerror(e)
-#endif /* defined(_WIN32) */
-
-/** Specified SOCKS5 status codes. */
-typedef enum {
- SOCKS5_SUCCEEDED = 0x00,
- SOCKS5_GENERAL_ERROR = 0x01,
- SOCKS5_NOT_ALLOWED = 0x02,
- SOCKS5_NET_UNREACHABLE = 0x03,
- SOCKS5_HOST_UNREACHABLE = 0x04,
- SOCKS5_CONNECTION_REFUSED = 0x05,
- SOCKS5_TTL_EXPIRED = 0x06,
- SOCKS5_COMMAND_NOT_SUPPORTED = 0x07,
- SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED = 0x08,
-} socks5_reply_status_t;
-
-/* ===== OS compatibility */
-MOCK_DECL(const char *, get_uname, (void));
-
-uint16_t get_uint16(const void *cp) ATTR_NONNULL((1));
-uint32_t get_uint32(const void *cp) ATTR_NONNULL((1));
-uint64_t get_uint64(const void *cp) ATTR_NONNULL((1));
-void set_uint16(void *cp, uint16_t v) ATTR_NONNULL((1));
-void set_uint32(void *cp, uint32_t v) ATTR_NONNULL((1));
-void set_uint64(void *cp, uint64_t v) ATTR_NONNULL((1));
-
-/* These uint8 variants are defined to make the code more uniform. */
-#define get_uint8(cp) (*(const uint8_t*)(cp))
-static void set_uint8(void *cp, uint8_t v);
-static inline void
-set_uint8(void *cp, uint8_t v)
-{
- *(uint8_t*)cp = v;
-}
-
-#if !defined(HAVE_RLIM_T)
-typedef unsigned long rlim_t;
-#endif
-int get_max_sockets(void);
-int set_max_file_descriptors(rlim_t limit, int *max);
-int tor_disable_debugger_attach(void);
-
-#if defined(HAVE_SYS_CAPABILITY_H) && defined(HAVE_CAP_SET_PROC)
-#define HAVE_LINUX_CAPABILITIES
-#endif
-
-int have_capability_support(void);
-
-/** Flag for switch_id; see switch_id() for documentation */
-#define SWITCH_ID_KEEP_BINDLOW (1<<0)
-/** Flag for switch_id; see switch_id() for documentation */
-#define SWITCH_ID_WARN_IF_NO_CAPS (1<<1)
-int switch_id(const char *user, unsigned flags);
-#ifdef HAVE_PWD_H
-char *get_user_homedir(const char *username);
-#endif
-
-#ifndef _WIN32
-const struct passwd *tor_getpwnam(const char *username);
-const struct passwd *tor_getpwuid(uid_t uid);
-#endif
-
-int get_parent_directory(char *fname);
-char *make_path_absolute(char *fname);
-
-char **get_environment(void);
-
-MOCK_DECL(int, get_total_system_memory, (size_t *mem_out));
-
-int compute_num_cpus(void);
-
-int tor_mlockall(void);
-
-/** Macros for MIN/MAX. Never use these when the arguments could have
- * side-effects.
- * {With GCC extensions we could probably define a safer MIN/MAX. But
- * depending on that safety would be dangerous, since not every platform
- * has it.}
- **/
-#ifndef MAX
-#define MAX(a,b) ( ((a)<(b)) ? (b) : (a) )
-#endif
-#ifndef MIN
-#define MIN(a,b) ( ((a)>(b)) ? (b) : (a) )
-#endif
-
-/* Platform-specific helpers. */
-#ifdef _WIN32
-char *format_win32_error(DWORD err);
-#endif
-
-/*for some reason my compiler doesn't have these version flags defined
- a nice homework assignment for someone one day is to define the rest*/
-//these are the values as given on MSDN
-#ifdef _WIN32
-
-#ifndef VER_SUITE_EMBEDDEDNT
-#define VER_SUITE_EMBEDDEDNT 0x00000040
-#endif
-
-#ifndef VER_SUITE_SINGLEUSERTS
-#define VER_SUITE_SINGLEUSERTS 0x00000100
-#endif
-
-#endif /* defined(_WIN32) */
-
-#ifdef COMPAT_PRIVATE
-#if !defined(HAVE_SOCKETPAIR) || defined(_WIN32) || defined(TOR_UNIT_TESTS)
-#define NEED_ERSATZ_SOCKETPAIR
-STATIC int tor_ersatz_socketpair(int family, int type, int protocol,
- tor_socket_t fd[2]);
-#endif
-#endif /* defined(COMPAT_PRIVATE) */
-
-ssize_t tor_getpass(const char *prompt, char *output, size_t buflen);
-
-/* This needs some of the declarations above so we include it here. */
-#include "compat_threads.h"
-
-#endif /* !defined(TOR_COMPAT_H) */
-
diff --git a/src/common/container.c b/src/common/container.c
deleted file mode 100644
index 5386e6458b..0000000000
--- a/src/common/container.c
+++ /dev/null
@@ -1,1542 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file container.c
- * \brief Implements a smartlist (a resizable array) along
- * with helper functions to use smartlists. Also includes
- * hash table implementations of a string-to-void* map, and of
- * a digest-to-void* map.
- **/
-
-#include "compat.h"
-#include "util.h"
-#include "torlog.h"
-#include "container.h"
-#include "crypto_digest.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include "ht.h"
-
-/** All newly allocated smartlists have this capacity. */
-#define SMARTLIST_DEFAULT_CAPACITY 16
-
-/** Allocate and return an empty smartlist.
- */
-MOCK_IMPL(smartlist_t *,
-smartlist_new,(void))
-{
- smartlist_t *sl = tor_malloc(sizeof(smartlist_t));
- sl->num_used = 0;
- sl->capacity = SMARTLIST_DEFAULT_CAPACITY;
- sl->list = tor_calloc(sizeof(void *), sl->capacity);
- return sl;
-}
-
-/** Deallocate a smartlist. Does not release storage associated with the
- * list's elements.
- */
-MOCK_IMPL(void,
-smartlist_free_,(smartlist_t *sl))
-{
- if (!sl)
- return;
- tor_free(sl->list);
- tor_free(sl);
-}
-
-/** Remove all elements from the list.
- */
-void
-smartlist_clear(smartlist_t *sl)
-{
- memset(sl->list, 0, sizeof(void *) * sl->num_used);
- sl->num_used = 0;
-}
-
-#if SIZE_MAX < INT_MAX
-#error "We don't support systems where size_t is smaller than int."
-#endif
-
-/** Make sure that <b>sl</b> can hold at least <b>size</b> entries. */
-static inline void
-smartlist_ensure_capacity(smartlist_t *sl, size_t size)
-{
- /* Set MAX_CAPACITY to MIN(INT_MAX, SIZE_MAX / sizeof(void*)) */
-#if (SIZE_MAX/SIZEOF_VOID_P) > INT_MAX
-#define MAX_CAPACITY (INT_MAX)
-#else
-#define MAX_CAPACITY (int)((SIZE_MAX / (sizeof(void*))))
-#endif
-
- tor_assert(size <= MAX_CAPACITY);
-
- if (size > (size_t) sl->capacity) {
- size_t higher = (size_t) sl->capacity;
- if (PREDICT_UNLIKELY(size > MAX_CAPACITY/2)) {
- higher = MAX_CAPACITY;
- } else {
- while (size > higher)
- higher *= 2;
- }
- sl->list = tor_reallocarray(sl->list, sizeof(void *),
- ((size_t)higher));
- memset(sl->list + sl->capacity, 0,
- sizeof(void *) * (higher - sl->capacity));
- sl->capacity = (int) higher;
- }
-#undef ASSERT_CAPACITY
-#undef MAX_CAPACITY
-}
-
-/** Append element to the end of the list. */
-void
-smartlist_add(smartlist_t *sl, void *element)
-{
- smartlist_ensure_capacity(sl, ((size_t) sl->num_used)+1);
- sl->list[sl->num_used++] = element;
-}
-
-/** Append each element from S2 to the end of S1. */
-void
-smartlist_add_all(smartlist_t *s1, const smartlist_t *s2)
-{
- size_t new_size = (size_t)s1->num_used + (size_t)s2->num_used;
- tor_assert(new_size >= (size_t) s1->num_used); /* check for overflow. */
- smartlist_ensure_capacity(s1, new_size);
- memcpy(s1->list + s1->num_used, s2->list, s2->num_used*sizeof(void*));
- tor_assert(new_size <= INT_MAX); /* redundant. */
- s1->num_used = (int) new_size;
-}
-
-/** 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)
-{
- int i;
- if (element == NULL)
- return;
- 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;
- }
-}
-
-/** As <b>smartlist_remove</b>, but do not change the order of
- * any elements not removed */
-void
-smartlist_remove_keeporder(smartlist_t *sl, const void *element)
-{
- int i, j, num_used_orig = sl->num_used;
- if (element == NULL)
- return;
-
- for (i=j=0; j < num_used_orig; ++j) {
- if (sl->list[j] == element) {
- --sl->num_used;
- } else {
- sl->list[i++] = sl->list[j];
- }
- }
-}
-
-/** If <b>sl</b> is nonempty, remove and return the final element. Otherwise,
- * return NULL. */
-void *
-smartlist_pop_last(smartlist_t *sl)
-{
- tor_assert(sl);
- if (sl->num_used) {
- void *tmp = sl->list[--sl->num_used];
- sl->list[sl->num_used] = NULL;
- return tmp;
- } else
- return NULL;
-}
-
-/** Reverse the order of the items in <b>sl</b>. */
-void
-smartlist_reverse(smartlist_t *sl)
-{
- int i, j;
- void *tmp;
- tor_assert(sl);
- for (i = 0, j = sl->num_used-1; i < j; ++i, --j) {
- tmp = sl->list[i];
- sl->list[i] = sl->list[j];
- sl->list[j] = tmp;
- }
-}
-
-/** If there are any strings in sl equal to element, remove and free them.
- * Does not preserve order. */
-void
-smartlist_string_remove(smartlist_t *sl, const char *element)
-{
- int i;
- tor_assert(sl);
- tor_assert(element);
- for (i = 0; i < sl->num_used; ++i) {
- if (!strcmp(element, sl->list[i])) {
- tor_free(sl->list[i]);
- 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;
- }
- }
-}
-
-/** Return true iff some element E of sl has E==element.
- */
-int
-smartlist_contains(const smartlist_t *sl, const void *element)
-{
- int i;
- for (i=0; i < sl->num_used; i++)
- if (sl->list[i] == element)
- return 1;
- return 0;
-}
-
-/** Return true iff <b>sl</b> has some element E such that
- * !strcmp(E,<b>element</b>)
- */
-int
-smartlist_contains_string(const smartlist_t *sl, const char *element)
-{
- int i;
- if (!sl) return 0;
- for (i=0; i < sl->num_used; i++)
- if (strcmp((const char*)sl->list[i],element)==0)
- return 1;
- return 0;
-}
-
-/** If <b>element</b> is equal to an element of <b>sl</b>, return that
- * element's index. Otherwise, return -1. */
-int
-smartlist_string_pos(const smartlist_t *sl, const char *element)
-{
- int i;
- if (!sl) return -1;
- for (i=0; i < sl->num_used; i++)
- if (strcmp((const char*)sl->list[i],element)==0)
- return i;
- return -1;
-}
-
-/** If <b>element</b> is the same pointer as an element of <b>sl</b>, return
- * that element's index. Otherwise, return -1. */
-int
-smartlist_pos(const smartlist_t *sl, const void *element)
-{
- int i;
- if (!sl) return -1;
- for (i=0; i < sl->num_used; i++)
- if (element == sl->list[i])
- return i;
- return -1;
-}
-
-/** Return true iff <b>sl</b> has some element E such that
- * !strcasecmp(E,<b>element</b>)
- */
-int
-smartlist_contains_string_case(const smartlist_t *sl, const char *element)
-{
- int i;
- if (!sl) return 0;
- for (i=0; i < sl->num_used; i++)
- if (strcasecmp((const char*)sl->list[i],element)==0)
- return 1;
- return 0;
-}
-
-/** Return true iff <b>sl</b> has some element E such that E is equal
- * to the decimal encoding of <b>num</b>.
- */
-int
-smartlist_contains_int_as_string(const smartlist_t *sl, int num)
-{
- char buf[32]; /* long enough for 64-bit int, and then some. */
- tor_snprintf(buf,sizeof(buf),"%d", num);
- return smartlist_contains_string(sl, buf);
-}
-
-/** Return true iff the two lists contain the same strings in the same
- * order, or if they are both NULL. */
-int
-smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2)
-{
- if (sl1 == NULL)
- return sl2 == NULL;
- if (sl2 == NULL)
- return 0;
- if (smartlist_len(sl1) != smartlist_len(sl2))
- return 0;
- SMARTLIST_FOREACH(sl1, const char *, cp1, {
- const char *cp2 = smartlist_get(sl2, cp1_sl_idx);
- if (strcmp(cp1, cp2))
- return 0;
- });
- return 1;
-}
-
-/** Return true iff the two lists contain the same int pointer values in
- * the same order, or if they are both NULL. */
-int
-smartlist_ints_eq(const smartlist_t *sl1, const smartlist_t *sl2)
-{
- if (sl1 == NULL)
- return sl2 == NULL;
- if (sl2 == NULL)
- return 0;
- if (smartlist_len(sl1) != smartlist_len(sl2))
- return 0;
- SMARTLIST_FOREACH(sl1, int *, cp1, {
- int *cp2 = smartlist_get(sl2, cp1_sl_idx);
- if (*cp1 != *cp2)
- return 0;
- });
- return 1;
-}
-
-/** Return true iff <b>sl</b> has some element E such that
- * tor_memeq(E,<b>element</b>,DIGEST_LEN)
- */
-int
-smartlist_contains_digest(const smartlist_t *sl, const char *element)
-{
- int i;
- if (!sl) return 0;
- for (i=0; i < sl->num_used; i++)
- if (tor_memeq((const char*)sl->list[i],element,DIGEST_LEN))
- return 1;
- return 0;
-}
-
-/** Return true iff some element E of sl2 has smartlist_contains(sl1,E).
- */
-int
-smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2)
-{
- int i;
- for (i=0; i < sl2->num_used; i++)
- if (smartlist_contains(sl1, sl2->list[i]))
- return 1;
- return 0;
-}
-
-/** Remove every element E of sl1 such that !smartlist_contains(sl2,E).
- * Does not preserve the order of sl1.
- */
-void
-smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2)
-{
- int i;
- for (i=0; i < sl1->num_used; i++)
- if (!smartlist_contains(sl2, sl1->list[i])) {
- sl1->list[i] = sl1->list[--sl1->num_used]; /* swap with the end */
- i--; /* so we process the new i'th element */
- sl1->list[sl1->num_used] = NULL;
- }
-}
-
-/** Remove every element E of sl1 such that smartlist_contains(sl2,E).
- * Does not preserve the order of sl1.
- */
-void
-smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2)
-{
- int i;
- for (i=0; i < sl2->num_used; i++)
- smartlist_remove(sl1, sl2->list[i]);
-}
-
-/** Remove the <b>idx</b>th element of sl; if idx is not the last
- * element, swap the last element of sl into the <b>idx</b>th space.
- */
-void
-smartlist_del(smartlist_t *sl, int idx)
-{
- tor_assert(sl);
- tor_assert(idx>=0);
- tor_assert(idx < sl->num_used);
- sl->list[idx] = sl->list[--sl->num_used];
- sl->list[sl->num_used] = NULL;
-}
-
-/** Remove the <b>idx</b>th element of sl; if idx is not the last element,
- * moving all subsequent elements back one space. Return the old value
- * of the <b>idx</b>th element.
- */
-void
-smartlist_del_keeporder(smartlist_t *sl, int idx)
-{
- tor_assert(sl);
- tor_assert(idx>=0);
- tor_assert(idx < sl->num_used);
- --sl->num_used;
- if (idx < sl->num_used)
- memmove(sl->list+idx, sl->list+idx+1, sizeof(void*)*(sl->num_used-idx));
- sl->list[sl->num_used] = NULL;
-}
-
-/** Insert the value <b>val</b> as the new <b>idx</b>th element of
- * <b>sl</b>, moving all items previously at <b>idx</b> or later
- * forward one space.
- */
-void
-smartlist_insert(smartlist_t *sl, int idx, void *val)
-{
- tor_assert(sl);
- tor_assert(idx>=0);
- tor_assert(idx <= sl->num_used);
- if (idx == sl->num_used) {
- smartlist_add(sl, val);
- } else {
- smartlist_ensure_capacity(sl, ((size_t) sl->num_used)+1);
- /* Move other elements away */
- if (idx < sl->num_used)
- memmove(sl->list + idx + 1, sl->list + idx,
- sizeof(void*)*(sl->num_used-idx));
- sl->num_used++;
- sl->list[idx] = val;
- }
-}
-
-/**
- * Split a string <b>str</b> along all occurrences of <b>sep</b>,
- * appending the (newly allocated) split strings, in order, to
- * <b>sl</b>. Return the number of strings added to <b>sl</b>.
- *
- * If <b>flags</b>&amp;SPLIT_SKIP_SPACE is true, remove initial and
- * trailing space from each entry.
- * If <b>flags</b>&amp;SPLIT_IGNORE_BLANK is true, remove any entries
- * of length 0.
- * If <b>flags</b>&amp;SPLIT_STRIP_SPACE is true, strip spaces from each
- * split string.
- *
- * If <b>max</b>\>0, divide the string into no more than <b>max</b> pieces. If
- * <b>sep</b> is NULL, split on any sequence of horizontal space.
- */
-int
-smartlist_split_string(smartlist_t *sl, const char *str, const char *sep,
- int flags, int max)
-{
- const char *cp, *end, *next;
- int n = 0;
-
- tor_assert(sl);
- tor_assert(str);
-
- cp = str;
- while (1) {
- if (flags&SPLIT_SKIP_SPACE) {
- while (TOR_ISSPACE(*cp)) ++cp;
- }
-
- if (max>0 && n == max-1) {
- end = strchr(cp,'\0');
- } else if (sep) {
- end = strstr(cp,sep);
- if (!end)
- end = strchr(cp,'\0');
- } else {
- for (end = cp; *end && *end != '\t' && *end != ' '; ++end)
- ;
- }
-
- tor_assert(end);
-
- if (!*end) {
- next = NULL;
- } else if (sep) {
- next = end+strlen(sep);
- } else {
- next = end+1;
- while (*next == '\t' || *next == ' ')
- ++next;
- }
-
- if (flags&SPLIT_SKIP_SPACE) {
- while (end > cp && TOR_ISSPACE(*(end-1)))
- --end;
- }
- if (end != cp || !(flags&SPLIT_IGNORE_BLANK)) {
- char *string = tor_strndup(cp, end-cp);
- if (flags&SPLIT_STRIP_SPACE)
- tor_strstrip(string, " ");
- smartlist_add(sl, string);
- ++n;
- }
- if (!next)
- break;
- cp = next;
- }
-
- return n;
-}
-
-/** Allocate and return a new string containing the concatenation of
- * the elements of <b>sl</b>, in order, separated by <b>join</b>. If
- * <b>terminate</b> is true, also terminate the string with <b>join</b>.
- * If <b>len_out</b> is not NULL, set <b>len_out</b> to the length of
- * the returned string. Requires that every element of <b>sl</b> is
- * NUL-terminated string.
- */
-char *
-smartlist_join_strings(smartlist_t *sl, const char *join,
- int terminate, size_t *len_out)
-{
- return smartlist_join_strings2(sl,join,strlen(join),terminate,len_out);
-}
-
-/** As smartlist_join_strings, but instead of separating/terminated with a
- * NUL-terminated string <b>join</b>, uses the <b>join_len</b>-byte sequence
- * at <b>join</b>. (Useful for generating a sequence of NUL-terminated
- * strings.)
- */
-char *
-smartlist_join_strings2(smartlist_t *sl, const char *join,
- size_t join_len, int terminate, size_t *len_out)
-{
- int i;
- size_t n = 0;
- char *r = NULL, *dst, *src;
-
- tor_assert(sl);
- tor_assert(join);
-
- if (terminate)
- n = join_len;
-
- for (i = 0; i < sl->num_used; ++i) {
- n += strlen(sl->list[i]);
- if (i+1 < sl->num_used) /* avoid double-counting the last one */
- n += join_len;
- }
- dst = r = tor_malloc(n+1);
- for (i = 0; i < sl->num_used; ) {
- for (src = sl->list[i]; *src; )
- *dst++ = *src++;
- if (++i < sl->num_used) {
- memcpy(dst, join, join_len);
- dst += join_len;
- }
- }
- if (terminate) {
- memcpy(dst, join, join_len);
- dst += join_len;
- }
- *dst = '\0';
-
- if (len_out)
- *len_out = dst-r;
- return r;
-}
-
-/** Sort the members of <b>sl</b> into an order defined by
- * the ordering function <b>compare</b>, which returns less then 0 if a
- * precedes b, greater than 0 if b precedes a, and 0 if a 'equals' b.
- */
-void
-smartlist_sort(smartlist_t *sl, int (*compare)(const void **a, const void **b))
-{
- if (!sl->num_used)
- return;
- qsort(sl->list, sl->num_used, sizeof(void*),
- (int (*)(const void *,const void*))compare);
-}
-
-/** Given a smartlist <b>sl</b> sorted with the function <b>compare</b>,
- * return the most frequent member in the list. Break ties in favor of
- * later elements. If the list is empty, return NULL. If count_out is
- * non-null, set it to the count of the most frequent member.
- */
-void *
-smartlist_get_most_frequent_(const smartlist_t *sl,
- int (*compare)(const void **a, const void **b),
- int *count_out)
-{
- const void *most_frequent = NULL;
- int most_frequent_count = 0;
-
- const void *cur = NULL;
- int i, count=0;
-
- if (!sl->num_used) {
- if (count_out)
- *count_out = 0;
- return NULL;
- }
- for (i = 0; i < sl->num_used; ++i) {
- const void *item = sl->list[i];
- if (cur && 0 == compare(&cur, &item)) {
- ++count;
- } else {
- if (cur && count >= most_frequent_count) {
- most_frequent = cur;
- most_frequent_count = count;
- }
- cur = item;
- count = 1;
- }
- }
- if (cur && count >= most_frequent_count) {
- most_frequent = cur;
- most_frequent_count = count;
- }
- if (count_out)
- *count_out = most_frequent_count;
- return (void*)most_frequent;
-}
-
-/** Given a sorted smartlist <b>sl</b> and the comparison function used to
- * sort it, remove all duplicate members. If free_fn is provided, calls
- * free_fn on each duplicate. Otherwise, just removes them. Preserves order.
- */
-void
-smartlist_uniq(smartlist_t *sl,
- int (*compare)(const void **a, const void **b),
- void (*free_fn)(void *a))
-{
- int i;
- for (i=1; i < sl->num_used; ++i) {
- if (compare((const void **)&(sl->list[i-1]),
- (const void **)&(sl->list[i])) == 0) {
- if (free_fn)
- free_fn(sl->list[i]);
- smartlist_del_keeporder(sl, i--);
- }
- }
-}
-
-/** Assuming the members of <b>sl</b> are in order, return a pointer to the
- * member that matches <b>key</b>. Ordering and matching are defined by a
- * <b>compare</b> function that returns 0 on a match; less than 0 if key is
- * less than member, and greater than 0 if key is greater then member.
- */
-void *
-smartlist_bsearch(smartlist_t *sl, const void *key,
- int (*compare)(const void *key, const void **member))
-{
- int found, idx;
- idx = smartlist_bsearch_idx(sl, key, compare, &found);
- return found ? smartlist_get(sl, idx) : NULL;
-}
-
-/** Assuming the members of <b>sl</b> are in order, return the index of the
- * member that matches <b>key</b>. If no member matches, return the index of
- * the first member greater than <b>key</b>, or smartlist_len(sl) if no member
- * is greater than <b>key</b>. Set <b>found_out</b> to true on a match, to
- * false otherwise. Ordering and matching are defined by a <b>compare</b>
- * function that returns 0 on a match; less than 0 if key is less than member,
- * and greater than 0 if key is greater then member.
- */
-int
-smartlist_bsearch_idx(const smartlist_t *sl, const void *key,
- int (*compare)(const void *key, const void **member),
- int *found_out)
-{
- int hi, lo, cmp, mid, len, diff;
-
- tor_assert(sl);
- tor_assert(compare);
- tor_assert(found_out);
-
- len = smartlist_len(sl);
-
- /* Check for the trivial case of a zero-length list */
- if (len == 0) {
- *found_out = 0;
- /* We already know smartlist_len(sl) is 0 in this case */
- return 0;
- }
-
- /* Okay, we have a real search to do */
- tor_assert(len > 0);
- lo = 0;
- hi = len - 1;
-
- /*
- * These invariants are always true:
- *
- * For all i such that 0 <= i < lo, sl[i] < key
- * For all i such that hi < i <= len, sl[i] > key
- */
-
- while (lo <= hi) {
- diff = hi - lo;
- /*
- * We want mid = (lo + hi) / 2, but that could lead to overflow, so
- * instead diff = hi - lo (non-negative because of loop condition), and
- * then hi = lo + diff, mid = (lo + lo + diff) / 2 = lo + (diff / 2).
- */
- mid = lo + (diff / 2);
- cmp = compare(key, (const void**) &(sl->list[mid]));
- if (cmp == 0) {
- /* sl[mid] == key; we found it */
- *found_out = 1;
- return mid;
- } else if (cmp > 0) {
- /*
- * key > sl[mid] and an index i such that sl[i] == key must
- * have i > mid if it exists.
- */
-
- /*
- * Since lo <= mid <= hi, hi can only decrease on each iteration (by
- * being set to mid - 1) and hi is initially len - 1, mid < len should
- * always hold, and this is not symmetric with the left end of list
- * mid > 0 test below. A key greater than the right end of the list
- * should eventually lead to lo == hi == mid == len - 1, and then
- * we set lo to len below and fall out to the same exit we hit for
- * a key in the middle of the list but not matching. Thus, we just
- * assert for consistency here rather than handle a mid == len case.
- */
- tor_assert(mid < len);
- /* Move lo to the element immediately after sl[mid] */
- lo = mid + 1;
- } else {
- /* This should always be true in this case */
- tor_assert(cmp < 0);
-
- /*
- * key < sl[mid] and an index i such that sl[i] == key must
- * have i < mid if it exists.
- */
-
- if (mid > 0) {
- /* Normal case, move hi to the element immediately before sl[mid] */
- hi = mid - 1;
- } else {
- /* These should always be true in this case */
- tor_assert(mid == lo);
- tor_assert(mid == 0);
- /*
- * We were at the beginning of the list and concluded that every
- * element e compares e > key.
- */
- *found_out = 0;
- return 0;
- }
- }
- }
-
- /*
- * lo > hi; we have no element matching key but we have elements falling
- * on both sides of it. The lo index points to the first element > key.
- */
- tor_assert(lo == hi + 1); /* All other cases should have been handled */
- tor_assert(lo >= 0);
- tor_assert(lo <= len);
- tor_assert(hi >= 0);
- tor_assert(hi <= len);
-
- if (lo < len) {
- cmp = compare(key, (const void **) &(sl->list[lo]));
- tor_assert(cmp < 0);
- } else {
- cmp = compare(key, (const void **) &(sl->list[len-1]));
- tor_assert(cmp > 0);
- }
-
- *found_out = 0;
- return lo;
-}
-
-/** Helper: compare two const char **s. */
-static int
-compare_string_ptrs_(const void **_a, const void **_b)
-{
- return strcmp((const char*)*_a, (const char*)*_b);
-}
-
-/** Sort a smartlist <b>sl</b> containing strings into lexically ascending
- * order. */
-void
-smartlist_sort_strings(smartlist_t *sl)
-{
- smartlist_sort(sl, compare_string_ptrs_);
-}
-
-/** Return the most frequent string in the sorted list <b>sl</b> */
-const char *
-smartlist_get_most_frequent_string(smartlist_t *sl)
-{
- return smartlist_get_most_frequent(sl, compare_string_ptrs_);
-}
-
-/** Return the most frequent string in the sorted list <b>sl</b>.
- * If <b>count_out</b> is provided, set <b>count_out</b> to the
- * number of times that string appears.
- */
-const char *
-smartlist_get_most_frequent_string_(smartlist_t *sl, int *count_out)
-{
- return smartlist_get_most_frequent_(sl, compare_string_ptrs_, count_out);
-}
-
-/** Remove duplicate strings from a sorted list, and free them with tor_free().
- */
-void
-smartlist_uniq_strings(smartlist_t *sl)
-{
- smartlist_uniq(sl, compare_string_ptrs_, tor_free_);
-}
-
-/** Helper: compare two pointers. */
-static int
-compare_ptrs_(const void **_a, const void **_b)
-{
- const void *a = *_a, *b = *_b;
- if (a<b)
- return -1;
- else if (a==b)
- return 0;
- else
- return 1;
-}
-
-/** Sort <b>sl</b> in ascending order of the pointers it contains. */
-void
-smartlist_sort_pointers(smartlist_t *sl)
-{
- smartlist_sort(sl, compare_ptrs_);
-}
-
-/* Heap-based priority queue implementation for O(lg N) insert and remove.
- * Recall that the heap property is that, for every index I, h[I] <
- * H[LEFT_CHILD[I]] and h[I] < H[RIGHT_CHILD[I]].
- *
- * For us to remove items other than the topmost item, each item must store
- * its own index within the heap. When calling the pqueue functions, tell
- * them about the offset of the field that stores the index within the item.
- *
- * Example:
- *
- * typedef struct timer_t {
- * struct timeval tv;
- * int heap_index;
- * } timer_t;
- *
- * static int compare(const void *p1, const void *p2) {
- * const timer_t *t1 = p1, *t2 = p2;
- * if (t1->tv.tv_sec < t2->tv.tv_sec) {
- * return -1;
- * } else if (t1->tv.tv_sec > t2->tv.tv_sec) {
- * return 1;
- * } else {
- * return t1->tv.tv_usec - t2->tv_usec;
- * }
- * }
- *
- * void timer_heap_insert(smartlist_t *heap, timer_t *timer) {
- * smartlist_pqueue_add(heap, compare, offsetof(timer_t, heap_index),
- * timer);
- * }
- *
- * void timer_heap_pop(smartlist_t *heap) {
- * return smartlist_pqueue_pop(heap, compare,
- * offsetof(timer_t, heap_index));
- * }
- */
-
-/** @{ */
-/** Functions to manipulate heap indices to find a node's parent and children.
- *
- * For a 1-indexed array, we would use LEFT_CHILD[x] = 2*x and RIGHT_CHILD[x]
- * = 2*x + 1. But this is C, so we have to adjust a little. */
-
-/* MAX_PARENT_IDX is the largest IDX in the smartlist which might have
- * children whose indices fit inside an int.
- * LEFT_CHILD(MAX_PARENT_IDX) == INT_MAX-2;
- * RIGHT_CHILD(MAX_PARENT_IDX) == INT_MAX-1;
- * LEFT_CHILD(MAX_PARENT_IDX + 1) == INT_MAX // impossible, see max list size.
- */
-#define MAX_PARENT_IDX ((INT_MAX - 2) / 2)
-/* If this is true, then i is small enough to potentially have children
- * in the smartlist, and it is save to use LEFT_CHILD/RIGHT_CHILD on it. */
-#define IDX_MAY_HAVE_CHILDREN(i) ((i) <= MAX_PARENT_IDX)
-#define LEFT_CHILD(i) ( 2*(i) + 1 )
-#define RIGHT_CHILD(i) ( 2*(i) + 2 )
-#define PARENT(i) ( ((i)-1) / 2 )
-/** }@ */
-
-/** @{ */
-/** Helper macros for heaps: Given a local variable <b>idx_field_offset</b>
- * set to the offset of an integer index within the heap element structure,
- * IDX_OF_ITEM(p) gives you the index of p, and IDXP(p) gives you a pointer to
- * where p's index is stored. Given additionally a local smartlist <b>sl</b>,
- * UPDATE_IDX(i) sets the index of the element at <b>i</b> to the correct
- * value (that is, to <b>i</b>).
- */
-#define IDXP(p) ((int*)STRUCT_VAR_P(p, idx_field_offset))
-
-#define UPDATE_IDX(i) do { \
- void *updated = sl->list[i]; \
- *IDXP(updated) = i; \
- } while (0)
-
-#define IDX_OF_ITEM(p) (*IDXP(p))
-/** @} */
-
-/** Helper. <b>sl</b> may have at most one violation of the heap property:
- * the item at <b>idx</b> may be greater than one or both of its children.
- * Restore the heap property. */
-static inline void
-smartlist_heapify(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset,
- int idx)
-{
- while (1) {
- if (! IDX_MAY_HAVE_CHILDREN(idx)) {
- /* idx is so large that it cannot have any children, since doing so
- * would mean the smartlist was over-capacity. Therefore it cannot
- * violate the heap property by being greater than a child (since it
- * doesn't have any). */
- return;
- }
-
- int left_idx = LEFT_CHILD(idx);
- int best_idx;
-
- if (left_idx >= sl->num_used)
- return;
- if (compare(sl->list[idx],sl->list[left_idx]) < 0)
- best_idx = idx;
- else
- best_idx = left_idx;
- if (left_idx+1 < sl->num_used &&
- compare(sl->list[left_idx+1],sl->list[best_idx]) < 0)
- best_idx = left_idx + 1;
-
- if (best_idx == idx) {
- return;
- } else {
- void *tmp = sl->list[idx];
- sl->list[idx] = sl->list[best_idx];
- sl->list[best_idx] = tmp;
- UPDATE_IDX(idx);
- UPDATE_IDX(best_idx);
-
- idx = best_idx;
- }
- }
-}
-
-/** Insert <b>item</b> into the heap stored in <b>sl</b>, where order is
- * determined by <b>compare</b> and the offset of the item in the heap is
- * stored in an int-typed field at position <b>idx_field_offset</b> within
- * item.
- */
-void
-smartlist_pqueue_add(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset,
- void *item)
-{
- int idx;
- smartlist_add(sl,item);
- UPDATE_IDX(sl->num_used-1);
-
- for (idx = sl->num_used - 1; idx; ) {
- int parent = PARENT(idx);
- if (compare(sl->list[idx], sl->list[parent]) < 0) {
- void *tmp = sl->list[parent];
- sl->list[parent] = sl->list[idx];
- sl->list[idx] = tmp;
- UPDATE_IDX(parent);
- UPDATE_IDX(idx);
- idx = parent;
- } else {
- return;
- }
- }
-}
-
-/** Remove and return the top-priority item from the heap stored in <b>sl</b>,
- * where order is determined by <b>compare</b> and the item's position is
- * stored at position <b>idx_field_offset</b> within the item. <b>sl</b> must
- * not be empty. */
-void *
-smartlist_pqueue_pop(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset)
-{
- void *top;
- tor_assert(sl->num_used);
-
- top = sl->list[0];
- *IDXP(top)=-1;
- if (--sl->num_used) {
- sl->list[0] = sl->list[sl->num_used];
- sl->list[sl->num_used] = NULL;
- UPDATE_IDX(0);
- smartlist_heapify(sl, compare, idx_field_offset, 0);
- }
- sl->list[sl->num_used] = NULL;
- return top;
-}
-
-/** Remove the item <b>item</b> from the heap stored in <b>sl</b>,
- * where order is determined by <b>compare</b> and the item's position is
- * stored at position <b>idx_field_offset</b> within the item. <b>sl</b> must
- * not be empty. */
-void
-smartlist_pqueue_remove(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset,
- void *item)
-{
- int idx = IDX_OF_ITEM(item);
- tor_assert(idx >= 0);
- tor_assert(sl->list[idx] == item);
- --sl->num_used;
- *IDXP(item) = -1;
- if (idx == sl->num_used) {
- sl->list[sl->num_used] = NULL;
- return;
- } else {
- sl->list[idx] = sl->list[sl->num_used];
- sl->list[sl->num_used] = NULL;
- UPDATE_IDX(idx);
- smartlist_heapify(sl, compare, idx_field_offset, idx);
- }
-}
-
-/** Assert that the heap property is correctly maintained by the heap stored
- * in <b>sl</b>, where order is determined by <b>compare</b>. */
-void
-smartlist_pqueue_assert_ok(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset)
-{
- int i;
- for (i = sl->num_used - 1; i >= 0; --i) {
- if (i>0)
- tor_assert(compare(sl->list[PARENT(i)], sl->list[i]) <= 0);
- tor_assert(IDX_OF_ITEM(sl->list[i]) == i);
- }
-}
-
-/** Helper: compare two DIGEST_LEN digests. */
-static int
-compare_digests_(const void **_a, const void **_b)
-{
- return tor_memcmp((const char*)*_a, (const char*)*_b, DIGEST_LEN);
-}
-
-/** Sort the list of DIGEST_LEN-byte digests into ascending order. */
-void
-smartlist_sort_digests(smartlist_t *sl)
-{
- smartlist_sort(sl, compare_digests_);
-}
-
-/** Remove duplicate digests from a sorted list, and free them with tor_free().
- */
-void
-smartlist_uniq_digests(smartlist_t *sl)
-{
- smartlist_uniq(sl, compare_digests_, tor_free_);
-}
-
-/** Helper: compare two DIGEST256_LEN digests. */
-static int
-compare_digests256_(const void **_a, const void **_b)
-{
- return tor_memcmp((const char*)*_a, (const char*)*_b, DIGEST256_LEN);
-}
-
-/** Sort the list of DIGEST256_LEN-byte digests into ascending order. */
-void
-smartlist_sort_digests256(smartlist_t *sl)
-{
- smartlist_sort(sl, compare_digests256_);
-}
-
-/** Return the most frequent member of the sorted list of DIGEST256_LEN
- * digests in <b>sl</b> */
-const uint8_t *
-smartlist_get_most_frequent_digest256(smartlist_t *sl)
-{
- return smartlist_get_most_frequent(sl, compare_digests256_);
-}
-
-/** Remove duplicate 256-bit digests from a sorted list, and free them with
- * tor_free().
- */
-void
-smartlist_uniq_digests256(smartlist_t *sl)
-{
- smartlist_uniq(sl, compare_digests256_, tor_free_);
-}
-
-/** Helper: Declare an entry type and a map type to implement a mapping using
- * ht.h. The map type will be called <b>maptype</b>. The key part of each
- * entry is declared using the C declaration <b>keydecl</b>. All functions
- * and types associated with the map get prefixed with <b>prefix</b> */
-#define DEFINE_MAP_STRUCTS(maptype, keydecl, prefix) \
- typedef struct prefix ## entry_t { \
- HT_ENTRY(prefix ## entry_t) node; \
- void *val; \
- keydecl; \
- } prefix ## entry_t; \
- struct maptype { \
- HT_HEAD(prefix ## impl, prefix ## entry_t) head; \
- }
-
-DEFINE_MAP_STRUCTS(strmap_t, char *key, strmap_);
-DEFINE_MAP_STRUCTS(digestmap_t, char key[DIGEST_LEN], digestmap_);
-DEFINE_MAP_STRUCTS(digest256map_t, uint8_t key[DIGEST256_LEN], digest256map_);
-
-/** Helper: compare strmap_entry_t objects by key value. */
-static inline int
-strmap_entries_eq(const strmap_entry_t *a, const strmap_entry_t *b)
-{
- return !strcmp(a->key, b->key);
-}
-
-/** Helper: return a hash value for a strmap_entry_t. */
-static inline unsigned int
-strmap_entry_hash(const strmap_entry_t *a)
-{
- return (unsigned) siphash24g(a->key, strlen(a->key));
-}
-
-/** Helper: compare digestmap_entry_t objects by key value. */
-static inline int
-digestmap_entries_eq(const digestmap_entry_t *a, const digestmap_entry_t *b)
-{
- return tor_memeq(a->key, b->key, DIGEST_LEN);
-}
-
-/** Helper: return a hash value for a digest_map_t. */
-static inline unsigned int
-digestmap_entry_hash(const digestmap_entry_t *a)
-{
- return (unsigned) siphash24g(a->key, DIGEST_LEN);
-}
-
-/** Helper: compare digestmap_entry_t objects by key value. */
-static inline int
-digest256map_entries_eq(const digest256map_entry_t *a,
- const digest256map_entry_t *b)
-{
- return tor_memeq(a->key, b->key, DIGEST256_LEN);
-}
-
-/** Helper: return a hash value for a digest_map_t. */
-static inline unsigned int
-digest256map_entry_hash(const digest256map_entry_t *a)
-{
- return (unsigned) siphash24g(a->key, DIGEST256_LEN);
-}
-
-HT_PROTOTYPE(strmap_impl, strmap_entry_t, node, strmap_entry_hash,
- strmap_entries_eq)
-HT_GENERATE2(strmap_impl, strmap_entry_t, node, strmap_entry_hash,
- strmap_entries_eq, 0.6, tor_reallocarray_, tor_free_)
-
-HT_PROTOTYPE(digestmap_impl, digestmap_entry_t, node, digestmap_entry_hash,
- digestmap_entries_eq)
-HT_GENERATE2(digestmap_impl, digestmap_entry_t, node, digestmap_entry_hash,
- digestmap_entries_eq, 0.6, tor_reallocarray_, tor_free_)
-
-HT_PROTOTYPE(digest256map_impl, digest256map_entry_t, node,
- digest256map_entry_hash,
- digest256map_entries_eq)
-HT_GENERATE2(digest256map_impl, digest256map_entry_t, node,
- digest256map_entry_hash,
- digest256map_entries_eq, 0.6, tor_reallocarray_, tor_free_)
-
-#define strmap_entry_free(ent) \
- FREE_AND_NULL(strmap_entry_t, strmap_entry_free_, (ent))
-#define digestmap_entry_free(ent) \
- FREE_AND_NULL(digestmap_entry_t, digestmap_entry_free_, (ent))
-#define digest256map_entry_free(ent) \
- FREE_AND_NULL(digest256map_entry_t, digest256map_entry_free_, (ent))
-
-static inline void
-strmap_entry_free_(strmap_entry_t *ent)
-{
- tor_free(ent->key);
- tor_free(ent);
-}
-static inline void
-digestmap_entry_free_(digestmap_entry_t *ent)
-{
- tor_free(ent);
-}
-static inline void
-digest256map_entry_free_(digest256map_entry_t *ent)
-{
- tor_free(ent);
-}
-
-static inline void
-strmap_assign_tmp_key(strmap_entry_t *ent, const char *key)
-{
- ent->key = (char*)key;
-}
-static inline void
-digestmap_assign_tmp_key(digestmap_entry_t *ent, const char *key)
-{
- memcpy(ent->key, key, DIGEST_LEN);
-}
-static inline void
-digest256map_assign_tmp_key(digest256map_entry_t *ent, const uint8_t *key)
-{
- memcpy(ent->key, key, DIGEST256_LEN);
-}
-static inline void
-strmap_assign_key(strmap_entry_t *ent, const char *key)
-{
- ent->key = tor_strdup(key);
-}
-static inline void
-digestmap_assign_key(digestmap_entry_t *ent, const char *key)
-{
- memcpy(ent->key, key, DIGEST_LEN);
-}
-static inline void
-digest256map_assign_key(digest256map_entry_t *ent, const uint8_t *key)
-{
- memcpy(ent->key, key, DIGEST256_LEN);
-}
-
-/**
- * Macro: implement all the functions for a map that are declared in
- * container.h by the DECLARE_MAP_FNS() macro. You must additionally define a
- * prefix_entry_free_() function to free entries (and their keys), a
- * prefix_assign_tmp_key() function to temporarily set a stack-allocated
- * entry to hold a key, and a prefix_assign_key() function to set a
- * heap-allocated entry to hold a key.
- */
-#define IMPLEMENT_MAP_FNS(maptype, keytype, prefix) \
- /** Create and return a new empty map. */ \
- MOCK_IMPL(maptype *, \
- prefix##_new,(void)) \
- { \
- maptype *result; \
- result = tor_malloc(sizeof(maptype)); \
- HT_INIT(prefix##_impl, &result->head); \
- return result; \
- } \
- \
- /** Return the item from <b>map</b> whose key matches <b>key</b>, or \
- * NULL if no such value exists. */ \
- void * \
- prefix##_get(const maptype *map, const keytype key) \
- { \
- prefix ##_entry_t *resolve; \
- prefix ##_entry_t search; \
- tor_assert(map); \
- tor_assert(key); \
- prefix ##_assign_tmp_key(&search, key); \
- resolve = HT_FIND(prefix ##_impl, &map->head, &search); \
- if (resolve) { \
- return resolve->val; \
- } else { \
- return NULL; \
- } \
- } \
- \
- /** Add an entry to <b>map</b> mapping <b>key</b> to <b>val</b>; \
- * return the previous value, or NULL if no such value existed. */ \
- void * \
- prefix##_set(maptype *map, const keytype key, void *val) \
- { \
- prefix##_entry_t search; \
- void *oldval; \
- tor_assert(map); \
- tor_assert(key); \
- tor_assert(val); \
- prefix##_assign_tmp_key(&search, key); \
- /* We a lot of our time in this function, so the code below is */ \
- /* meant to optimize the check/alloc/set cycle by avoiding the two */\
- /* trips to the hash table that we would do in the unoptimized */ \
- /* version of this code. (Each of HT_INSERT and HT_FIND calls */ \
- /* HT_SET_HASH and HT_FIND_P.) */ \
- HT_FIND_OR_INSERT_(prefix##_impl, node, prefix##_entry_hash, \
- &(map->head), \
- prefix##_entry_t, &search, ptr, \
- { \
- /* we found an entry. */ \
- oldval = (*ptr)->val; \
- (*ptr)->val = val; \
- return oldval; \
- }, \
- { \
- /* We didn't find the entry. */ \
- prefix##_entry_t *newent = \
- tor_malloc_zero(sizeof(prefix##_entry_t)); \
- prefix##_assign_key(newent, key); \
- newent->val = val; \
- HT_FOI_INSERT_(node, &(map->head), \
- &search, newent, ptr); \
- return NULL; \
- }); \
- } \
- \
- /** Remove the value currently associated with <b>key</b> from the map. \
- * Return the value if one was set, or NULL if there was no entry for \
- * <b>key</b>. \
- * \
- * Note: you must free any storage associated with the returned value. \
- */ \
- void * \
- prefix##_remove(maptype *map, const keytype key) \
- { \
- prefix##_entry_t *resolve; \
- prefix##_entry_t search; \
- void *oldval; \
- tor_assert(map); \
- tor_assert(key); \
- prefix##_assign_tmp_key(&search, key); \
- resolve = HT_REMOVE(prefix##_impl, &map->head, &search); \
- if (resolve) { \
- oldval = resolve->val; \
- prefix##_entry_free(resolve); \
- return oldval; \
- } else { \
- return NULL; \
- } \
- } \
- \
- /** Return the number of elements in <b>map</b>. */ \
- int \
- prefix##_size(const maptype *map) \
- { \
- return HT_SIZE(&map->head); \
- } \
- \
- /** Return true iff <b>map</b> has no entries. */ \
- int \
- prefix##_isempty(const maptype *map) \
- { \
- return HT_EMPTY(&map->head); \
- } \
- \
- /** Assert that <b>map</b> is not corrupt. */ \
- void \
- prefix##_assert_ok(const maptype *map) \
- { \
- tor_assert(!prefix##_impl_HT_REP_IS_BAD_(&map->head)); \
- } \
- \
- /** Remove all entries from <b>map</b>, and deallocate storage for \
- * those entries. If free_val is provided, invoked it every value in \
- * <b>map</b>. */ \
- MOCK_IMPL(void, \
- prefix##_free_, (maptype *map, void (*free_val)(void*))) \
- { \
- prefix##_entry_t **ent, **next, *this; \
- if (!map) \
- return; \
- for (ent = HT_START(prefix##_impl, &map->head); ent != NULL; \
- ent = next) { \
- this = *ent; \
- next = HT_NEXT_RMV(prefix##_impl, &map->head, ent); \
- if (free_val) \
- free_val(this->val); \
- prefix##_entry_free(this); \
- } \
- tor_assert(HT_EMPTY(&map->head)); \
- HT_CLEAR(prefix##_impl, &map->head); \
- tor_free(map); \
- } \
- \
- /** return an <b>iterator</b> pointer to the front of a map. \
- * \
- * Iterator example: \
- * \
- * \code \
- * // uppercase values in "map", removing empty values. \
- * \
- * strmap_iter_t *iter; \
- * const char *key; \
- * void *val; \
- * char *cp; \
- * \
- * for (iter = strmap_iter_init(map); !strmap_iter_done(iter); ) { \
- * strmap_iter_get(iter, &key, &val); \
- * cp = (char*)val; \
- * if (!*cp) { \
- * iter = strmap_iter_next_rmv(map,iter); \
- * free(val); \
- * } else { \
- * for (;*cp;cp++) *cp = TOR_TOUPPER(*cp); \
- */ \
- prefix##_iter_t * \
- prefix##_iter_init(maptype *map) \
- { \
- tor_assert(map); \
- return HT_START(prefix##_impl, &map->head); \
- } \
- \
- /** Advance <b>iter</b> a single step to the next entry, and return \
- * its new value. */ \
- prefix##_iter_t * \
- prefix##_iter_next(maptype *map, prefix##_iter_t *iter) \
- { \
- tor_assert(map); \
- tor_assert(iter); \
- return HT_NEXT(prefix##_impl, &map->head, iter); \
- } \
- /** Advance <b>iter</b> a single step to the next entry, removing the \
- * current entry, and return its new value. */ \
- prefix##_iter_t * \
- prefix##_iter_next_rmv(maptype *map, prefix##_iter_t *iter) \
- { \
- prefix##_entry_t *rmv; \
- tor_assert(map); \
- tor_assert(iter); \
- tor_assert(*iter); \
- rmv = *iter; \
- iter = HT_NEXT_RMV(prefix##_impl, &map->head, iter); \
- prefix##_entry_free(rmv); \
- return iter; \
- } \
- /** Set *<b>keyp</b> and *<b>valp</b> to the current entry pointed \
- * to by iter. */ \
- void \
- prefix##_iter_get(prefix##_iter_t *iter, const keytype *keyp, \
- void **valp) \
- { \
- tor_assert(iter); \
- tor_assert(*iter); \
- tor_assert(keyp); \
- tor_assert(valp); \
- *keyp = (*iter)->key; \
- *valp = (*iter)->val; \
- } \
- /** Return true iff <b>iter</b> has advanced past the last entry of \
- * <b>map</b>. */ \
- int \
- prefix##_iter_done(prefix##_iter_t *iter) \
- { \
- return iter == NULL; \
- }
-
-IMPLEMENT_MAP_FNS(strmap_t, char *, strmap)
-IMPLEMENT_MAP_FNS(digestmap_t, char *, digestmap)
-IMPLEMENT_MAP_FNS(digest256map_t, uint8_t *, digest256map)
-
-/** Same as strmap_set, but first converts <b>key</b> to lowercase. */
-void *
-strmap_set_lc(strmap_t *map, const char *key, void *val)
-{
- /* We could be a little faster by using strcasecmp instead, and a separate
- * type, but I don't think it matters. */
- void *v;
- char *lc_key = tor_strdup(key);
- tor_strlower(lc_key);
- v = strmap_set(map,lc_key,val);
- tor_free(lc_key);
- return v;
-}
-
-/** Same as strmap_get, but first converts <b>key</b> to lowercase. */
-void *
-strmap_get_lc(const strmap_t *map, const char *key)
-{
- void *v;
- char *lc_key = tor_strdup(key);
- tor_strlower(lc_key);
- v = strmap_get(map,lc_key);
- tor_free(lc_key);
- return v;
-}
-
-/** Same as strmap_remove, but first converts <b>key</b> to lowercase */
-void *
-strmap_remove_lc(strmap_t *map, const char *key)
-{
- void *v;
- char *lc_key = tor_strdup(key);
- tor_strlower(lc_key);
- v = strmap_remove(map,lc_key);
- tor_free(lc_key);
- return v;
-}
-
-/** Declare a function called <b>funcname</b> that acts as a find_nth_FOO
- * function for an array of type <b>elt_t</b>*.
- *
- * NOTE: The implementation kind of sucks: It's O(n log n), whereas finding
- * the kth element of an n-element list can be done in O(n). Then again, this
- * implementation is not in critical path, and it is obviously correct. */
-#define IMPLEMENT_ORDER_FUNC(funcname, elt_t) \
- static int \
- _cmp_ ## elt_t(const void *_a, const void *_b) \
- { \
- const elt_t *a = _a, *b = _b; \
- if (*a<*b) \
- return -1; \
- else if (*a>*b) \
- return 1; \
- else \
- return 0; \
- } \
- elt_t \
- funcname(elt_t *array, int n_elements, int nth) \
- { \
- tor_assert(nth >= 0); \
- tor_assert(nth < n_elements); \
- qsort(array, n_elements, sizeof(elt_t), _cmp_ ##elt_t); \
- return array[nth]; \
- }
-
-IMPLEMENT_ORDER_FUNC(find_nth_int, int)
-IMPLEMENT_ORDER_FUNC(find_nth_time, time_t)
-IMPLEMENT_ORDER_FUNC(find_nth_double, double)
-IMPLEMENT_ORDER_FUNC(find_nth_uint32, uint32_t)
-IMPLEMENT_ORDER_FUNC(find_nth_int32, int32_t)
-IMPLEMENT_ORDER_FUNC(find_nth_long, long)
-
-/** Return a newly allocated digestset_t, optimized to hold a total of
- * <b>max_elements</b> digests with a reasonably low false positive weight. */
-digestset_t *
-digestset_new(int max_elements)
-{
- /* The probability of false positives is about P=(1 - exp(-kn/m))^k, where k
- * is the number of hash functions per entry, m is the bits in the array,
- * and n is the number of elements inserted. For us, k==4, n<=max_elements,
- * and m==n_bits= approximately max_elements*32. This gives
- * P<(1-exp(-4*n/(32*n)))^4 == (1-exp(1/-8))^4 == .00019
- *
- * It would be more optimal in space vs false positives to get this false
- * positive rate by going for k==13, and m==18.5n, but we also want to
- * conserve CPU, and k==13 is pretty big.
- */
- int n_bits = 1u << (tor_log2(max_elements)+5);
- digestset_t *r = tor_malloc(sizeof(digestset_t));
- r->mask = n_bits - 1;
- r->ba = bitarray_init_zero(n_bits);
- return r;
-}
-
-/** Free all storage held in <b>set</b>. */
-void
-digestset_free_(digestset_t *set)
-{
- if (!set)
- return;
- bitarray_free(set->ba);
- tor_free(set);
-}
-
diff --git a/src/common/container.h b/src/common/container.h
deleted file mode 100644
index 5d2dce5416..0000000000
--- a/src/common/container.h
+++ /dev/null
@@ -1,742 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_CONTAINER_H
-#define TOR_CONTAINER_H
-
-#include "util.h"
-#include "siphash.h"
-
-/** A resizeable list of pointers, with associated helpful functionality.
- *
- * The members of this struct are exposed only so that macros and inlines can
- * use them; all access to smartlist internals should go through the functions
- * and macros defined here.
- **/
-typedef struct smartlist_t {
- /** @{ */
- /** <b>list</b> has enough capacity to store exactly <b>capacity</b> elements
- * before it needs to be resized. Only the first <b>num_used</b> (\<=
- * capacity) elements point to valid data.
- */
- void **list;
- int num_used;
- int capacity;
- /** @} */
-} smartlist_t;
-
-MOCK_DECL(smartlist_t *, smartlist_new, (void));
-MOCK_DECL(void, smartlist_free_, (smartlist_t *sl));
-#define smartlist_free(sl) FREE_AND_NULL(smartlist_t, smartlist_free_, (sl))
-
-void smartlist_clear(smartlist_t *sl);
-void smartlist_add(smartlist_t *sl, void *element);
-void smartlist_add_all(smartlist_t *sl, const smartlist_t *s2);
-void smartlist_remove(smartlist_t *sl, const void *element);
-void smartlist_remove_keeporder(smartlist_t *sl, const void *element);
-void *smartlist_pop_last(smartlist_t *sl);
-void smartlist_reverse(smartlist_t *sl);
-void smartlist_string_remove(smartlist_t *sl, const char *element);
-int smartlist_contains(const smartlist_t *sl, const void *element);
-int smartlist_contains_string(const smartlist_t *sl, const char *element);
-int smartlist_pos(const smartlist_t *sl, const void *element);
-int smartlist_string_pos(const smartlist_t *, const char *elt);
-int smartlist_contains_string_case(const smartlist_t *sl, const char *element);
-int smartlist_contains_int_as_string(const smartlist_t *sl, int num);
-int smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2);
-int smartlist_contains_digest(const smartlist_t *sl, const char *element);
-int smartlist_ints_eq(const smartlist_t *sl1, const smartlist_t *sl2);
-int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2);
-void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2);
-void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2);
-
-/* smartlist_choose() is defined in crypto.[ch] */
-#ifdef DEBUG_SMARTLIST
-/** Return the number of items in sl.
- */
-static inline int smartlist_len(const smartlist_t *sl);
-static inline int smartlist_len(const smartlist_t *sl) {
- tor_assert(sl);
- return (sl)->num_used;
-}
-/** Return the <b>idx</b>th element of sl.
- */
-static inline void *smartlist_get(const smartlist_t *sl, int idx);
-static inline void *smartlist_get(const smartlist_t *sl, int idx) {
- tor_assert(sl);
- tor_assert(idx>=0);
- tor_assert(sl->num_used > idx);
- return sl->list[idx];
-}
-static inline void smartlist_set(smartlist_t *sl, int idx, void *val) {
- tor_assert(sl);
- tor_assert(idx>=0);
- tor_assert(sl->num_used > idx);
- sl->list[idx] = val;
-}
-#else /* !(defined(DEBUG_SMARTLIST)) */
-#define smartlist_len(sl) ((sl)->num_used)
-#define smartlist_get(sl, idx) ((sl)->list[idx])
-#define smartlist_set(sl, idx, val) ((sl)->list[idx] = (val))
-#endif /* defined(DEBUG_SMARTLIST) */
-
-/** Exchange the elements at indices <b>idx1</b> and <b>idx2</b> of the
- * smartlist <b>sl</b>. */
-static inline void smartlist_swap(smartlist_t *sl, int idx1, int idx2)
-{
- if (idx1 != idx2) {
- void *elt = smartlist_get(sl, idx1);
- smartlist_set(sl, idx1, smartlist_get(sl, idx2));
- smartlist_set(sl, idx2, elt);
- }
-}
-
-void smartlist_del(smartlist_t *sl, int idx);
-void smartlist_del_keeporder(smartlist_t *sl, int idx);
-void smartlist_insert(smartlist_t *sl, int idx, void *val);
-void smartlist_sort(smartlist_t *sl,
- int (*compare)(const void **a, const void **b));
-void *smartlist_get_most_frequent_(const smartlist_t *sl,
- int (*compare)(const void **a, const void **b),
- int *count_out);
-#define smartlist_get_most_frequent(sl, compare) \
- smartlist_get_most_frequent_((sl), (compare), NULL)
-void smartlist_uniq(smartlist_t *sl,
- int (*compare)(const void **a, const void **b),
- void (*free_fn)(void *elt));
-
-void smartlist_sort_strings(smartlist_t *sl);
-void smartlist_sort_digests(smartlist_t *sl);
-void smartlist_sort_digests256(smartlist_t *sl);
-void smartlist_sort_pointers(smartlist_t *sl);
-
-const char *smartlist_get_most_frequent_string(smartlist_t *sl);
-const char *smartlist_get_most_frequent_string_(smartlist_t *sl,
- int *count_out);
-const uint8_t *smartlist_get_most_frequent_digest256(smartlist_t *sl);
-
-void smartlist_uniq_strings(smartlist_t *sl);
-void smartlist_uniq_digests(smartlist_t *sl);
-void smartlist_uniq_digests256(smartlist_t *sl);
-void *smartlist_bsearch(smartlist_t *sl, const void *key,
- int (*compare)(const void *key, const void **member));
-int smartlist_bsearch_idx(const smartlist_t *sl, const void *key,
- int (*compare)(const void *key, const void **member),
- int *found_out);
-
-void smartlist_pqueue_add(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset,
- void *item);
-void *smartlist_pqueue_pop(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset);
-void smartlist_pqueue_remove(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset,
- void *item);
-void smartlist_pqueue_assert_ok(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx_field_offset);
-
-#define SPLIT_SKIP_SPACE 0x01
-#define SPLIT_IGNORE_BLANK 0x02
-#define SPLIT_STRIP_SPACE 0x04
-int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep,
- int flags, int max);
-char *smartlist_join_strings(smartlist_t *sl, const char *join, int terminate,
- size_t *len_out) ATTR_MALLOC;
-char *smartlist_join_strings2(smartlist_t *sl, const char *join,
- size_t join_len, int terminate, size_t *len_out)
- ATTR_MALLOC;
-
-/** Iterate over the items in a smartlist <b>sl</b>, in order. For each item,
- * assign it to a new local variable of type <b>type</b> named <b>var</b>, and
- * execute the statements inside the loop body. Inside the loop, the loop
- * index can be accessed as <b>var</b>_sl_idx and the length of the list can
- * be accessed as <b>var</b>_sl_len.
- *
- * NOTE: Do not change the length of the list while the loop is in progress,
- * unless you adjust the _sl_len variable correspondingly. See second example
- * below.
- *
- * Example use:
- * <pre>
- * smartlist_t *list = smartlist_split("A:B:C", ":", 0, 0);
- * SMARTLIST_FOREACH_BEGIN(list, char *, cp) {
- * printf("%d: %s\n", cp_sl_idx, cp);
- * tor_free(cp);
- * } SMARTLIST_FOREACH_END(cp);
- * smartlist_free(list);
- * </pre>
- *
- * Example use (advanced):
- * <pre>
- * SMARTLIST_FOREACH_BEGIN(list, char *, cp) {
- * if (!strcmp(cp, "junk")) {
- * tor_free(cp);
- * SMARTLIST_DEL_CURRENT(list, cp);
- * }
- * } SMARTLIST_FOREACH_END(cp);
- * </pre>
- */
-/* Note: these macros use token pasting, and reach into smartlist internals.
- * This can make them a little daunting. Here's the approximate unpacking of
- * the above examples, for entertainment value:
- *
- * <pre>
- * smartlist_t *list = smartlist_split("A:B:C", ":", 0, 0);
- * {
- * int cp_sl_idx, cp_sl_len = smartlist_len(list);
- * char *cp;
- * for (cp_sl_idx = 0; cp_sl_idx < cp_sl_len; ++cp_sl_idx) {
- * cp = smartlist_get(list, cp_sl_idx);
- * printf("%d: %s\n", cp_sl_idx, cp);
- * tor_free(cp);
- * }
- * }
- * smartlist_free(list);
- * </pre>
- *
- * <pre>
- * {
- * int cp_sl_idx, cp_sl_len = smartlist_len(list);
- * char *cp;
- * for (cp_sl_idx = 0; cp_sl_idx < cp_sl_len; ++cp_sl_idx) {
- * cp = smartlist_get(list, cp_sl_idx);
- * if (!strcmp(cp, "junk")) {
- * tor_free(cp);
- * smartlist_del(list, cp_sl_idx);
- * --cp_sl_idx;
- * --cp_sl_len;
- * }
- * }
- * }
- * </pre>
- */
-#define SMARTLIST_FOREACH_BEGIN(sl, type, var) \
- STMT_BEGIN \
- int var ## _sl_idx, var ## _sl_len=(sl)->num_used; \
- type var; \
- for (var ## _sl_idx = 0; var ## _sl_idx < var ## _sl_len; \
- ++var ## _sl_idx) { \
- var = (sl)->list[var ## _sl_idx];
-
-#define SMARTLIST_FOREACH_END(var) \
- var = NULL; \
- (void) var ## _sl_idx; \
- } STMT_END
-
-/**
- * An alias for SMARTLIST_FOREACH_BEGIN and SMARTLIST_FOREACH_END, using
- * <b>cmd</b> as the loop body. This wrapper is here for convenience with
- * very short loops.
- *
- * By convention, we do not use this for loops which nest, or for loops over
- * 10 lines or so. Use SMARTLIST_FOREACH_{BEGIN,END} for those.
- */
-#define SMARTLIST_FOREACH(sl, type, var, cmd) \
- SMARTLIST_FOREACH_BEGIN(sl,type,var) { \
- cmd; \
- } SMARTLIST_FOREACH_END(var)
-
-/** Helper: While in a SMARTLIST_FOREACH loop over the list <b>sl</b> indexed
- * with the variable <b>var</b>, remove the current element in a way that
- * won't confuse the loop. */
-#define SMARTLIST_DEL_CURRENT(sl, var) \
- STMT_BEGIN \
- smartlist_del(sl, var ## _sl_idx); \
- --var ## _sl_idx; \
- --var ## _sl_len; \
- STMT_END
-
-/** Helper: While in a SMARTLIST_FOREACH loop over the list <b>sl</b> indexed
- * with the variable <b>var</b>, remove the current element in a way that
- * won't confuse the loop. */
-#define SMARTLIST_DEL_CURRENT_KEEPORDER(sl, var) \
- STMT_BEGIN \
- smartlist_del_keeporder(sl, var ## _sl_idx); \
- --var ## _sl_idx; \
- --var ## _sl_len; \
- STMT_END
-
-/** Helper: While in a SMARTLIST_FOREACH loop over the list <b>sl</b> indexed
- * with the variable <b>var</b>, replace the current element with <b>val</b>.
- * Does not deallocate the current value of <b>var</b>.
- */
-#define SMARTLIST_REPLACE_CURRENT(sl, var, val) \
- STMT_BEGIN \
- smartlist_set(sl, var ## _sl_idx, val); \
- STMT_END
-
-/* Helper: Given two lists of items, possibly of different types, such that
- * both lists are sorted on some common field (as determined by a comparison
- * expression <b>cmpexpr</b>), and such that one list (<b>sl1</b>) has no
- * duplicates on the common field, loop through the lists in lockstep, and
- * execute <b>unmatched_var2</b> on items in var2 that do not appear in
- * var1.
- *
- * WARNING: It isn't safe to add remove elements from either list while the
- * loop is in progress.
- *
- * Example use:
- * SMARTLIST_FOREACH_JOIN(routerstatus_list, routerstatus_t *, rs,
- * routerinfo_list, routerinfo_t *, ri,
- * tor_memcmp(rs->identity_digest, ri->identity_digest, 20),
- * log_info(LD_GENERAL,"No match for %s", ri->nickname)) {
- * log_info(LD_GENERAL, "%s matches routerstatus %p", ri->nickname, rs);
- * } SMARTLIST_FOREACH_JOIN_END(rs, ri);
- **/
-/* The example above unpacks (approximately) to:
- * int rs_sl_idx = 0, rs_sl_len = smartlist_len(routerstatus_list);
- * int ri_sl_idx, ri_sl_len = smartlist_len(routerinfo_list);
- * int rs_ri_cmp;
- * routerstatus_t *rs;
- * routerinfo_t *ri;
- * for (; ri_sl_idx < ri_sl_len; ++ri_sl_idx) {
- * ri = smartlist_get(routerinfo_list, ri_sl_idx);
- * while (rs_sl_idx < rs_sl_len) {
- * rs = smartlist_get(routerstatus_list, rs_sl_idx);
- * rs_ri_cmp = tor_memcmp(rs->identity_digest, ri->identity_digest, 20);
- * if (rs_ri_cmp > 0) {
- * break;
- * } else if (rs_ri_cmp == 0) {
- * goto matched_ri;
- * } else {
- * ++rs_sl_idx;
- * }
- * }
- * log_info(LD_GENERAL,"No match for %s", ri->nickname);
- * continue;
- * matched_ri: {
- * log_info(LD_GENERAL,"%s matches with routerstatus %p",ri->nickname,rs);
- * }
- * }
- */
-#define SMARTLIST_FOREACH_JOIN(sl1, type1, var1, sl2, type2, var2, \
- cmpexpr, unmatched_var2) \
- STMT_BEGIN \
- int var1 ## _sl_idx = 0, var1 ## _sl_len=(sl1)->num_used; \
- int var2 ## _sl_idx = 0, var2 ## _sl_len=(sl2)->num_used; \
- int var1 ## _ ## var2 ## _cmp; \
- type1 var1; \
- type2 var2; \
- for (; var2##_sl_idx < var2##_sl_len; ++var2##_sl_idx) { \
- var2 = (sl2)->list[var2##_sl_idx]; \
- while (var1##_sl_idx < var1##_sl_len) { \
- var1 = (sl1)->list[var1##_sl_idx]; \
- var1##_##var2##_cmp = (cmpexpr); \
- if (var1##_##var2##_cmp > 0) { \
- break; \
- } else if (var1##_##var2##_cmp == 0) { \
- goto matched_##var2; \
- } else { \
- ++var1##_sl_idx; \
- } \
- } \
- /* Ran out of v1, or no match for var2. */ \
- unmatched_var2; \
- continue; \
- matched_##var2: ; \
-
-#define SMARTLIST_FOREACH_JOIN_END(var1, var2) \
- } \
- STMT_END
-
-#define DECLARE_MAP_FNS(maptype, keytype, prefix) \
- typedef struct maptype maptype; \
- typedef struct prefix##entry_t *prefix##iter_t; \
- MOCK_DECL(maptype*, prefix##new, (void)); \
- void* prefix##set(maptype *map, keytype key, void *val); \
- void* prefix##get(const maptype *map, keytype key); \
- void* prefix##remove(maptype *map, keytype key); \
- MOCK_DECL(void, prefix##free_, (maptype *map, void (*free_val)(void*))); \
- int prefix##isempty(const maptype *map); \
- int prefix##size(const maptype *map); \
- prefix##iter_t *prefix##iter_init(maptype *map); \
- prefix##iter_t *prefix##iter_next(maptype *map, prefix##iter_t *iter); \
- prefix##iter_t *prefix##iter_next_rmv(maptype *map, prefix##iter_t *iter); \
- void prefix##iter_get(prefix##iter_t *iter, keytype *keyp, void **valp); \
- int prefix##iter_done(prefix##iter_t *iter); \
- void prefix##assert_ok(const maptype *map)
-
-/* Map from const char * to void *. Implemented with a hash table. */
-DECLARE_MAP_FNS(strmap_t, const char *, strmap_);
-/* Map from const char[DIGEST_LEN] to void *. Implemented with a hash table. */
-DECLARE_MAP_FNS(digestmap_t, const char *, digestmap_);
-/* Map from const uint8_t[DIGEST256_LEN] to void *. Implemented with a hash
- * table. */
-DECLARE_MAP_FNS(digest256map_t, const uint8_t *, digest256map_);
-
-#define MAP_FREE_AND_NULL(maptype, map, fn) \
- do { \
- maptype ## _free_((map), (fn)); \
- (map) = NULL; \
- } while (0)
-
-#define strmap_free(map, fn) MAP_FREE_AND_NULL(strmap, (map), (fn))
-#define digestmap_free(map, fn) MAP_FREE_AND_NULL(digestmap, (map), (fn))
-#define digest256map_free(map, fn) MAP_FREE_AND_NULL(digest256map, (map), (fn))
-
-#undef DECLARE_MAP_FNS
-
-/** Iterates over the key-value pairs in a map <b>map</b> in order.
- * <b>prefix</b> is as for DECLARE_MAP_FNS (i.e., strmap_ or digestmap_).
- * The map's keys and values are of type keytype and valtype respectively;
- * each iteration assigns them to keyvar and valvar.
- *
- * Example use:
- * MAP_FOREACH(digestmap_, m, const char *, k, routerinfo_t *, r) {
- * // use k and r
- * } MAP_FOREACH_END.
- */
-/* Unpacks to, approximately:
- * {
- * digestmap_iter_t *k_iter;
- * for (k_iter = digestmap_iter_init(m); !digestmap_iter_done(k_iter);
- * k_iter = digestmap_iter_next(m, k_iter)) {
- * const char *k;
- * void *r_voidp;
- * routerinfo_t *r;
- * digestmap_iter_get(k_iter, &k, &r_voidp);
- * r = r_voidp;
- * // use k and r
- * }
- * }
- */
-#define MAP_FOREACH(prefix, map, keytype, keyvar, valtype, valvar) \
- STMT_BEGIN \
- prefix##iter_t *keyvar##_iter; \
- for (keyvar##_iter = prefix##iter_init(map); \
- !prefix##iter_done(keyvar##_iter); \
- keyvar##_iter = prefix##iter_next(map, keyvar##_iter)) { \
- keytype keyvar; \
- void *valvar##_voidp; \
- valtype valvar; \
- prefix##iter_get(keyvar##_iter, &keyvar, &valvar##_voidp); \
- valvar = valvar##_voidp;
-
-/** As MAP_FOREACH, except allows members to be removed from the map
- * during the iteration via MAP_DEL_CURRENT. Example use:
- *
- * Example use:
- * MAP_FOREACH(digestmap_, m, const char *, k, routerinfo_t *, r) {
- * if (is_very_old(r))
- * MAP_DEL_CURRENT(k);
- * } MAP_FOREACH_END.
- **/
-/* Unpacks to, approximately:
- * {
- * digestmap_iter_t *k_iter;
- * int k_del=0;
- * for (k_iter = digestmap_iter_init(m); !digestmap_iter_done(k_iter);
- * k_iter = k_del ? digestmap_iter_next(m, k_iter)
- * : digestmap_iter_next_rmv(m, k_iter)) {
- * const char *k;
- * void *r_voidp;
- * routerinfo_t *r;
- * k_del=0;
- * digestmap_iter_get(k_iter, &k, &r_voidp);
- * r = r_voidp;
- * if (is_very_old(r)) {
- * k_del = 1;
- * }
- * }
- * }
- */
-#define MAP_FOREACH_MODIFY(prefix, map, keytype, keyvar, valtype, valvar) \
- STMT_BEGIN \
- prefix##iter_t *keyvar##_iter; \
- int keyvar##_del=0; \
- for (keyvar##_iter = prefix##iter_init(map); \
- !prefix##iter_done(keyvar##_iter); \
- keyvar##_iter = keyvar##_del ? \
- prefix##iter_next_rmv(map, keyvar##_iter) : \
- prefix##iter_next(map, keyvar##_iter)) { \
- keytype keyvar; \
- void *valvar##_voidp; \
- valtype valvar; \
- keyvar##_del=0; \
- prefix##iter_get(keyvar##_iter, &keyvar, &valvar##_voidp); \
- valvar = valvar##_voidp;
-
-/** Used with MAP_FOREACH_MODIFY to remove the currently-iterated-upon
- * member of the map. */
-#define MAP_DEL_CURRENT(keyvar) \
- STMT_BEGIN \
- keyvar##_del = 1; \
- STMT_END
-
-/** Used to end a MAP_FOREACH() block. */
-#define MAP_FOREACH_END } STMT_END ;
-
-/** As MAP_FOREACH, but does not require declaration of prefix or keytype.
- * Example use:
- * DIGESTMAP_FOREACH(m, k, routerinfo_t *, r) {
- * // use k and r
- * } DIGESTMAP_FOREACH_END.
- */
-#define DIGESTMAP_FOREACH(map, keyvar, valtype, valvar) \
- MAP_FOREACH(digestmap_, map, const char *, keyvar, valtype, valvar)
-
-/** As MAP_FOREACH_MODIFY, but does not require declaration of prefix or
- * keytype.
- * Example use:
- * DIGESTMAP_FOREACH_MODIFY(m, k, routerinfo_t *, r) {
- * if (is_very_old(r))
- * MAP_DEL_CURRENT(k);
- * } DIGESTMAP_FOREACH_END.
- */
-#define DIGESTMAP_FOREACH_MODIFY(map, keyvar, valtype, valvar) \
- MAP_FOREACH_MODIFY(digestmap_, map, const char *, keyvar, valtype, valvar)
-/** Used to end a DIGESTMAP_FOREACH() block. */
-#define DIGESTMAP_FOREACH_END MAP_FOREACH_END
-
-#define DIGEST256MAP_FOREACH(map, keyvar, valtype, valvar) \
- MAP_FOREACH(digest256map_, map, const uint8_t *, keyvar, valtype, valvar)
-#define DIGEST256MAP_FOREACH_MODIFY(map, keyvar, valtype, valvar) \
- MAP_FOREACH_MODIFY(digest256map_, map, const uint8_t *, \
- keyvar, valtype, valvar)
-#define DIGEST256MAP_FOREACH_END MAP_FOREACH_END
-
-#define STRMAP_FOREACH(map, keyvar, valtype, valvar) \
- MAP_FOREACH(strmap_, map, const char *, keyvar, valtype, valvar)
-#define STRMAP_FOREACH_MODIFY(map, keyvar, valtype, valvar) \
- MAP_FOREACH_MODIFY(strmap_, map, const char *, keyvar, valtype, valvar)
-#define STRMAP_FOREACH_END MAP_FOREACH_END
-
-void* strmap_set_lc(strmap_t *map, const char *key, void *val);
-void* strmap_get_lc(const strmap_t *map, const char *key);
-void* strmap_remove_lc(strmap_t *map, const char *key);
-
-#define DECLARE_TYPED_DIGESTMAP_FNS(prefix, maptype, valtype) \
- typedef struct maptype maptype; \
- typedef struct prefix##iter_t *prefix##iter_t; \
- ATTR_UNUSED static inline maptype* \
- prefix##new(void) \
- { \
- return (maptype*)digestmap_new(); \
- } \
- ATTR_UNUSED static inline digestmap_t* \
- prefix##to_digestmap(maptype *map) \
- { \
- return (digestmap_t*)map; \
- } \
- ATTR_UNUSED static inline valtype* \
- prefix##get(maptype *map, const char *key) \
- { \
- return (valtype*)digestmap_get((digestmap_t*)map, key); \
- } \
- ATTR_UNUSED static inline valtype* \
- prefix##set(maptype *map, const char *key, valtype *val) \
- { \
- return (valtype*)digestmap_set((digestmap_t*)map, key, val); \
- } \
- ATTR_UNUSED static inline valtype* \
- prefix##remove(maptype *map, const char *key) \
- { \
- return (valtype*)digestmap_remove((digestmap_t*)map, key); \
- } \
- ATTR_UNUSED static inline void \
- prefix##f##ree_(maptype *map, void (*free_val)(void*)) \
- { \
- digestmap_free_((digestmap_t*)map, free_val); \
- } \
- ATTR_UNUSED static inline int \
- prefix##isempty(maptype *map) \
- { \
- return digestmap_isempty((digestmap_t*)map); \
- } \
- ATTR_UNUSED static inline int \
- prefix##size(maptype *map) \
- { \
- return digestmap_size((digestmap_t*)map); \
- } \
- ATTR_UNUSED static inline \
- prefix##iter_t *prefix##iter_init(maptype *map) \
- { \
- return (prefix##iter_t*) digestmap_iter_init((digestmap_t*)map); \
- } \
- ATTR_UNUSED static inline \
- prefix##iter_t *prefix##iter_next(maptype *map, prefix##iter_t *iter) \
- { \
- return (prefix##iter_t*) digestmap_iter_next( \
- (digestmap_t*)map, (digestmap_iter_t*)iter); \
- } \
- ATTR_UNUSED static inline prefix##iter_t* \
- prefix##iter_next_rmv(maptype *map, prefix##iter_t *iter) \
- { \
- return (prefix##iter_t*) digestmap_iter_next_rmv( \
- (digestmap_t*)map, (digestmap_iter_t*)iter); \
- } \
- ATTR_UNUSED static inline void \
- prefix##iter_get(prefix##iter_t *iter, \
- const char **keyp, \
- valtype **valp) \
- { \
- void *v; \
- digestmap_iter_get((digestmap_iter_t*) iter, keyp, &v); \
- *valp = v; \
- } \
- ATTR_UNUSED static inline int \
- prefix##iter_done(prefix##iter_t *iter) \
- { \
- return digestmap_iter_done((digestmap_iter_t*)iter); \
- }
-
-#if SIZEOF_INT == 4
-#define BITARRAY_SHIFT 5
-#elif SIZEOF_INT == 8
-#define BITARRAY_SHIFT 6
-#else
-#error "int is neither 4 nor 8 bytes. I can't deal with that."
-#endif /* SIZEOF_INT == 4 || ... */
-#define BITARRAY_MASK ((1u<<BITARRAY_SHIFT)-1)
-
-/** A random-access array of one-bit-wide elements. */
-typedef unsigned int bitarray_t;
-/** Create a new bit array that can hold <b>n_bits</b> bits. */
-static inline bitarray_t *
-bitarray_init_zero(unsigned int n_bits)
-{
- /* round up to the next int. */
- size_t sz = (n_bits+BITARRAY_MASK) >> BITARRAY_SHIFT;
- return tor_calloc(sz, sizeof(unsigned int));
-}
-/** Expand <b>ba</b> from holding <b>n_bits_old</b> to <b>n_bits_new</b>,
- * clearing all new bits. Returns a possibly changed pointer to the
- * bitarray. */
-static inline bitarray_t *
-bitarray_expand(bitarray_t *ba,
- unsigned int n_bits_old, unsigned int n_bits_new)
-{
- size_t sz_old = (n_bits_old+BITARRAY_MASK) >> BITARRAY_SHIFT;
- size_t sz_new = (n_bits_new+BITARRAY_MASK) >> BITARRAY_SHIFT;
- char *ptr;
- if (sz_new <= sz_old)
- return ba;
- ptr = tor_reallocarray(ba, sz_new, sizeof(unsigned int));
- /* This memset does nothing to the older excess bytes. But they were
- * already set to 0 by bitarry_init_zero. */
- memset(ptr+sz_old*sizeof(unsigned int), 0,
- (sz_new-sz_old)*sizeof(unsigned int));
- return (bitarray_t*) ptr;
-}
-/** Free the bit array <b>ba</b>. */
-static inline void
-bitarray_free_(bitarray_t *ba)
-{
- tor_free(ba);
-}
-#define bitarray_free(ba) FREE_AND_NULL(bitarray_t, bitarray_free_, (ba))
-
-/** Set the <b>bit</b>th bit in <b>b</b> to 1. */
-static inline void
-bitarray_set(bitarray_t *b, int bit)
-{
- b[bit >> BITARRAY_SHIFT] |= (1u << (bit & BITARRAY_MASK));
-}
-/** Set the <b>bit</b>th bit in <b>b</b> to 0. */
-static inline void
-bitarray_clear(bitarray_t *b, int bit)
-{
- b[bit >> BITARRAY_SHIFT] &= ~ (1u << (bit & BITARRAY_MASK));
-}
-/** Return true iff <b>bit</b>th bit in <b>b</b> is nonzero. NOTE: does
- * not necessarily return 1 on true. */
-static inline unsigned int
-bitarray_is_set(bitarray_t *b, int bit)
-{
- return b[bit >> BITARRAY_SHIFT] & (1u << (bit & BITARRAY_MASK));
-}
-
-/** A set of digests, implemented as a Bloom filter. */
-typedef struct {
- int mask; /**< One less than the number of bits in <b>ba</b>; always one less
- * than a power of two. */
- bitarray_t *ba; /**< A bit array to implement the Bloom filter. */
-} digestset_t;
-
-#define BIT(n) ((n) & set->mask)
-/** Add the digest <b>digest</b> to <b>set</b>. */
-static inline void
-digestset_add(digestset_t *set, const char *digest)
-{
- const uint64_t x = siphash24g(digest, 20);
- const uint32_t d1 = (uint32_t) x;
- const uint32_t d2 = (uint32_t)( (x>>16) + x);
- const uint32_t d3 = (uint32_t)( (x>>32) + x);
- const uint32_t d4 = (uint32_t)( (x>>48) + x);
- bitarray_set(set->ba, BIT(d1));
- bitarray_set(set->ba, BIT(d2));
- bitarray_set(set->ba, BIT(d3));
- bitarray_set(set->ba, BIT(d4));
-}
-
-/** If <b>digest</b> is in <b>set</b>, return nonzero. Otherwise,
- * <em>probably</em> return zero. */
-static inline int
-digestset_contains(const digestset_t *set, const char *digest)
-{
- const uint64_t x = siphash24g(digest, 20);
- const uint32_t d1 = (uint32_t) x;
- const uint32_t d2 = (uint32_t)( (x>>16) + x);
- const uint32_t d3 = (uint32_t)( (x>>32) + x);
- const uint32_t d4 = (uint32_t)( (x>>48) + x);
- return bitarray_is_set(set->ba, BIT(d1)) &&
- bitarray_is_set(set->ba, BIT(d2)) &&
- bitarray_is_set(set->ba, BIT(d3)) &&
- bitarray_is_set(set->ba, BIT(d4));
-}
-#undef BIT
-
-digestset_t *digestset_new(int max_elements);
-void digestset_free_(digestset_t* set);
-#define digestset_free(set) FREE_AND_NULL(digestset_t, digestset_free_, (set))
-
-/* These functions, given an <b>array</b> of <b>n_elements</b>, return the
- * <b>nth</b> lowest element. <b>nth</b>=0 gives the lowest element;
- * <b>n_elements</b>-1 gives the highest; and (<b>n_elements</b>-1) / 2 gives
- * the median. As a side effect, the elements of <b>array</b> are sorted. */
-int find_nth_int(int *array, int n_elements, int nth);
-time_t find_nth_time(time_t *array, int n_elements, int nth);
-double find_nth_double(double *array, int n_elements, int nth);
-int32_t find_nth_int32(int32_t *array, int n_elements, int nth);
-uint32_t find_nth_uint32(uint32_t *array, int n_elements, int nth);
-long find_nth_long(long *array, int n_elements, int nth);
-static inline int
-median_int(int *array, int n_elements)
-{
- return find_nth_int(array, n_elements, (n_elements-1)/2);
-}
-static inline time_t
-median_time(time_t *array, int n_elements)
-{
- return find_nth_time(array, n_elements, (n_elements-1)/2);
-}
-static inline double
-median_double(double *array, int n_elements)
-{
- return find_nth_double(array, n_elements, (n_elements-1)/2);
-}
-static inline uint32_t
-median_uint32(uint32_t *array, int n_elements)
-{
- return find_nth_uint32(array, n_elements, (n_elements-1)/2);
-}
-static inline int32_t
-median_int32(int32_t *array, int n_elements)
-{
- return find_nth_int32(array, n_elements, (n_elements-1)/2);
-}
-
-static inline uint32_t
-third_quartile_uint32(uint32_t *array, int n_elements)
-{
- return find_nth_uint32(array, n_elements, (n_elements*3)/4);
-}
-
-#endif /* !defined(TOR_CONTAINER_H) */
-
diff --git a/src/common/crypto.c b/src/common/crypto.c
deleted file mode 100644
index d5b7c96916..0000000000
--- a/src/common/crypto.c
+++ /dev/null
@@ -1,1118 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto.c
- * \brief Wrapper functions to present a consistent interface to
- * public-key and symmetric cryptography operations from OpenSSL and
- * other places.
- **/
-
-#include "orconfig.h"
-
-#ifdef _WIN32
-#include <winsock2.h>
-#include <windows.h>
-#include <wincrypt.h>
-/* Windows defines this; so does OpenSSL 0.9.8h and later. We don't actually
- * use either definition. */
-#undef OCSP_RESPONSE
-#endif /* defined(_WIN32) */
-
-#define CRYPTO_PRIVATE
-#include "compat_openssl.h"
-#include "crypto.h"
-#include "crypto_curve25519.h"
-#include "crypto_digest.h"
-#include "crypto_ed25519.h"
-#include "crypto_format.h"
-#include "crypto_rand.h"
-#include "crypto_rsa.h"
-#include "crypto_util.h"
-
-DISABLE_GCC_WARNING(redundant-decls)
-
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/engine.h>
-#include <openssl/bn.h>
-#include <openssl/dh.h>
-#include <openssl/conf.h>
-#include <openssl/hmac.h>
-#include <openssl/ssl.h>
-
-ENABLE_GCC_WARNING(redundant-decls)
-
-#if __GNUC__ && GCC_VERSION >= 402
-#if GCC_VERSION >= 406
-#pragma GCC diagnostic pop
-#else
-#pragma GCC diagnostic warning "-Wredundant-decls"
-#endif
-#endif /* __GNUC__ && GCC_VERSION >= 402 */
-
-#ifdef HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "torlog.h"
-#include "torint.h"
-#include "aes.h"
-#include "util.h"
-#include "container.h"
-#include "compat.h"
-#include "sandbox.h"
-#include "util_format.h"
-
-#include "keccak-tiny/keccak-tiny.h"
-
-/** A structure to hold the first half (x, g^x) of a Diffie-Hellman handshake
- * while we're waiting for the second.*/
-struct crypto_dh_t {
- DH *dh; /**< The openssl DH object */
-};
-
-static int tor_check_dh_key(int severity, const BIGNUM *bn);
-
-/** Boolean: has OpenSSL's crypto been initialized? */
-static int crypto_early_initialized_ = 0;
-
-/** Boolean: has OpenSSL's crypto been initialized? */
-static int crypto_global_initialized_ = 0;
-
-/** Log all pending crypto errors at level <b>severity</b>. Use
- * <b>doing</b> to describe our current activities.
- */
-static void
-crypto_log_errors(int severity, const char *doing)
-{
- unsigned long err;
- const char *msg, *lib, *func;
- while ((err = ERR_get_error()) != 0) {
- msg = (const char*)ERR_reason_error_string(err);
- lib = (const char*)ERR_lib_error_string(err);
- func = (const char*)ERR_func_error_string(err);
- if (!msg) msg = "(null)";
- if (!lib) lib = "(null)";
- if (!func) func = "(null)";
- if (BUG(!doing)) doing = "(null)";
- tor_log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)",
- doing, msg, lib, func);
- }
-}
-
-#ifndef DISABLE_ENGINES
-/** Log any OpenSSL engines we're using at NOTICE. */
-static void
-log_engine(const char *fn, ENGINE *e)
-{
- if (e) {
- const char *name, *id;
- name = ENGINE_get_name(e);
- id = ENGINE_get_id(e);
- log_notice(LD_CRYPTO, "Default OpenSSL engine for %s is %s [%s]",
- fn, name?name:"?", id?id:"?");
- } else {
- log_info(LD_CRYPTO, "Using default implementation for %s", fn);
- }
-}
-#endif /* !defined(DISABLE_ENGINES) */
-
-#ifndef DISABLE_ENGINES
-/** Try to load an engine in a shared library via fully qualified path.
- */
-static ENGINE *
-try_load_engine(const char *path, const char *engine)
-{
- ENGINE *e = ENGINE_by_id("dynamic");
- if (e) {
- if (!ENGINE_ctrl_cmd_string(e, "ID", engine, 0) ||
- !ENGINE_ctrl_cmd_string(e, "DIR_LOAD", "2", 0) ||
- !ENGINE_ctrl_cmd_string(e, "DIR_ADD", path, 0) ||
- !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
- ENGINE_free(e);
- e = NULL;
- }
- }
- return e;
-}
-#endif /* !defined(DISABLE_ENGINES) */
-
-static int have_seeded_siphash = 0;
-
-/** Set up the siphash key if we haven't already done so. */
-int
-crypto_init_siphash_key(void)
-{
- struct sipkey key;
- if (have_seeded_siphash)
- return 0;
-
- crypto_rand((char*) &key, sizeof(key));
- siphash_set_global_key(&key);
- have_seeded_siphash = 1;
- return 0;
-}
-
-/** Initialize the crypto library. Return 0 on success, -1 on failure.
- */
-int
-crypto_early_init(void)
-{
- if (!crypto_early_initialized_) {
-
- crypto_early_initialized_ = 1;
-
-#ifdef OPENSSL_1_1_API
- OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS |
- OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
- OPENSSL_INIT_ADD_ALL_CIPHERS |
- OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
-#else
- ERR_load_crypto_strings();
- OpenSSL_add_all_algorithms();
-#endif
-
- setup_openssl_threading();
-
- unsigned long version_num = OpenSSL_version_num();
- const char *version_str = OpenSSL_version(OPENSSL_VERSION);
- if (version_num == OPENSSL_VERSION_NUMBER &&
- !strcmp(version_str, OPENSSL_VERSION_TEXT)) {
- log_info(LD_CRYPTO, "OpenSSL version matches version from headers "
- "(%lx: %s).", version_num, version_str);
- } else {
- log_warn(LD_CRYPTO, "OpenSSL version from headers does not match the "
- "version we're running with. If you get weird crashes, that "
- "might be why. (Compiled with %lx: %s; running with %lx: %s).",
- (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
- version_num, version_str);
- }
-
- crypto_force_rand_ssleay();
-
- if (crypto_seed_rng() < 0)
- return -1;
- if (crypto_init_siphash_key() < 0)
- return -1;
-
- curve25519_init();
- ed25519_init();
- }
- return 0;
-}
-
-/** Initialize the crypto library. Return 0 on success, -1 on failure.
- */
-int
-crypto_global_init(int useAccel, const char *accelName, const char *accelDir)
-{
- if (!crypto_global_initialized_) {
- if (crypto_early_init() < 0)
- return -1;
-
- crypto_global_initialized_ = 1;
-
- if (useAccel > 0) {
-#ifdef DISABLE_ENGINES
- (void)accelName;
- (void)accelDir;
- log_warn(LD_CRYPTO, "No OpenSSL hardware acceleration support enabled.");
-#else
- ENGINE *e = NULL;
-
- log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
- ENGINE_load_builtin_engines();
- ENGINE_register_all_complete();
-
- if (accelName) {
- if (accelDir) {
- log_info(LD_CRYPTO, "Trying to load dynamic OpenSSL engine \"%s\""
- " via path \"%s\".", accelName, accelDir);
- e = try_load_engine(accelName, accelDir);
- } else {
- log_info(LD_CRYPTO, "Initializing dynamic OpenSSL engine \"%s\""
- " acceleration support.", accelName);
- e = ENGINE_by_id(accelName);
- }
- if (!e) {
- log_warn(LD_CRYPTO, "Unable to load dynamic OpenSSL engine \"%s\".",
- accelName);
- } else {
- log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".",
- accelName);
- }
- }
- if (e) {
- log_info(LD_CRYPTO, "Loaded OpenSSL hardware acceleration engine,"
- " setting default ciphers.");
- ENGINE_set_default(e, ENGINE_METHOD_ALL);
- }
- /* Log, if available, the intersection of the set of algorithms
- used by Tor and the set of algorithms available in the engine */
- log_engine("RSA", ENGINE_get_default_RSA());
- log_engine("DH", ENGINE_get_default_DH());
-#ifdef OPENSSL_1_1_API
- log_engine("EC", ENGINE_get_default_EC());
-#else
- log_engine("ECDH", ENGINE_get_default_ECDH());
- log_engine("ECDSA", ENGINE_get_default_ECDSA());
-#endif /* defined(OPENSSL_1_1_API) */
- log_engine("RAND", ENGINE_get_default_RAND());
- log_engine("RAND (which we will not use)", ENGINE_get_default_RAND());
- log_engine("SHA1", ENGINE_get_digest_engine(NID_sha1));
- log_engine("3DES-CBC", ENGINE_get_cipher_engine(NID_des_ede3_cbc));
- log_engine("AES-128-ECB", ENGINE_get_cipher_engine(NID_aes_128_ecb));
- log_engine("AES-128-CBC", ENGINE_get_cipher_engine(NID_aes_128_cbc));
-#ifdef NID_aes_128_ctr
- log_engine("AES-128-CTR", ENGINE_get_cipher_engine(NID_aes_128_ctr));
-#endif
-#ifdef NID_aes_128_gcm
- log_engine("AES-128-GCM", ENGINE_get_cipher_engine(NID_aes_128_gcm));
-#endif
- log_engine("AES-256-CBC", ENGINE_get_cipher_engine(NID_aes_256_cbc));
-#ifdef NID_aes_256_gcm
- log_engine("AES-256-GCM", ENGINE_get_cipher_engine(NID_aes_256_gcm));
-#endif
-
-#endif /* defined(DISABLE_ENGINES) */
- } else {
- log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
- }
-
- if (crypto_force_rand_ssleay()) {
- if (crypto_seed_rng() < 0)
- return -1;
- }
-
- evaluate_evp_for_aes(-1);
- evaluate_ctr_for_aes();
- }
- return 0;
-}
-
-/** Free crypto resources held by this thread. */
-void
-crypto_thread_cleanup(void)
-{
-#ifndef NEW_THREAD_API
- ERR_remove_thread_state(NULL);
-#endif
-}
-
-/** Used by tortls.c: Get the DH* from a crypto_dh_t.
- */
-DH *
-crypto_dh_get_dh_(crypto_dh_t *dh)
-{
- return dh->dh;
-}
-
-/** Allocate and return a new symmetric cipher using the provided key and iv.
- * The key is <b>bits</b> bits long; the IV is CIPHER_IV_LEN bytes. Both
- * must be provided. Key length must be 128, 192, or 256 */
-crypto_cipher_t *
-crypto_cipher_new_with_iv_and_bits(const uint8_t *key,
- const uint8_t *iv,
- int bits)
-{
- tor_assert(key);
- tor_assert(iv);
-
- return aes_new_cipher((const uint8_t*)key, (const uint8_t*)iv, bits);
-}
-
-/** Allocate and return a new symmetric cipher using the provided key and iv.
- * The key is CIPHER_KEY_LEN bytes; the IV is CIPHER_IV_LEN bytes. Both
- * must be provided.
- */
-crypto_cipher_t *
-crypto_cipher_new_with_iv(const char *key, const char *iv)
-{
- return crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)iv,
- 128);
-}
-
-/** Return a new crypto_cipher_t with the provided <b>key</b> and an IV of all
- * zero bytes and key length <b>bits</b>. Key length must be 128, 192, or
- * 256. */
-crypto_cipher_t *
-crypto_cipher_new_with_bits(const char *key, int bits)
-{
- char zeroiv[CIPHER_IV_LEN];
- memset(zeroiv, 0, sizeof(zeroiv));
- return crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)zeroiv,
- bits);
-}
-
-/** Return a new crypto_cipher_t with the provided <b>key</b> (of
- * CIPHER_KEY_LEN bytes) and an IV of all zero bytes. */
-crypto_cipher_t *
-crypto_cipher_new(const char *key)
-{
- return crypto_cipher_new_with_bits(key, 128);
-}
-
-/** Free a symmetric cipher.
- */
-void
-crypto_cipher_free_(crypto_cipher_t *env)
-{
- if (!env)
- return;
-
- aes_cipher_free(env);
-}
-
-/** Copy <b>in</b> to the <b>outlen</b>-byte buffer <b>out</b>, adding spaces
- * every four characters. */
-void
-crypto_add_spaces_to_fp(char *out, size_t outlen, const char *in)
-{
- int n = 0;
- char *end = out+outlen;
- tor_assert(outlen < SIZE_T_CEILING);
-
- while (*in && out<end) {
- *out++ = *in++;
- if (++n == 4 && *in && out<end) {
- n = 0;
- *out++ = ' ';
- }
- }
- tor_assert(out<end);
- *out = '\0';
-}
-
-/* symmetric crypto */
-
-/** Encrypt <b>fromlen</b> bytes from <b>from</b> using the cipher
- * <b>env</b>; on success, store the result to <b>to</b> and return 0.
- * Does not check for failure.
- */
-int
-crypto_cipher_encrypt(crypto_cipher_t *env, char *to,
- const char *from, size_t fromlen)
-{
- tor_assert(env);
- tor_assert(env);
- tor_assert(from);
- tor_assert(fromlen);
- tor_assert(to);
- tor_assert(fromlen < SIZE_T_CEILING);
-
- memcpy(to, from, fromlen);
- aes_crypt_inplace(env, to, fromlen);
- return 0;
-}
-
-/** Decrypt <b>fromlen</b> bytes from <b>from</b> using the cipher
- * <b>env</b>; on success, store the result to <b>to</b> and return 0.
- * Does not check for failure.
- */
-int
-crypto_cipher_decrypt(crypto_cipher_t *env, char *to,
- const char *from, size_t fromlen)
-{
- tor_assert(env);
- tor_assert(from);
- tor_assert(to);
- tor_assert(fromlen < SIZE_T_CEILING);
-
- memcpy(to, from, fromlen);
- aes_crypt_inplace(env, to, fromlen);
- return 0;
-}
-
-/** Encrypt <b>len</b> bytes on <b>from</b> using the cipher in <b>env</b>;
- * on success. Does not check for failure.
- */
-void
-crypto_cipher_crypt_inplace(crypto_cipher_t *env, char *buf, size_t len)
-{
- tor_assert(len < SIZE_T_CEILING);
- aes_crypt_inplace(env, buf, len);
-}
-
-/** Encrypt <b>fromlen</b> bytes (at least 1) from <b>from</b> with the key in
- * <b>key</b> to the buffer in <b>to</b> of length
- * <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> plus
- * CIPHER_IV_LEN bytes for the initialization vector. On success, return the
- * number of bytes written, on failure, return -1.
- */
-int
-crypto_cipher_encrypt_with_iv(const char *key,
- char *to, size_t tolen,
- const char *from, size_t fromlen)
-{
- crypto_cipher_t *cipher;
- tor_assert(from);
- tor_assert(to);
- tor_assert(fromlen < INT_MAX);
-
- if (fromlen < 1)
- return -1;
- if (tolen < fromlen + CIPHER_IV_LEN)
- return -1;
-
- char iv[CIPHER_IV_LEN];
- crypto_rand(iv, sizeof(iv));
- cipher = crypto_cipher_new_with_iv(key, iv);
-
- memcpy(to, iv, CIPHER_IV_LEN);
- crypto_cipher_encrypt(cipher, to+CIPHER_IV_LEN, from, fromlen);
- crypto_cipher_free(cipher);
- memwipe(iv, 0, sizeof(iv));
- return (int)(fromlen + CIPHER_IV_LEN);
-}
-
-/** Decrypt <b>fromlen</b> bytes (at least 1+CIPHER_IV_LEN) from <b>from</b>
- * with the key in <b>key</b> to the buffer in <b>to</b> of length
- * <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> minus
- * CIPHER_IV_LEN bytes for the initialization vector. On success, return the
- * number of bytes written, on failure, return -1.
- */
-int
-crypto_cipher_decrypt_with_iv(const char *key,
- char *to, size_t tolen,
- const char *from, size_t fromlen)
-{
- crypto_cipher_t *cipher;
- tor_assert(key);
- tor_assert(from);
- tor_assert(to);
- tor_assert(fromlen < INT_MAX);
-
- if (fromlen <= CIPHER_IV_LEN)
- return -1;
- if (tolen < fromlen - CIPHER_IV_LEN)
- return -1;
-
- cipher = crypto_cipher_new_with_iv(key, from);
-
- crypto_cipher_encrypt(cipher, to, from+CIPHER_IV_LEN, fromlen-CIPHER_IV_LEN);
- crypto_cipher_free(cipher);
- return (int)(fromlen - CIPHER_IV_LEN);
-}
-
-/* DH */
-
-/** Our DH 'g' parameter */
-#define DH_GENERATOR 2
-
-/** Shared P parameter for our circuit-crypto DH key exchanges. */
-static BIGNUM *dh_param_p = NULL;
-/** Shared P parameter for our TLS DH key exchanges. */
-static BIGNUM *dh_param_p_tls = NULL;
-/** Shared G parameter for our DH key exchanges. */
-static BIGNUM *dh_param_g = NULL;
-
-/** Validate a given set of Diffie-Hellman parameters. This is moderately
- * computationally expensive (milliseconds), so should only be called when
- * the DH parameters change. Returns 0 on success, * -1 on failure.
- */
-static int
-crypto_validate_dh_params(const BIGNUM *p, const BIGNUM *g)
-{
- DH *dh = NULL;
- int ret = -1;
-
- /* Copy into a temporary DH object, just so that DH_check() can be called. */
- if (!(dh = DH_new()))
- goto out;
-#ifdef OPENSSL_1_1_API
- BIGNUM *dh_p, *dh_g;
- if (!(dh_p = BN_dup(p)))
- goto out;
- if (!(dh_g = BN_dup(g)))
- goto out;
- if (!DH_set0_pqg(dh, dh_p, NULL, dh_g))
- goto out;
-#else /* !(defined(OPENSSL_1_1_API)) */
- if (!(dh->p = BN_dup(p)))
- goto out;
- if (!(dh->g = BN_dup(g)))
- goto out;
-#endif /* defined(OPENSSL_1_1_API) */
-
- /* Perform the validation. */
- int codes = 0;
- if (!DH_check(dh, &codes))
- goto out;
- if (BN_is_word(g, DH_GENERATOR_2)) {
- /* Per https://wiki.openssl.org/index.php/Diffie-Hellman_parameters
- *
- * OpenSSL checks the prime is congruent to 11 when g = 2; while the
- * IETF's primes are congruent to 23 when g = 2.
- */
- BN_ULONG residue = BN_mod_word(p, 24);
- if (residue == 11 || residue == 23)
- codes &= ~DH_NOT_SUITABLE_GENERATOR;
- }
- if (codes != 0) /* Specifics on why the params suck is irrelevant. */
- goto out;
-
- /* Things are probably not evil. */
- ret = 0;
-
- out:
- if (dh)
- DH_free(dh);
- return ret;
-}
-
-/** Set the global Diffie-Hellman generator, used for both TLS and internal
- * DH stuff.
- */
-static void
-crypto_set_dh_generator(void)
-{
- BIGNUM *generator;
- int r;
-
- if (dh_param_g)
- return;
-
- generator = BN_new();
- tor_assert(generator);
-
- r = BN_set_word(generator, DH_GENERATOR);
- tor_assert(r);
-
- dh_param_g = generator;
-}
-
-/** Set the global TLS Diffie-Hellman modulus. Use the Apache mod_ssl DH
- * modulus. */
-void
-crypto_set_tls_dh_prime(void)
-{
- BIGNUM *tls_prime = NULL;
- int r;
-
- /* If the space is occupied, free the previous TLS DH prime */
- if (BUG(dh_param_p_tls)) {
- /* LCOV_EXCL_START
- *
- * We shouldn't be calling this twice.
- */
- BN_clear_free(dh_param_p_tls);
- dh_param_p_tls = NULL;
- /* LCOV_EXCL_STOP */
- }
-
- tls_prime = BN_new();
- tor_assert(tls_prime);
-
- /* This is the 1024-bit safe prime that Apache uses for its DH stuff; see
- * modules/ssl/ssl_engine_dh.c; Apache also uses a generator of 2 with this
- * prime.
- */
- r = BN_hex2bn(&tls_prime,
- "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98"
- "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A"
- "467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7"
- "DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68"
- "B0E7393E0F24218EB3");
- tor_assert(r);
-
- tor_assert(tls_prime);
-
- dh_param_p_tls = tls_prime;
- crypto_set_dh_generator();
- tor_assert(0 == crypto_validate_dh_params(dh_param_p_tls, dh_param_g));
-}
-
-/** Initialize dh_param_p and dh_param_g if they are not already
- * set. */
-static void
-init_dh_param(void)
-{
- BIGNUM *circuit_dh_prime;
- int r;
- if (BUG(dh_param_p && dh_param_g))
- return; // LCOV_EXCL_LINE This function isn't supposed to be called twice.
-
- circuit_dh_prime = BN_new();
- tor_assert(circuit_dh_prime);
-
- /* This is from rfc2409, section 6.2. It's a safe prime, and
- supposedly it equals:
- 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }.
- */
- r = BN_hex2bn(&circuit_dh_prime,
- "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
- "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
- "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
- "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
- "49286651ECE65381FFFFFFFFFFFFFFFF");
- tor_assert(r);
-
- /* Set the new values as the global DH parameters. */
- dh_param_p = circuit_dh_prime;
- crypto_set_dh_generator();
- tor_assert(0 == crypto_validate_dh_params(dh_param_p, dh_param_g));
-
- if (!dh_param_p_tls) {
- crypto_set_tls_dh_prime();
- }
-}
-
-/** 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.
- */
-#define DH_PRIVATE_KEY_BITS 320
-
-/** Allocate and return a new DH object for a key exchange. Returns NULL on
- * failure.
- */
-crypto_dh_t *
-crypto_dh_new(int dh_type)
-{
- crypto_dh_t *res = tor_malloc_zero(sizeof(crypto_dh_t));
-
- tor_assert(dh_type == DH_TYPE_CIRCUIT || dh_type == DH_TYPE_TLS ||
- dh_type == DH_TYPE_REND);
-
- if (!dh_param_p)
- init_dh_param();
-
- if (!(res->dh = DH_new()))
- goto err;
-
-#ifdef OPENSSL_1_1_API
- BIGNUM *dh_p = NULL, *dh_g = NULL;
-
- if (dh_type == DH_TYPE_TLS) {
- dh_p = BN_dup(dh_param_p_tls);
- } else {
- dh_p = BN_dup(dh_param_p);
- }
- if (!dh_p)
- goto err;
-
- dh_g = BN_dup(dh_param_g);
- if (!dh_g) {
- BN_free(dh_p);
- goto err;
- }
-
- if (!DH_set0_pqg(res->dh, dh_p, NULL, dh_g)) {
- goto err;
- }
-
- if (!DH_set_length(res->dh, DH_PRIVATE_KEY_BITS))
- goto err;
-#else /* !(defined(OPENSSL_1_1_API)) */
- if (dh_type == DH_TYPE_TLS) {
- if (!(res->dh->p = BN_dup(dh_param_p_tls)))
- goto err;
- } else {
- if (!(res->dh->p = BN_dup(dh_param_p)))
- goto err;
- }
-
- if (!(res->dh->g = BN_dup(dh_param_g)))
- goto err;
-
- res->dh->length = DH_PRIVATE_KEY_BITS;
-#endif /* defined(OPENSSL_1_1_API) */
-
- return res;
-
- /* LCOV_EXCL_START
- * This error condition is only reached when an allocation fails */
- err:
- crypto_log_errors(LOG_WARN, "creating DH object");
- if (res->dh) DH_free(res->dh); /* frees p and g too */
- tor_free(res);
- return NULL;
- /* LCOV_EXCL_STOP */
-}
-
-/** Return a copy of <b>dh</b>, sharing its internal state. */
-crypto_dh_t *
-crypto_dh_dup(const crypto_dh_t *dh)
-{
- crypto_dh_t *dh_new = tor_malloc_zero(sizeof(crypto_dh_t));
- tor_assert(dh);
- tor_assert(dh->dh);
- dh_new->dh = dh->dh;
- DH_up_ref(dh->dh);
- return dh_new;
-}
-
-/** Return the length of the DH key in <b>dh</b>, in bytes.
- */
-int
-crypto_dh_get_bytes(crypto_dh_t *dh)
-{
- tor_assert(dh);
- return DH_size(dh->dh);
-}
-
-/** Generate \<x,g^x\> for our part of the key exchange. Return 0 on
- * success, -1 on failure.
- */
-int
-crypto_dh_generate_public(crypto_dh_t *dh)
-{
-#ifndef OPENSSL_1_1_API
- again:
-#endif
- if (!DH_generate_key(dh->dh)) {
- /* LCOV_EXCL_START
- * To test this we would need some way to tell openssl to break DH. */
- crypto_log_errors(LOG_WARN, "generating DH key");
- return -1;
- /* LCOV_EXCL_STOP */
- }
-#ifdef OPENSSL_1_1_API
- /* OpenSSL 1.1.x doesn't appear to let you regenerate a DH key, without
- * recreating the DH object. I have no idea what sort of aliasing madness
- * can occur here, so do the check, and just bail on failure.
- */
- const BIGNUM *pub_key, *priv_key;
- DH_get0_key(dh->dh, &pub_key, &priv_key);
- if (tor_check_dh_key(LOG_WARN, pub_key)<0) {
- log_warn(LD_CRYPTO, "Weird! Our own DH key was invalid. I guess once-in-"
- "the-universe chances really do happen. Treating as a failure.");
- return -1;
- }
-#else /* !(defined(OPENSSL_1_1_API)) */
- if (tor_check_dh_key(LOG_WARN, dh->dh->pub_key)<0) {
- /* LCOV_EXCL_START
- * If this happens, then openssl's DH implementation is busted. */
- log_warn(LD_CRYPTO, "Weird! Our own DH key was invalid. I guess once-in-"
- "the-universe chances really do happen. Trying again.");
- /* Free and clear the keys, so OpenSSL will actually try again. */
- BN_clear_free(dh->dh->pub_key);
- BN_clear_free(dh->dh->priv_key);
- dh->dh->pub_key = dh->dh->priv_key = NULL;
- goto again;
- /* LCOV_EXCL_STOP */
- }
-#endif /* defined(OPENSSL_1_1_API) */
- return 0;
-}
-
-/** Generate g^x as necessary, and write the g^x for the key exchange
- * as a <b>pubkey_len</b>-byte value into <b>pubkey</b>. Return 0 on
- * success, -1 on failure. <b>pubkey_len</b> must be \>= DH_BYTES.
- */
-int
-crypto_dh_get_public(crypto_dh_t *dh, char *pubkey, size_t pubkey_len)
-{
- int bytes;
- tor_assert(dh);
-
- const BIGNUM *dh_pub;
-
-#ifdef OPENSSL_1_1_API
- const BIGNUM *dh_priv;
- DH_get0_key(dh->dh, &dh_pub, &dh_priv);
-#else
- dh_pub = dh->dh->pub_key;
-#endif /* defined(OPENSSL_1_1_API) */
-
- if (!dh_pub) {
- if (crypto_dh_generate_public(dh)<0)
- return -1;
- else {
-#ifdef OPENSSL_1_1_API
- DH_get0_key(dh->dh, &dh_pub, &dh_priv);
-#else
- dh_pub = dh->dh->pub_key;
-#endif
- }
- }
-
- tor_assert(dh_pub);
- bytes = BN_num_bytes(dh_pub);
- tor_assert(bytes >= 0);
- if (pubkey_len < (size_t)bytes) {
- log_warn(LD_CRYPTO,
- "Weird! pubkey_len (%d) was smaller than DH_BYTES (%d)",
- (int) pubkey_len, bytes);
- return -1;
- }
-
- memset(pubkey, 0, pubkey_len);
- BN_bn2bin(dh_pub, (unsigned char*)(pubkey+(pubkey_len-bytes)));
-
- return 0;
-}
-
-/** Check for bad Diffie-Hellman public keys (g^x). Return 0 if the key is
- * okay (in the subgroup [2,p-2]), or -1 if it's bad.
- * See http://www.cl.cam.ac.uk/ftp/users/rja14/psandqs.ps.gz for some tips.
- */
-static int
-tor_check_dh_key(int severity, const BIGNUM *bn)
-{
- BIGNUM *x;
- char *s;
- tor_assert(bn);
- x = BN_new();
- tor_assert(x);
- if (BUG(!dh_param_p))
- init_dh_param(); //LCOV_EXCL_LINE we already checked whether we did this.
- BN_set_word(x, 1);
- if (BN_cmp(bn,x)<=0) {
- log_fn(severity, LD_CRYPTO, "DH key must be at least 2.");
- goto err;
- }
- BN_copy(x,dh_param_p);
- BN_sub_word(x, 1);
- if (BN_cmp(bn,x)>=0) {
- log_fn(severity, LD_CRYPTO, "DH key must be at most p-2.");
- goto err;
- }
- BN_clear_free(x);
- return 0;
- err:
- BN_clear_free(x);
- s = BN_bn2hex(bn);
- log_fn(severity, LD_CRYPTO, "Rejecting insecure DH key [%s]", s);
- OPENSSL_free(s);
- return -1;
-}
-
-/** Given a DH key exchange object, and our peer's value of g^y (as a
- * <b>pubkey_len</b>-byte value in <b>pubkey</b>) generate
- * <b>secret_bytes_out</b> bytes of shared key material and write them
- * to <b>secret_out</b>. Return the number of bytes generated on success,
- * or -1 on failure.
- *
- * (We generate key material by computing
- * SHA1( g^xy || "\x00" ) || SHA1( g^xy || "\x01" ) || ...
- * where || is concatenation.)
- */
-ssize_t
-crypto_dh_compute_secret(int severity, crypto_dh_t *dh,
- const char *pubkey, size_t pubkey_len,
- char *secret_out, size_t secret_bytes_out)
-{
- char *secret_tmp = NULL;
- BIGNUM *pubkey_bn = NULL;
- size_t secret_len=0, secret_tmp_len=0;
- int result=0;
- tor_assert(dh);
- tor_assert(secret_bytes_out/DIGEST_LEN <= 255);
- tor_assert(pubkey_len < INT_MAX);
-
- if (!(pubkey_bn = BN_bin2bn((const unsigned char*)pubkey,
- (int)pubkey_len, NULL)))
- goto error;
- if (tor_check_dh_key(severity, pubkey_bn)<0) {
- /* Check for invalid public keys. */
- log_fn(severity, LD_CRYPTO,"Rejected invalid g^x");
- goto error;
- }
- secret_tmp_len = crypto_dh_get_bytes(dh);
- secret_tmp = tor_malloc(secret_tmp_len);
- result = DH_compute_key((unsigned char*)secret_tmp, pubkey_bn, dh->dh);
- if (result < 0) {
- log_warn(LD_CRYPTO,"DH_compute_key() failed.");
- goto error;
- }
- secret_len = result;
- if (crypto_expand_key_material_TAP((uint8_t*)secret_tmp, secret_len,
- (uint8_t*)secret_out, secret_bytes_out)<0)
- goto error;
- secret_len = secret_bytes_out;
-
- goto done;
- error:
- result = -1;
- done:
- crypto_log_errors(LOG_WARN, "completing DH handshake");
- if (pubkey_bn)
- BN_clear_free(pubkey_bn);
- if (secret_tmp) {
- memwipe(secret_tmp, 0, secret_tmp_len);
- tor_free(secret_tmp);
- }
- if (result < 0)
- return result;
- else
- return secret_len;
-}
-
-/** Given <b>key_in_len</b> bytes of negotiated randomness in <b>key_in</b>
- * ("K"), expand it into <b>key_out_len</b> bytes of negotiated key material in
- * <b>key_out</b> by taking the first <b>key_out_len</b> bytes of
- * H(K | [00]) | H(K | [01]) | ....
- *
- * This is the key expansion algorithm used in the "TAP" circuit extension
- * mechanism; it shouldn't be used for new protocols.
- *
- * Return 0 on success, -1 on failure.
- */
-int
-crypto_expand_key_material_TAP(const uint8_t *key_in, size_t key_in_len,
- uint8_t *key_out, size_t key_out_len)
-{
- int i, r = -1;
- uint8_t *cp, *tmp = tor_malloc(key_in_len+1);
- uint8_t digest[DIGEST_LEN];
-
- /* If we try to get more than this amount of key data, we'll repeat blocks.*/
- tor_assert(key_out_len <= DIGEST_LEN*256);
-
- memcpy(tmp, key_in, key_in_len);
- for (cp = key_out, i=0; cp < key_out+key_out_len;
- ++i, cp += DIGEST_LEN) {
- tmp[key_in_len] = i;
- if (crypto_digest((char*)digest, (const char *)tmp, key_in_len+1) < 0)
- goto exit;
- memcpy(cp, digest, MIN(DIGEST_LEN, key_out_len-(cp-key_out)));
- }
-
- r = 0;
- exit:
- memwipe(tmp, 0, key_in_len+1);
- tor_free(tmp);
- memwipe(digest, 0, sizeof(digest));
- return r;
-}
-
-/** Expand some secret key material according to RFC5869, using SHA256 as the
- * underlying hash. The <b>key_in_len</b> bytes at <b>key_in</b> are the
- * secret key material; the <b>salt_in_len</b> bytes at <b>salt_in</b> and the
- * <b>info_in_len</b> bytes in <b>info_in_len</b> are the algorithm's "salt"
- * and "info" parameters respectively. On success, write <b>key_out_len</b>
- * bytes to <b>key_out</b> and return 0. Assert on failure.
- */
-int
-crypto_expand_key_material_rfc5869_sha256(
- const uint8_t *key_in, size_t key_in_len,
- const uint8_t *salt_in, size_t salt_in_len,
- const uint8_t *info_in, size_t info_in_len,
- uint8_t *key_out, size_t key_out_len)
-{
- uint8_t prk[DIGEST256_LEN];
- uint8_t tmp[DIGEST256_LEN + 128 + 1];
- uint8_t mac[DIGEST256_LEN];
- int i;
- uint8_t *outp;
- size_t tmp_len;
-
- crypto_hmac_sha256((char*)prk,
- (const char*)salt_in, salt_in_len,
- (const char*)key_in, key_in_len);
-
- /* If we try to get more than this amount of key data, we'll repeat blocks.*/
- tor_assert(key_out_len <= DIGEST256_LEN * 256);
- tor_assert(info_in_len <= 128);
- memset(tmp, 0, sizeof(tmp));
- outp = key_out;
- i = 1;
-
- while (key_out_len) {
- size_t n;
- if (i > 1) {
- memcpy(tmp, mac, DIGEST256_LEN);
- memcpy(tmp+DIGEST256_LEN, info_in, info_in_len);
- tmp[DIGEST256_LEN+info_in_len] = i;
- tmp_len = DIGEST256_LEN + info_in_len + 1;
- } else {
- memcpy(tmp, info_in, info_in_len);
- tmp[info_in_len] = i;
- tmp_len = info_in_len + 1;
- }
- crypto_hmac_sha256((char*)mac,
- (const char*)prk, DIGEST256_LEN,
- (const char*)tmp, tmp_len);
- n = key_out_len < DIGEST256_LEN ? key_out_len : DIGEST256_LEN;
- memcpy(outp, mac, n);
- key_out_len -= n;
- outp += n;
- ++i;
- }
-
- memwipe(tmp, 0, sizeof(tmp));
- memwipe(mac, 0, sizeof(mac));
- return 0;
-}
-
-/** Free a DH key exchange object.
- */
-void
-crypto_dh_free_(crypto_dh_t *dh)
-{
- if (!dh)
- return;
- tor_assert(dh->dh);
- DH_free(dh->dh);
- tor_free(dh);
-}
-
-/** @{ */
-/** Uninitialize the crypto library. Return 0 on success. Does not detect
- * failure.
- */
-int
-crypto_global_cleanup(void)
-{
-#ifndef OPENSSL_1_1_API
- EVP_cleanup();
-#endif
-#ifndef NEW_THREAD_API
- ERR_remove_thread_state(NULL);
-#endif
-#ifndef OPENSSL_1_1_API
- ERR_free_strings();
-#endif
-
- if (dh_param_p)
- BN_clear_free(dh_param_p);
- if (dh_param_p_tls)
- BN_clear_free(dh_param_p_tls);
- if (dh_param_g)
- BN_clear_free(dh_param_g);
-
- dh_param_p = dh_param_p_tls = dh_param_g = NULL;
-
-#ifndef DISABLE_ENGINES
-#ifndef OPENSSL_1_1_API
- ENGINE_cleanup();
-#endif
-#endif
-
- CONF_modules_unload(1);
-#ifndef OPENSSL_1_1_API
- CRYPTO_cleanup_all_ex_data();
-#endif
-
- crypto_openssl_free_all();
-
- crypto_early_initialized_ = 0;
- crypto_global_initialized_ = 0;
- have_seeded_siphash = 0;
- siphash_unset_global_key();
-
- return 0;
-}
-
-/** @} */
-
-#ifdef USE_DMALLOC
-/** Tell the crypto library to use Tor's allocation functions rather than
- * calling libc's allocation functions directly. Return 0 on success, -1
- * on failure. */
-int
-crypto_use_tor_alloc_functions(void)
-{
- int r = CRYPTO_set_mem_ex_functions(tor_malloc_, tor_realloc_, tor_free_);
- return r ? 0 : -1;
-}
-#endif /* defined(USE_DMALLOC) */
-
diff --git a/src/common/include.am b/src/common/include.am
deleted file mode 100644
index cfaf993674..0000000000
--- a/src/common/include.am
+++ /dev/null
@@ -1,213 +0,0 @@
-
-noinst_LIBRARIES += \
- src/common/libor.a \
- src/common/libor-ctime.a \
- src/common/libor-crypto.a \
- src/common/libor-event.a
-
-if UNITTESTS_ENABLED
-noinst_LIBRARIES += \
- src/common/libor-testing.a \
- src/common/libor-ctime-testing.a \
- src/common/libor-crypto-testing.a \
- src/common/libor-event-testing.a
-endif
-
-EXTRA_DIST += src/common/Makefile.nmake
-
-#CFLAGS = -Wall -Wpointer-arith -O2
-AM_CPPFLAGS += -I$(srcdir)/src/common -Isrc/common -I$(srcdir)/src/ext/trunnel -I$(srcdir)/src/trunnel
-
-if USE_OPENBSD_MALLOC
-libor_extra_source=src/ext/OpenBSD_malloc_Linux.c
-else
-libor_extra_source=
-endif
-
-src_common_libcurve25519_donna_a_CFLAGS=
-
-if BUILD_CURVE25519_DONNA
-src_common_libcurve25519_donna_a_SOURCES=\
- src/ext/curve25519_donna/curve25519-donna.c
-# See bug 13538 -- this code is known to have signed overflow issues.
-src_common_libcurve25519_donna_a_CFLAGS+=\
- @F_OMIT_FRAME_POINTER@ @CFLAGS_CONSTTIME@
-noinst_LIBRARIES+=src/common/libcurve25519_donna.a
-LIBDONNA=src/common/libcurve25519_donna.a
-else
-if BUILD_CURVE25519_DONNA_C64
-src_common_libcurve25519_donna_a_CFLAGS+=@CFLAGS_CONSTTIME@
-src_common_libcurve25519_donna_a_SOURCES=\
- src/ext/curve25519_donna/curve25519-donna-c64.c
-noinst_LIBRARIES+=src/common/libcurve25519_donna.a
-LIBDONNA=src/common/libcurve25519_donna.a
-else
-LIBDONNA=
-endif
-endif
-
-LIBDONNA += $(LIBED25519_REF10)
-LIBDONNA += $(LIBED25519_DONNA)
-
-if THREADS_PTHREADS
-threads_impl_source=src/common/compat_pthreads.c
-endif
-if THREADS_WIN32
-threads_impl_source=src/common/compat_winthreads.c
-endif
-
-if BUILD_READPASSPHRASE_C
-readpassphrase_source=src/ext/readpassphrase.c
-else
-readpassphrase_source=
-endif
-
-if ADD_MULODI4
-mulodi4_source=src/ext/mulodi/mulodi4.c
-else
-mulodi4_source=
-endif
-
-LIBOR_CTIME_A_SRC = \
- $(mulodi4_source) \
- src/ext/csiphash.c \
- src/common/di_ops.c
-
-src_common_libor_ctime_a_SOURCES = $(LIBOR_CTIME_A_SRC)
-if UNITTESTS_ENABLED
-src_common_libor_ctime_testing_a_SOURCES = $(LIBOR_CTIME_A_SRC)
-else
-src_common_libor_ctime_testing_a_SOURCES =
-endif
-src_common_libor_ctime_a_CFLAGS = @CFLAGS_CONSTTIME@
-src_common_libor_ctime_testing_a_CFLAGS = @CFLAGS_CONSTTIME@ $(TEST_CFLAGS)
-
-LIBOR_A_SRC = \
- src/common/address.c \
- src/common/address_set.c \
- src/common/backtrace.c \
- src/common/buffers.c \
- src/common/compat.c \
- src/common/compat_threads.c \
- src/common/compat_time.c \
- src/common/confline.c \
- src/common/container.c \
- src/common/log.c \
- src/common/memarea.c \
- src/common/pubsub.c \
- src/common/util.c \
- src/common/util_bug.c \
- src/common/util_format.c \
- src/common/util_process.c \
- src/common/sandbox.c \
- src/common/storagedir.c \
- src/common/token_bucket.c \
- src/common/workqueue.c \
- $(libor_extra_source) \
- $(threads_impl_source) \
- $(readpassphrase_source)
-
-src/common/src_common_libor_testing_a-log.$(OBJEXT) \
- src/common/log.$(OBJEXT): micro-revision.i
-
-LIBOR_CRYPTO_A_SRC = \
- src/common/aes.c \
- src/common/buffers_tls.c \
- src/common/compress.c \
- src/common/compress_lzma.c \
- src/common/compress_none.c \
- src/common/compress_zlib.c \
- src/common/compress_zstd.c \
- src/common/crypto.c \
- src/common/crypto_digest.c \
- src/common/crypto_format.c \
- src/common/crypto_openssl_mgt.c \
- src/common/crypto_pwbox.c \
- src/common/crypto_rand.c \
- src/common/crypto_rsa.c \
- src/common/crypto_s2k.c \
- src/common/crypto_util.c \
- src/common/tortls.c \
- src/common/crypto_curve25519.c \
- src/common/crypto_ed25519.c
-
-LIBOR_EVENT_A_SRC = \
- src/common/compat_libevent.c \
- src/common/procmon.c \
- src/common/timers.c \
- src/ext/timeouts/timeout.c
-
-src_common_libor_a_SOURCES = $(LIBOR_A_SRC)
-src_common_libor_crypto_a_SOURCES = $(LIBOR_CRYPTO_A_SRC)
-src_common_libor_event_a_SOURCES = $(LIBOR_EVENT_A_SRC)
-
-if UNITTESTS_ENABLED
-src_common_libor_testing_a_SOURCES = $(LIBOR_A_SRC)
-src_common_libor_crypto_testing_a_SOURCES = $(LIBOR_CRYPTO_A_SRC)
-src_common_libor_event_testing_a_SOURCES = $(LIBOR_EVENT_A_SRC)
-else
-src_common_libor_testing_a_SOURCES =
-src_common_libor_crypto_testing_a_SOURCES =
-src_common_libor_event_testing_a_SOURCES =
-endif
-
-src_common_libor_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
-src_common_libor_crypto_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
-src_common_libor_event_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
-src_common_libor_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
-src_common_libor_crypto_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
-src_common_libor_event_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
-
-COMMONHEADERS = \
- src/common/address.h \
- src/common/address_set.h \
- src/common/backtrace.h \
- src/common/buffers.h \
- src/common/buffers_tls.h \
- src/common/aes.h \
- src/common/ciphers.inc \
- src/common/compat.h \
- src/common/compat_libevent.h \
- src/common/compat_openssl.h \
- src/common/compat_threads.h \
- src/common/compat_time.h \
- src/common/compress.h \
- src/common/compress_lzma.h \
- src/common/compress_none.h \
- src/common/compress_zlib.h \
- src/common/compress_zstd.h \
- src/common/confline.h \
- src/common/container.h \
- src/common/crypto.h \
- src/common/crypto_digest.h \
- src/common/crypto_curve25519.h \
- src/common/crypto_ed25519.h \
- src/common/crypto_format.h \
- src/common/crypto_openssl_mgt.h \
- src/common/crypto_pwbox.h \
- src/common/crypto_rand.h \
- src/common/crypto_rsa.h \
- src/common/crypto_s2k.h \
- src/common/crypto_util.h \
- src/common/di_ops.h \
- src/common/handles.h \
- src/common/memarea.h \
- src/common/linux_syscalls.inc \
- src/common/procmon.h \
- src/common/pubsub.h \
- src/common/sandbox.h \
- src/common/storagedir.h \
- src/common/testsupport.h \
- src/common/timers.h \
- src/common/token_bucket.h \
- src/common/torint.h \
- src/common/torlog.h \
- src/common/tortls.h \
- src/common/util.h \
- src/common/util_bug.h \
- src/common/util_format.h \
- src/common/util_process.h \
- src/common/workqueue.h
-
-noinst_HEADERS+= $(COMMONHEADERS)
-
diff --git a/src/common/pubsub.c b/src/common/pubsub.c
deleted file mode 100644
index 336e8a6e7f..0000000000
--- a/src/common/pubsub.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file pubsub.c
- *
- * \brief DOCDOC
- */
-
-#include "orconfig.h"
-#include "pubsub.h"
-#include "container.h"
-
-/** Helper: insert <b>s</b> into <b>topic's</b> list of subscribers, keeping
- * them sorted in priority order. */
-static void
-subscriber_insert(pubsub_topic_t *topic, pubsub_subscriber_t *s)
-{
- int i;
- smartlist_t *sl = topic->subscribers;
- for (i = 0; i < smartlist_len(sl); ++i) {
- pubsub_subscriber_t *other = smartlist_get(sl, i);
- if (s->priority < other->priority) {
- break;
- }
- }
- smartlist_insert(sl, i, s);
-}
-
-/**
- * Add a new subscriber to <b>topic</b>, where (when an event is triggered),
- * we'll notify the function <b>fn</b> by passing it <b>subscriber_data</b>.
- * Return a handle to the subscribe which can later be passed to
- * pubsub_unsubscribe_().
- *
- * Functions are called in priority order, from lowest to highest.
- *
- * See pubsub.h for <b>subscribe_flags</b>.
- */
-const pubsub_subscriber_t *
-pubsub_subscribe_(pubsub_topic_t *topic,
- pubsub_subscriber_fn_t fn,
- void *subscriber_data,
- unsigned subscribe_flags,
- unsigned priority)
-{
- tor_assert(! topic->locked);
- if (subscribe_flags & SUBSCRIBE_ATSTART) {
- tor_assert(topic->n_events_fired == 0);
- }
- pubsub_subscriber_t *r = tor_malloc_zero(sizeof(*r));
- r->priority = priority;
- r->subscriber_flags = subscribe_flags;
- r->fn = fn;
- r->subscriber_data = subscriber_data;
- if (topic->subscribers == NULL) {
- topic->subscribers = smartlist_new();
- }
- subscriber_insert(topic, r);
- return r;
-}
-
-/**
- * Remove the subscriber <b>s</b> from <b>topic</b>. After calling this
- * function, <b>s</b> may no longer be used.
- */
-int
-pubsub_unsubscribe_(pubsub_topic_t *topic,
- const pubsub_subscriber_t *s)
-{
- tor_assert(! topic->locked);
- smartlist_t *sl = topic->subscribers;
- if (sl == NULL)
- return -1;
- int i = smartlist_pos(sl, s);
- if (i == -1)
- return -1;
- pubsub_subscriber_t *tmp = smartlist_get(sl, i);
- tor_assert(tmp == s);
- smartlist_del_keeporder(sl, i);
- tor_free(tmp);
- return 0;
-}
-
-/**
- * For every subscriber s in <b>topic</b>, invoke notify_fn on s and
- * event_data. Return 0 if there were no nonzero return values, and -1 if
- * there were any.
- */
-int
-pubsub_notify_(pubsub_topic_t *topic, pubsub_notify_fn_t notify_fn,
- void *event_data, unsigned notify_flags)
-{
- tor_assert(! topic->locked);
- (void) notify_flags;
- smartlist_t *sl = topic->subscribers;
- int n_bad = 0;
- ++topic->n_events_fired;
- if (sl == NULL)
- return -1;
- topic->locked = 1;
- SMARTLIST_FOREACH_BEGIN(sl, pubsub_subscriber_t *, s) {
- int r = notify_fn(s, event_data);
- if (r != 0)
- ++n_bad;
- } SMARTLIST_FOREACH_END(s);
- topic->locked = 0;
- return (n_bad == 0) ? 0 : -1;
-}
-
-/**
- * Release all storage held by <b>topic</b>.
- */
-void
-pubsub_clear_(pubsub_topic_t *topic)
-{
- tor_assert(! topic->locked);
-
- smartlist_t *sl = topic->subscribers;
- if (sl == NULL)
- return;
- SMARTLIST_FOREACH_BEGIN(sl, pubsub_subscriber_t *, s) {
- tor_free(s);
- } SMARTLIST_FOREACH_END(s);
- smartlist_free(sl);
- topic->subscribers = NULL;
- topic->n_events_fired = 0;
-}
-
diff --git a/src/common/pubsub.h b/src/common/pubsub.h
deleted file mode 100644
index 2bee3af085..0000000000
--- a/src/common/pubsub.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file pubsub.h
- * \brief Macros to implement publish/subscribe abstractions.
- *
- * To use these macros, call DECLARE_PUBSUB_TOPIC() with an identifier to use
- * as your topic. Below, I'm going to assume you say DECLARE_PUBSUB_TOPIC(T).
- *
- * Doing this will declare the following types:
- * typedef struct T_event_data_t T_event_data_t; // you define this struct
- * typedef struct T_subscriber_data_t T_subscriber_data_t; // this one too.
- * typedef struct T_subscriber_t T_subscriber_t; // opaque
- * typedef int (*T_subscriber_fn_t)(T_event_data_t*, T_subscriber_data_t*);
- *
- * and it will declare the following functions:
- * const T_subscriber_t *T_subscribe(T_subscriber_fn_t,
- * T_subscriber_data_t *,
- * unsigned flags,
- * unsigned priority);
- * int T_unsubscribe(const T_subscriber_t *)
- *
- * Elsewhere you can say DECLARE_NOTIFY_PUBSUB_TOPIC(static, T), which
- * declares:
- *
- * static int T_notify(T_event_data_t *, unsigned notify_flags);
- * static void T_clear(void);
- *
- * And in some C file, you would define these functions with:
- * IMPLEMENT_PUBSUB_TOPIC(static, T).
- *
- * The implementations will be small typesafe wrappers over generic versions
- * of the above functions.
- *
- * To use the typesafe functions, you add any number of subscribers with
- * T_subscribe(). Each has an associated function pointer, data pointer,
- * and priority. Later, you can invoke T_notify() to declare that the
- * event has occurred. Each of the subscribers will be invoked once.
- **/
-
-#ifndef TOR_PUBSUB_H
-#define TOR_PUBSUB_H
-
-#include "torint.h"
-
-/**
- * Flag for T_subscribe: die with an assertion failure if the event
- * have ever been published before. Used when a subscriber must absolutely
- * never have missed an event.
- */
-#define SUBSCRIBE_ATSTART (1u<<0)
-
-#define DECLARE_PUBSUB_STRUCT_TYPES(name) \
- /* You define this type. */ \
- typedef struct name ## _event_data_t name ## _event_data_t; \
- /* You define this type. */ \
- typedef struct name ## _subscriber_data_t name ## _subscriber_data_t;
-
-#define DECLARE_PUBSUB_TOPIC(name) \
- /* This type is opaque. */ \
- typedef struct name ## _subscriber_t name ## _subscriber_t; \
- /* You declare functions matching this type. */ \
- typedef int (*name ## _subscriber_fn_t)( \
- name ## _event_data_t *data, \
- name ## _subscriber_data_t *extra); \
- /* Call this function to subscribe to a topic. */ \
- const name ## _subscriber_t *name ## _subscribe( \
- name##_subscriber_fn_t subscriber, \
- name##_subscriber_data_t *extra_data, \
- unsigned flags, \
- unsigned priority); \
- /* Call this function to unsubscribe from a topic. */ \
- int name ## _unsubscribe(const name##_subscriber_t *s);
-
-#define DECLARE_NOTIFY_PUBSUB_TOPIC(linkage, name) \
- /* Call this function to notify all subscribers. Flags not yet used. */ \
- linkage int name ## _notify(name ## _event_data_t *data, unsigned flags); \
- /* Call this function to release storage held by the topic. */ \
- linkage void name ## _clear(void);
-
-/**
- * Type used to hold a generic function for a subscriber.
- *
- * [Yes, it is safe to cast to this, so long as we cast back to the original
- * type before calling. From C99: "A pointer to a function of one type may be
- * converted to a pointer to a function of another type and back again; the
- * result shall compare equal to the original pointer."]
-*/
-typedef int (*pubsub_subscriber_fn_t)(void *, void *);
-
-/**
- * Helper type to implement pubsub abstraction. Don't use this directly.
- * It represents a subscriber.
- */
-typedef struct pubsub_subscriber_t {
- /** Function to invoke when the event triggers. */
- pubsub_subscriber_fn_t fn;
- /** Data associated with this subscriber. */
- void *subscriber_data;
- /** Priority for this subscriber. Low priorities happen first. */
- unsigned priority;
- /** Flags set on this subscriber. Not yet used.*/
- unsigned subscriber_flags;
-} pubsub_subscriber_t;
-
-/**
- * Helper type to implement pubsub abstraction. Don't use this directly.
- * It represents a topic, and keeps a record of subscribers.
- */
-typedef struct pubsub_topic_t {
- /** List of subscribers to this topic. May be NULL. */
- struct smartlist_t *subscribers;
- /** Total number of times that pubsub_notify_() has ever been called on this
- * topic. */
- uint64_t n_events_fired;
- /** True iff we're running 'notify' on this topic, and shouldn't allow
- * any concurrent modifications or events. */
- unsigned locked;
-} pubsub_topic_t;
-
-const pubsub_subscriber_t *pubsub_subscribe_(pubsub_topic_t *topic,
- pubsub_subscriber_fn_t fn,
- void *subscriber_data,
- unsigned subscribe_flags,
- unsigned priority);
-int pubsub_unsubscribe_(pubsub_topic_t *topic, const pubsub_subscriber_t *sub);
-void pubsub_clear_(pubsub_topic_t *topic);
-typedef int (*pubsub_notify_fn_t)(pubsub_subscriber_t *subscriber,
- void *notify_data);
-int pubsub_notify_(pubsub_topic_t *topic, pubsub_notify_fn_t notify_fn,
- void *notify_data, unsigned notify_flags);
-
-#define IMPLEMENT_PUBSUB_TOPIC(notify_linkage, name) \
- static pubsub_topic_t name ## _topic_ = { NULL, 0, 0 }; \
- const name ## _subscriber_t * \
- name ## _subscribe(name##_subscriber_fn_t subscriber, \
- name##_subscriber_data_t *extra_data, \
- unsigned flags, \
- unsigned priority) \
- { \
- const pubsub_subscriber_t *s; \
- s = pubsub_subscribe_(&name##_topic_, \
- (pubsub_subscriber_fn_t)subscriber, \
- extra_data, \
- flags, \
- priority); \
- return (const name##_subscriber_t *)s; \
- } \
- int \
- name ## _unsubscribe(const name##_subscriber_t *subscriber) \
- { \
- return pubsub_unsubscribe_(&name##_topic_, \
- (const pubsub_subscriber_t *)subscriber); \
- } \
- static int \
- name##_call_the_notify_fn_(pubsub_subscriber_t *subscriber, \
- void *notify_data) \
- { \
- name ## _subscriber_fn_t fn; \
- fn = (name ## _subscriber_fn_t) subscriber->fn; \
- return fn(notify_data, subscriber->subscriber_data); \
- } \
- notify_linkage int \
- name ## _notify(name ## _event_data_t *event_data, unsigned flags) \
- { \
- return pubsub_notify_(&name##_topic_, \
- name##_call_the_notify_fn_, \
- event_data, \
- flags); \
- } \
- notify_linkage void \
- name ## _clear(void) \
- { \
- pubsub_clear_(&name##_topic_); \
- }
-
-#endif /* !defined(TOR_PUBSUB_H) */
-
diff --git a/src/common/torint.h b/src/common/torint.h
deleted file mode 100644
index fc7818fe2c..0000000000
--- a/src/common/torint.h
+++ /dev/null
@@ -1,379 +0,0 @@
-/* Copyright (c) 2003, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file torint.h
- * \brief Header file to define uint32_t and friends
- **/
-
-#ifndef TOR_TORINT_H
-#define TOR_TORINT_H
-
-#include "orconfig.h"
-
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#ifdef HAVE_SYS_LIMITS_H
-#include <sys/limits.h>
-#endif
-#ifdef HAVE_MACHINE_LIMITS_H
-#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
- /* FreeBSD has a bug where it complains that this file is obsolete,
- and I should migrate to using sys/limits. It complains even when
- I include both.
- __FreeBSD_kernel__ is defined by Debian GNU/kFreeBSD which
- does the same thing (but doesn't defined __FreeBSD__).
- */
-#include <machine/limits.h>
-#endif /* !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) */
-#endif /* defined(HAVE_MACHINE_LIMITS_H) */
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-
-#include <stdbool.h>
-
-#if (SIZEOF_INT8_T != 0)
-#define HAVE_INT8_T
-#endif
-#if (SIZEOF_INT16_T != 0)
-#define HAVE_INT16_T
-#endif
-#if (SIZEOF_INT32_T != 0)
-#define HAVE_INT32_T
-#endif
-#if (SIZEOF_INT64_T != 0)
-#define HAVE_INT64_T
-#endif
-#if (SIZEOF_UINT8_T != 0)
-#define HAVE_UINT8_T
-#endif
-#if (SIZEOF_UINT16_T != 0)
-#define HAVE_UINT16_T
-#endif
-#if (SIZEOF_UINT32_T != 0)
-#define HAVE_UINT32_T
-#endif
-#if (SIZEOF_UINT64_T != 0)
-#define HAVE_UINT64_T
-#endif
-#if (SIZEOF_INTPTR_T != 0)
-#define HAVE_INTPTR_T
-#endif
-#if (SIZEOF_UINTPTR_T != 0)
-#define HAVE_UINTPTR_T
-#endif
-
-#if (SIZEOF_CHAR == 1)
-#ifndef HAVE_INT8_T
-typedef signed char int8_t;
-#define HAVE_INT8_T
-#endif
-#ifndef HAVE_UINT8_T
-typedef unsigned char uint8_t;
-#define HAVE_UINT8_T
-#endif
-#endif /* (SIZEOF_CHAR == 1) */
-
-#if (SIZEOF_SHORT == 2)
-#ifndef HAVE_INT16_T
-typedef signed short int16_t;
-#define HAVE_INT16_T
-#endif
-#ifndef HAVE_UINT16_T
-typedef unsigned short uint16_t;
-#define HAVE_UINT16_T
-#endif
-#endif /* (SIZEOF_SHORT == 2) */
-
-#if (SIZEOF_INT == 2)
-#ifndef HAVE_INT16_T
-typedef signed int int16_t;
-#define HAVE_INT16_T
-#endif
-#ifndef HAVE_UINT16_T
-typedef unsigned int uint16_t;
-#define HAVE_UINT16_T
-#endif
-#elif (SIZEOF_INT == 4)
-#ifndef HAVE_INT32_T
-typedef signed int int32_t;
-#define HAVE_INT32_T
-#endif
-#ifndef HAVE_UINT32_T
-typedef unsigned int uint32_t;
-#define HAVE_UINT32_T
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX 0xffffu
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX 0x7fff
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN (-INT16_MAX-1)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX 0xffffffffu
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX 0x7fffffff
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN (-2147483647-1)
-#endif
-#endif /* (SIZEOF_INT == 2) || ... */
-
-#if (SIZEOF_LONG == 4)
-#ifndef HAVE_INT32_T
-typedef signed long int32_t;
-#define HAVE_INT32_T
-#endif
-#ifndef HAVE_UINT32_T
-typedef unsigned long uint32_t;
-#define HAVE_UINT32_T
-#ifndef UINT32_MAX
-#define UINT32_MAX 0xfffffffful
-#endif
-#endif /* !defined(HAVE_UINT32_T) */
-#elif (SIZEOF_LONG == 8)
-#ifndef HAVE_INT64_T
-typedef signed long int64_t;
-#define HAVE_INT64_T
-#endif
-#ifndef HAVE_UINT32_T
-typedef unsigned long uint64_t;
-#define HAVE_UINT32_T
-#endif
-#ifndef UINT64_MAX
-#define UINT64_MAX 0xfffffffffffffffful
-#endif
-#endif /* (SIZEOF_LONG == 4) || ... */
-
-#if (SIZEOF_LONG_LONG == 8)
-#ifndef HAVE_INT64_T
-typedef signed long long int64_t;
-#define HAVE_INT64_T
-#endif
-#ifndef HAVE_UINT64_T
-typedef unsigned long long uint64_t;
-#define HAVE_UINT64_T
-#endif
-#ifndef UINT64_MAX
-#define UINT64_MAX 0xffffffffffffffffull
-#endif
-#ifndef INT64_MAX
-#define INT64_MAX 0x7fffffffffffffffll
-#endif
-#endif /* (SIZEOF_LONG_LONG == 8) */
-
-#if (SIZEOF___INT64 == 8)
-#ifndef HAVE_INT64_T
-typedef signed __int64 int64_t;
-#define HAVE_INT64_T
-#endif
-#ifndef HAVE_UINT64_T
-typedef unsigned __int64 uint64_t;
-#define HAVE_UINT64_T
-#endif
-#ifndef UINT64_MAX
-#define UINT64_MAX 0xffffffffffffffffui64
-#endif
-#ifndef INT64_MAX
-#define INT64_MAX 0x7fffffffffffffffi64
-#endif
-#endif /* (SIZEOF___INT64 == 8) */
-
-#ifndef INT64_MIN
-#define INT64_MIN ((- INT64_MAX) - 1)
-#endif
-
-#ifndef SIZE_MAX
-#if SIZEOF_SIZE_T == 8
-#define SIZE_MAX UINT64_MAX
-#elif SIZEOF_SIZE_T == 4
-#define SIZE_MAX UINT32_MAX
-#else
-#error "Can't define SIZE_MAX"
-#endif /* SIZEOF_SIZE_T == 8 || ... */
-#endif /* !defined(SIZE_MAX) */
-
-#ifndef HAVE_SSIZE_T
-#if SIZEOF_SIZE_T == 8
-typedef int64_t ssize_t;
-#elif SIZEOF_SIZE_T == 4
-typedef int32_t ssize_t;
-#else
-#error "Can't define ssize_t."
-#endif /* SIZEOF_SIZE_T == 8 || ... */
-#endif /* !defined(HAVE_SSIZE_T) */
-
-#if (SIZEOF_VOID_P > 4 && SIZEOF_VOID_P <= 8)
-#ifndef HAVE_INTPTR_T
-typedef int64_t intptr_t;
-#define SIZEOF_INTPTR_T 8
-#endif
-#ifndef HAVE_UINTPTR_T
-typedef uint64_t uintptr_t;
-#define SIZEOF_UINTPTR_T 8
-#endif
-#elif (SIZEOF_VOID_P > 2 && SIZEOF_VOID_P <= 4)
-#ifndef HAVE_INTPTR_T
-typedef int32_t intptr_t;
-#define SIZEOF_INTPTR_T 4
-#endif
-#ifndef HAVE_UINTPTR_T
-typedef uint32_t uintptr_t;
-#define SIZEOF_UINTPTR_T 4
-#endif
-#else
-#error "void * is either >8 bytes or <= 2. In either case, I am confused."
-#endif /* (SIZEOF_VOID_P > 4 && SIZEOF_VOID_P <= 8) || ... */
-
-#ifndef HAVE_INT8_T
-#error "Missing type int8_t"
-#endif
-#ifndef HAVE_UINT8_T
-#error "Missing type uint8_t"
-#endif
-#ifndef HAVE_INT16_T
-#error "Missing type int16_t"
-#endif
-#ifndef HAVE_UINT16_T
-#error "Missing type uint16_t"
-#endif
-#ifndef HAVE_INT32_T
-#error "Missing type int32_t"
-#endif
-#ifndef HAVE_UINT32_T
-#error "Missing type uint32_t"
-#endif
-#ifndef HAVE_INT64_T
-#error "Missing type int64_t"
-#endif
-#ifndef HAVE_UINT64_T
-#error "Missing type uint64_t"
-#endif
-
-/* This assumes a sane (2's-complement) representation. But if you
- * aren't 2's complement, and you don't define LONG_MAX, then you're so
- * bizarre that I want nothing to do with you. */
-#ifndef USING_TWOS_COMPLEMENT
-#error "Seems that your platform doesn't use 2's complement arithmetic. Argh."
-#endif
-#ifndef LONG_MAX
-#if (SIZEOF_LONG == 4)
-#define LONG_MAX 0x7fffffffL
-#elif (SIZEOF_LONG == 8)
-#define LONG_MAX 0x7fffffffffffffffL
-#else
-#error "Can't define LONG_MAX"
-#endif /* (SIZEOF_LONG == 4) || ... */
-#endif /* !defined(LONG_MAX) */
-
-#ifndef INT_MAX
-#if (SIZEOF_INT == 4)
-#define INT_MAX 0x7fffffffL
-#elif (SIZEOF_INT == 8)
-#define INT_MAX 0x7fffffffffffffffL
-#else
-#error "Can't define INT_MAX"
-#endif /* (SIZEOF_INT == 4) || ... */
-#endif /* !defined(INT_MAX) */
-
-#ifndef UINT_MAX
-#if (SIZEOF_INT == 2)
-#define UINT_MAX 0xffffu
-#elif (SIZEOF_INT == 4)
-#define UINT_MAX 0xffffffffu
-#elif (SIZEOF_INT == 8)
-#define UINT_MAX 0xffffffffffffffffu
-#else
-#error "Can't define UINT_MAX"
-#endif /* (SIZEOF_INT == 2) || ... */
-#endif /* !defined(UINT_MAX) */
-
-#ifndef SHORT_MAX
-#if (SIZEOF_SHORT == 2)
-#define SHORT_MAX 0x7fff
-#elif (SIZEOF_SHORT == 4)
-#define SHORT_MAX 0x7fffffff
-#else
-#error "Can't define SHORT_MAX"
-#endif /* (SIZEOF_SHORT == 2) || ... */
-#endif /* !defined(SHORT_MAX) */
-
-#ifndef TIME_MAX
-
-#if (SIZEOF_TIME_T == SIZEOF_INT)
-#define TIME_MAX ((time_t)INT_MAX)
-#elif (SIZEOF_TIME_T == SIZEOF_LONG)
-#define TIME_MAX ((time_t)LONG_MAX)
-#elif (SIZEOF_TIME_T == 8)
-#define TIME_MAX ((time_t)INT64_MAX)
-#else
-#error "Can't define TIME_MAX"
-#endif /* (SIZEOF_TIME_T == SIZEOF_INT) || ... */
-
-#endif /* !defined(TIME_MAX) */
-
-#ifndef TIME_MIN
-
-#if (SIZEOF_TIME_T == SIZEOF_INT)
-#define TIME_MIN ((time_t)INT_MIN)
-#elif (SIZEOF_TIME_T == SIZEOF_LONG)
-#define TIME_MIN ((time_t)LONG_MIN)
-#elif (SIZEOF_TIME_T == 8)
-#define TIME_MIN ((time_t)INT64_MIN)
-#else
-#error "Can't define TIME_MIN"
-#endif /* (SIZEOF_TIME_T == SIZEOF_INT) || ... */
-
-#endif /* !defined(TIME_MIN) */
-
-#ifndef SIZE_MAX
-#if (SIZEOF_SIZE_T == 4)
-#define SIZE_MAX UINT32_MAX
-#elif (SIZEOF_SIZE_T == 8)
-#define SIZE_MAX UINT64_MAX
-#else
-#error "Can't define SIZE_MAX"
-#endif /* (SIZEOF_SIZE_T == 4) || ... */
-#endif /* !defined(SIZE_MAX) */
-
-#ifdef _WIN32
-# ifdef _WIN64
-# define TOR_PRIuSZ PRIu64
-# else
-# define TOR_PRIuSZ PRIu32
-# endif
-#else
-# define TOR_PRIuSZ "zu"
-#endif
-
-#ifndef SSIZE_MAX
-#if (SIZEOF_SIZE_T == 4)
-#define SSIZE_MAX INT32_MAX
-#elif (SIZEOF_SIZE_T == 8)
-#define SSIZE_MAX INT64_MAX
-#else
-#error "Can't define SSIZE_MAX"
-#endif /* (SIZEOF_SIZE_T == 4) || ... */
-#endif /* !defined(SSIZE_MAX) */
-
-/** Any ssize_t larger than this amount is likely to be an underflow. */
-#define SSIZE_T_CEILING ((ssize_t)(SSIZE_MAX-16))
-/** Any size_t larger than this amount is likely to be an underflow. */
-#define SIZE_T_CEILING ((size_t)(SSIZE_MAX-16))
-
-#endif /* !defined(TOR_TORINT_H) */
-
diff --git a/src/common/util.c b/src/common/util.c
deleted file mode 100644
index dece5877f1..0000000000
--- a/src/common/util.c
+++ /dev/null
@@ -1,5378 +0,0 @@
-/* Copyright (c) 2003, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file util.c
- * \brief Common functions for strings, IO, network, data structures,
- * process control.
- **/
-
-#include "orconfig.h"
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#define UTIL_PRIVATE
-#include "util.h"
-#include "torlog.h"
-#include "crypto_digest.h"
-#include "torint.h"
-#include "container.h"
-#include "address.h"
-#include "sandbox.h"
-#include "backtrace.h"
-#include "util_process.h"
-#include "util_format.h"
-
-#ifdef _WIN32
-#include <io.h>
-#include <direct.h>
-#include <process.h>
-#include <tchar.h>
-#include <winbase.h>
-#else /* !(defined(_WIN32)) */
-#include <dirent.h>
-#include <pwd.h>
-#include <grp.h>
-#endif /* defined(_WIN32) */
-
-/* math.h needs this on Linux */
-#ifndef _USE_ISOC99_
-#define _USE_ISOC99_ 1
-#endif
-#include <math.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <signal.h>
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_FCNTL_H
-#include <sys/fcntl.h>
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-#ifdef HAVE_MALLOC_MALLOC_H
-#include <malloc/malloc.h>
-#endif
-#ifdef HAVE_MALLOC_H
-#if !defined(OpenBSD) && !defined(__FreeBSD__)
-/* OpenBSD has a malloc.h, but for our purposes, it only exists in order to
- * scold us for being so stupid as to autodetect its presence. To be fair,
- * they've done this since 1996, when autoconf was only 5 years old. */
-#include <malloc.h>
-#endif /* !defined(OpenBSD) && !defined(__FreeBSD__) */
-#endif /* defined(HAVE_MALLOC_H) */
-#ifdef HAVE_MALLOC_NP_H
-#include <malloc_np.h>
-#endif
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-#if defined(HAVE_SYS_PRCTL_H) && defined(__linux__)
-#include <sys/prctl.h>
-#endif
-
-#ifdef __clang_analyzer__
-#undef MALLOC_ZERO_WORKS
-#endif
-
-/* =====
- * Memory management
- * ===== */
-#ifdef USE_DMALLOC
- #undef strndup
- #include <dmalloc.h>
- /* Macro to pass the extra dmalloc args to another function. */
- #define DMALLOC_FN_ARGS , file, line
-
- #if defined(HAVE_DMALLOC_STRDUP)
- /* the dmalloc_strdup should be fine as defined */
- #elif defined(HAVE_DMALLOC_STRNDUP)
- #define dmalloc_strdup(file, line, string, xalloc_b) \
- dmalloc_strndup(file, line, (string), -1, xalloc_b)
- #else
- #error "No dmalloc_strdup or equivalent"
-#endif /* defined(HAVE_DMALLOC_STRDUP) || ... */
-
-#else /* !(defined(USE_DMALLOC)) */
-
- #define DMALLOC_FN_ARGS
-#endif /* defined(USE_DMALLOC) */
-
-/** Allocate a chunk of <b>size</b> bytes of memory, and return a pointer to
- * result. On error, log and terminate the process. (Same as malloc(size),
- * but never returns NULL.)
- *
- * <b>file</b> and <b>line</b> are used if dmalloc is enabled, and
- * ignored otherwise.
- */
-void *
-tor_malloc_(size_t size DMALLOC_PARAMS)
-{
- void *result;
-
- tor_assert(size < SIZE_T_CEILING);
-
-#ifndef MALLOC_ZERO_WORKS
- /* Some libc mallocs don't work when size==0. Override them. */
- if (size==0) {
- size=1;
- }
-#endif /* !defined(MALLOC_ZERO_WORKS) */
-
-#ifdef USE_DMALLOC
- result = dmalloc_malloc(file, line, size, DMALLOC_FUNC_MALLOC, 0, 0);
-#else
- result = raw_malloc(size);
-#endif
-
- if (PREDICT_UNLIKELY(result == NULL)) {
- /* LCOV_EXCL_START */
- log_err(LD_MM,"Out of memory on malloc(). Dying.");
- /* If these functions die within a worker process, they won't call
- * spawn_exit, but that's ok, since the parent will run out of memory soon
- * anyway. */
- exit(1); // exit ok: alloc failed.
- /* LCOV_EXCL_STOP */
- }
- return result;
-}
-
-/** Allocate a chunk of <b>size</b> bytes of memory, fill the memory with
- * zero bytes, and return a pointer to the result. Log and terminate
- * the process on error. (Same as calloc(size,1), but never returns NULL.)
- */
-void *
-tor_malloc_zero_(size_t size DMALLOC_PARAMS)
-{
- /* You may ask yourself, "wouldn't it be smart to use calloc instead of
- * malloc+memset? Perhaps libc's calloc knows some nifty optimization trick
- * we don't!" Indeed it does, but its optimizations are only a big win when
- * we're allocating something very big (it knows if it just got the memory
- * from the OS in a pre-zeroed state). We don't want to use tor_malloc_zero
- * for big stuff, so we don't bother with calloc. */
- void *result = tor_malloc_(size DMALLOC_FN_ARGS);
- memset(result, 0, size);
- return result;
-}
-
-/* The square root of SIZE_MAX + 1. If a is less than this, and b is less
- * than this, then a*b is less than SIZE_MAX. (For example, if size_t is
- * 32 bits, then SIZE_MAX is 0xffffffff and this value is 0x10000. If a and
- * b are less than this, then their product is at most (65535*65535) ==
- * 0xfffe0001. */
-#define SQRT_SIZE_MAX_P1 (((size_t)1) << (sizeof(size_t)*4))
-
-/** Return non-zero if and only if the product of the arguments is exact,
- * and cannot overflow. */
-int
-size_mul_check(const size_t x, const size_t y)
-{
- /* This first check is equivalent to
- (x < SQRT_SIZE_MAX_P1 && y < SQRT_SIZE_MAX_P1)
-
- Rationale: if either one of x or y is >= SQRT_SIZE_MAX_P1, then it
- will have some bit set in its most significant half.
- */
- return ((x|y) < SQRT_SIZE_MAX_P1 ||
- y == 0 ||
- x <= SIZE_MAX / y);
-}
-
-/** Allocate a chunk of <b>nmemb</b>*<b>size</b> bytes of memory, fill
- * the memory with zero bytes, and return a pointer to the result.
- * Log and terminate the process on error. (Same as
- * calloc(<b>nmemb</b>,<b>size</b>), but never returns NULL.)
- * The second argument (<b>size</b>) should preferably be non-zero
- * and a compile-time constant.
- */
-void *
-tor_calloc_(size_t nmemb, size_t size DMALLOC_PARAMS)
-{
- tor_assert(size_mul_check(nmemb, size));
- return tor_malloc_zero_((nmemb * size) DMALLOC_FN_ARGS);
-}
-
-/** Change the size of the memory block pointed to by <b>ptr</b> to <b>size</b>
- * bytes long; return the new memory block. On error, log and
- * terminate. (Like realloc(ptr,size), but never returns NULL.)
- */
-void *
-tor_realloc_(void *ptr, size_t size DMALLOC_PARAMS)
-{
- void *result;
-
- tor_assert(size < SIZE_T_CEILING);
-
-#ifndef MALLOC_ZERO_WORKS
- /* Some libc mallocs don't work when size==0. Override them. */
- if (size==0) {
- size=1;
- }
-#endif /* !defined(MALLOC_ZERO_WORKS) */
-
-#ifdef USE_DMALLOC
- result = dmalloc_realloc(file, line, ptr, size, DMALLOC_FUNC_REALLOC, 0);
-#else
- result = raw_realloc(ptr, size);
-#endif
-
- if (PREDICT_UNLIKELY(result == NULL)) {
- /* LCOV_EXCL_START */
- log_err(LD_MM,"Out of memory on realloc(). Dying.");
- exit(1); // exit ok: alloc failed.
- /* LCOV_EXCL_STOP */
- }
- return result;
-}
-
-/**
- * Try to realloc <b>ptr</b> so that it takes up sz1 * sz2 bytes. Check for
- * overflow. Unlike other allocation functions, return NULL on overflow.
- */
-void *
-tor_reallocarray_(void *ptr, size_t sz1, size_t sz2 DMALLOC_PARAMS)
-{
- /* XXXX we can make this return 0, but we would need to check all the
- * reallocarray users. */
- tor_assert(size_mul_check(sz1, sz2));
-
- return tor_realloc(ptr, (sz1 * sz2) DMALLOC_FN_ARGS);
-}
-
-/** Return a newly allocated copy of the NUL-terminated string s. On
- * error, log and terminate. (Like strdup(s), but never returns
- * NULL.)
- */
-char *
-tor_strdup_(const char *s DMALLOC_PARAMS)
-{
- char *duplicate;
- tor_assert(s);
-
-#ifdef USE_DMALLOC
- duplicate = dmalloc_strdup(file, line, s, 0);
-#else
- duplicate = raw_strdup(s);
-#endif
- if (PREDICT_UNLIKELY(duplicate == NULL)) {
- /* LCOV_EXCL_START */
- log_err(LD_MM,"Out of memory on strdup(). Dying.");
- exit(1); // exit ok: alloc failed.
- /* LCOV_EXCL_STOP */
- }
- return duplicate;
-}
-
-/** Allocate and return a new string containing the first <b>n</b>
- * characters of <b>s</b>. If <b>s</b> is longer than <b>n</b>
- * characters, only the first <b>n</b> are copied. The result is
- * always NUL-terminated. (Like strndup(s,n), but never returns
- * NULL.)
- */
-char *
-tor_strndup_(const char *s, size_t n DMALLOC_PARAMS)
-{
- char *duplicate;
- tor_assert(s);
- tor_assert(n < SIZE_T_CEILING);
- duplicate = tor_malloc_((n+1) DMALLOC_FN_ARGS);
- /* Performance note: Ordinarily we prefer strlcpy to strncpy. But
- * this function gets called a whole lot, and platform strncpy is
- * much faster than strlcpy when strlen(s) is much longer than n.
- */
- strncpy(duplicate, s, n);
- duplicate[n]='\0';
- return duplicate;
-}
-
-/** Allocate a chunk of <b>len</b> bytes, with the same contents as the
- * <b>len</b> bytes starting at <b>mem</b>. */
-void *
-tor_memdup_(const void *mem, size_t len DMALLOC_PARAMS)
-{
- char *duplicate;
- tor_assert(len < SIZE_T_CEILING);
- tor_assert(mem);
- duplicate = tor_malloc_(len DMALLOC_FN_ARGS);
- memcpy(duplicate, mem, len);
- return duplicate;
-}
-
-/** As tor_memdup(), but add an extra 0 byte at the end of the resulting
- * memory. */
-void *
-tor_memdup_nulterm_(const void *mem, size_t len DMALLOC_PARAMS)
-{
- char *duplicate;
- tor_assert(len < SIZE_T_CEILING+1);
- tor_assert(mem);
- duplicate = tor_malloc_(len+1 DMALLOC_FN_ARGS);
- memcpy(duplicate, mem, len);
- duplicate[len] = '\0';
- return duplicate;
-}
-
-/** Helper for places that need to take a function pointer to the right
- * spelling of "free()". */
-void
-tor_free_(void *mem)
-{
- tor_free(mem);
-}
-
-DISABLE_GCC_WARNING(aggregate-return)
-/** Call the platform malloc info function, and dump the results to the log at
- * level <b>severity</b>. If no such function exists, do nothing. */
-void
-tor_log_mallinfo(int severity)
-{
-#ifdef HAVE_MALLINFO
- struct mallinfo mi;
- memset(&mi, 0, sizeof(mi));
- mi = mallinfo();
- tor_log(severity, LD_MM,
- "mallinfo() said: arena=%d, ordblks=%d, smblks=%d, hblks=%d, "
- "hblkhd=%d, usmblks=%d, fsmblks=%d, uordblks=%d, fordblks=%d, "
- "keepcost=%d",
- mi.arena, mi.ordblks, mi.smblks, mi.hblks,
- mi.hblkhd, mi.usmblks, mi.fsmblks, mi.uordblks, mi.fordblks,
- mi.keepcost);
-#else /* !(defined(HAVE_MALLINFO)) */
- (void)severity;
-#endif /* defined(HAVE_MALLINFO) */
-#ifdef USE_DMALLOC
- dmalloc_log_changed(0, /* Since the program started. */
- 1, /* Log info about non-freed pointers. */
- 0, /* Do not log info about freed pointers. */
- 0 /* Do not log individual pointers. */
- );
-#endif /* defined(USE_DMALLOC) */
-}
-ENABLE_GCC_WARNING(aggregate-return)
-
-/* =====
- * Math
- * ===== */
-
-/**
- * Returns the natural logarithm of d base e. We defined this wrapper here so
- * to avoid conflicts with old versions of tor_log(), which were named log().
- */
-double
-tor_mathlog(double d)
-{
- return log(d);
-}
-
-/** Return the long integer closest to <b>d</b>. We define this wrapper
- * here so that not all users of math.h need to use the right incantations
- * to get the c99 functions. */
-long
-tor_lround(double d)
-{
-#if defined(HAVE_LROUND)
- return lround(d);
-#elif defined(HAVE_RINT)
- return (long)rint(d);
-#else
- return (long)(d > 0 ? d + 0.5 : ceil(d - 0.5));
-#endif /* defined(HAVE_LROUND) || ... */
-}
-
-/** Return the 64-bit integer closest to d. We define this wrapper here so
- * that not all users of math.h need to use the right incantations to get the
- * c99 functions. */
-int64_t
-tor_llround(double d)
-{
-#if defined(HAVE_LLROUND)
- return (int64_t)llround(d);
-#elif defined(HAVE_RINT)
- return (int64_t)rint(d);
-#else
- return (int64_t)(d > 0 ? d + 0.5 : ceil(d - 0.5));
-#endif /* defined(HAVE_LLROUND) || ... */
-}
-
-/** Returns floor(log2(u64)). If u64 is 0, (incorrectly) returns 0. */
-int
-tor_log2(uint64_t u64)
-{
- int r = 0;
- if (u64 >= (U64_LITERAL(1)<<32)) {
- u64 >>= 32;
- r = 32;
- }
- if (u64 >= (U64_LITERAL(1)<<16)) {
- u64 >>= 16;
- r += 16;
- }
- if (u64 >= (U64_LITERAL(1)<<8)) {
- u64 >>= 8;
- r += 8;
- }
- if (u64 >= (U64_LITERAL(1)<<4)) {
- u64 >>= 4;
- r += 4;
- }
- if (u64 >= (U64_LITERAL(1)<<2)) {
- u64 >>= 2;
- r += 2;
- }
- if (u64 >= (U64_LITERAL(1)<<1)) {
- // u64 >>= 1; // not using this any more.
- r += 1;
- }
- return r;
-}
-
-/** Return the power of 2 in range [1,UINT64_MAX] closest to <b>u64</b>. If
- * there are two powers of 2 equally close, round down. */
-uint64_t
-round_to_power_of_2(uint64_t u64)
-{
- int lg2;
- uint64_t low;
- uint64_t high;
- if (u64 == 0)
- return 1;
-
- lg2 = tor_log2(u64);
- low = U64_LITERAL(1) << lg2;
-
- if (lg2 == 63)
- return low;
-
- high = U64_LITERAL(1) << (lg2+1);
- if (high - u64 < u64 - low)
- return high;
- else
- return low;
-}
-
-/** Return the lowest x such that x is at least <b>number</b>, and x modulo
- * <b>divisor</b> == 0. If no such x can be expressed as an unsigned, return
- * UINT_MAX. Asserts if divisor is zero. */
-unsigned
-round_to_next_multiple_of(unsigned number, unsigned divisor)
-{
- tor_assert(divisor > 0);
- if (UINT_MAX - divisor + 1 < number)
- return UINT_MAX;
- number += divisor - 1;
- number -= number % divisor;
- return number;
-}
-
-/** Return the lowest x such that x is at least <b>number</b>, and x modulo
- * <b>divisor</b> == 0. If no such x can be expressed as a uint32_t, return
- * UINT32_MAX. Asserts if divisor is zero. */
-uint32_t
-round_uint32_to_next_multiple_of(uint32_t number, uint32_t divisor)
-{
- tor_assert(divisor > 0);
- if (UINT32_MAX - divisor + 1 < number)
- return UINT32_MAX;
-
- number += divisor - 1;
- number -= number % divisor;
- return number;
-}
-
-/** Return the lowest x such that x is at least <b>number</b>, and x modulo
- * <b>divisor</b> == 0. If no such x can be expressed as a uint64_t, return
- * UINT64_MAX. Asserts if divisor is zero. */
-uint64_t
-round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor)
-{
- tor_assert(divisor > 0);
- if (UINT64_MAX - divisor + 1 < number)
- return UINT64_MAX;
- number += divisor - 1;
- number -= number % divisor;
- return number;
-}
-
-/** Transform a random value <b>p</b> from the uniform distribution in
- * [0.0, 1.0[ into a Laplace distributed value with location parameter
- * <b>mu</b> and scale parameter <b>b</b>. Truncate the final result
- * to be an integer in [INT64_MIN, INT64_MAX]. */
-int64_t
-sample_laplace_distribution(double mu, double b, double p)
-{
- double result;
- tor_assert(p >= 0.0 && p < 1.0);
-
- /* This is the "inverse cumulative distribution function" from:
- * http://en.wikipedia.org/wiki/Laplace_distribution */
- if (p <= 0.0) {
- /* Avoid taking log(0.0) == -INFINITY, as some processors or compiler
- * options can cause the program to trap. */
- return INT64_MIN;
- }
-
- result = mu - b * (p > 0.5 ? 1.0 : -1.0)
- * tor_mathlog(1.0 - 2.0 * fabs(p - 0.5));
-
- return clamp_double_to_int64(result);
-}
-
-/** Add random noise between INT64_MIN and INT64_MAX coming from a Laplace
- * distribution with mu = 0 and b = <b>delta_f</b>/<b>epsilon</b> to
- * <b>signal</b> based on the provided <b>random</b> value in [0.0, 1.0[.
- * The epsilon value must be between ]0.0, 1.0]. delta_f must be greater
- * than 0. */
-int64_t
-add_laplace_noise(int64_t signal_, double random_, double delta_f,
- double epsilon)
-{
- int64_t noise;
-
- /* epsilon MUST be between ]0.0, 1.0] */
- tor_assert(epsilon > 0.0 && epsilon <= 1.0);
- /* delta_f MUST be greater than 0. */
- tor_assert(delta_f > 0.0);
-
- /* Just add noise, no further signal */
- noise = sample_laplace_distribution(0.0,
- delta_f / epsilon,
- random_);
-
- /* Clip (signal + noise) to [INT64_MIN, INT64_MAX] */
- if (noise > 0 && INT64_MAX - noise < signal_)
- return INT64_MAX;
- else if (noise < 0 && INT64_MIN - noise > signal_)
- return INT64_MIN;
- else
- return signal_ + noise;
-}
-
-/* Helper: safely add two uint32_t's, capping at UINT32_MAX rather
- * than overflow */
-uint32_t
-tor_add_u32_nowrap(uint32_t a, uint32_t b)
-{
- /* a+b > UINT32_MAX check, without overflow */
- if (PREDICT_UNLIKELY(a > UINT32_MAX - b)) {
- return UINT32_MAX;
- } else {
- return a+b;
- }
-}
-
-/* Helper: return greatest common divisor of a,b */
-static uint64_t
-gcd64(uint64_t a, uint64_t b)
-{
- while (b) {
- uint64_t t = b;
- b = a % b;
- a = t;
- }
- return a;
-}
-
-/* Given a fraction *<b>numer</b> / *<b>denom</b>, simplify it.
- * Requires that the denominator is greater than 0. */
-void
-simplify_fraction64(uint64_t *numer, uint64_t *denom)
-{
- tor_assert(denom);
- uint64_t gcd = gcd64(*numer, *denom);
- *numer /= gcd;
- *denom /= gcd;
-}
-
-/** Return the number of bits set in <b>v</b>. */
-int
-n_bits_set_u8(uint8_t v)
-{
- static const int nybble_table[] = {
- 0, /* 0000 */
- 1, /* 0001 */
- 1, /* 0010 */
- 2, /* 0011 */
- 1, /* 0100 */
- 2, /* 0101 */
- 2, /* 0110 */
- 3, /* 0111 */
- 1, /* 1000 */
- 2, /* 1001 */
- 2, /* 1010 */
- 3, /* 1011 */
- 2, /* 1100 */
- 3, /* 1101 */
- 3, /* 1110 */
- 4, /* 1111 */
- };
-
- return nybble_table[v & 15] + nybble_table[v>>4];
-}
-
-/* =====
- * String manipulation
- * ===== */
-
-/** Remove from the string <b>s</b> every character which appears in
- * <b>strip</b>. */
-void
-tor_strstrip(char *s, const char *strip)
-{
- char *readp = s;
- while (*readp) {
- if (strchr(strip, *readp)) {
- ++readp;
- } else {
- *s++ = *readp++;
- }
- }
- *s = '\0';
-}
-
-/** Return a pointer to a NUL-terminated hexadecimal string encoding
- * the first <b>fromlen</b> bytes of <b>from</b>. (fromlen must be \<= 32.) The
- * result does not need to be deallocated, but repeated calls to
- * hex_str will trash old results.
- */
-const char *
-hex_str(const char *from, size_t fromlen)
-{
- static char buf[65];
- if (fromlen>(sizeof(buf)-1)/2)
- fromlen = (sizeof(buf)-1)/2;
- base16_encode(buf,sizeof(buf),from,fromlen);
- return buf;
-}
-
-/** Convert all alphabetic characters in the nul-terminated string <b>s</b> to
- * lowercase. */
-void
-tor_strlower(char *s)
-{
- while (*s) {
- *s = TOR_TOLOWER(*s);
- ++s;
- }
-}
-
-/** Convert all alphabetic characters in the nul-terminated string <b>s</b> to
- * lowercase. */
-void
-tor_strupper(char *s)
-{
- while (*s) {
- *s = TOR_TOUPPER(*s);
- ++s;
- }
-}
-
-/** Return 1 if every character in <b>s</b> is printable, else return 0.
- */
-int
-tor_strisprint(const char *s)
-{
- while (*s) {
- if (!TOR_ISPRINT(*s))
- return 0;
- s++;
- }
- return 1;
-}
-
-/** Return 1 if no character in <b>s</b> is uppercase, else return 0.
- */
-int
-tor_strisnonupper(const char *s)
-{
- while (*s) {
- if (TOR_ISUPPER(*s))
- return 0;
- s++;
- }
- return 1;
-}
-
-/** Return true iff every character in <b>s</b> is whitespace space; else
- * return false. */
-int
-tor_strisspace(const char *s)
-{
- while (*s) {
- if (!TOR_ISSPACE(*s))
- return 0;
- s++;
- }
- return 1;
-}
-
-/** As strcmp, except that either string may be NULL. The NULL string is
- * considered to be before any non-NULL string. */
-int
-strcmp_opt(const char *s1, const char *s2)
-{
- if (!s1) {
- if (!s2)
- return 0;
- else
- return -1;
- } else if (!s2) {
- return 1;
- } else {
- return strcmp(s1, s2);
- }
-}
-
-/** Compares the first strlen(s2) characters of s1 with s2. Returns as for
- * strcmp.
- */
-int
-strcmpstart(const char *s1, const char *s2)
-{
- size_t n = strlen(s2);
- return strncmp(s1, s2, n);
-}
-
-/** Compare the s1_len-byte string <b>s1</b> with <b>s2</b>,
- * without depending on a terminating nul in s1. Sorting order is first by
- * length, then lexically; return values are as for strcmp.
- */
-int
-strcmp_len(const char *s1, const char *s2, size_t s1_len)
-{
- size_t s2_len = strlen(s2);
- if (s1_len < s2_len)
- return -1;
- if (s1_len > s2_len)
- return 1;
- return fast_memcmp(s1, s2, s2_len);
-}
-
-/** Compares the first strlen(s2) characters of s1 with s2. Returns as for
- * strcasecmp.
- */
-int
-strcasecmpstart(const char *s1, const char *s2)
-{
- size_t n = strlen(s2);
- return strncasecmp(s1, s2, n);
-}
-
-/** Compares the last strlen(s2) characters of s1 with s2. Returns as for
- * strcmp.
- */
-int
-strcmpend(const char *s1, const char *s2)
-{
- size_t n1 = strlen(s1), n2 = strlen(s2);
- if (n2>n1)
- return strcmp(s1,s2);
- else
- return strncmp(s1+(n1-n2), s2, n2);
-}
-
-/** Compares the last strlen(s2) characters of s1 with s2. Returns as for
- * strcasecmp.
- */
-int
-strcasecmpend(const char *s1, const char *s2)
-{
- size_t n1 = strlen(s1), n2 = strlen(s2);
- if (n2>n1) /* then they can't be the same; figure out which is bigger */
- return strcasecmp(s1,s2);
- else
- return strncasecmp(s1+(n1-n2), s2, n2);
-}
-
-/** Compare the value of the string <b>prefix</b> with the start of the
- * <b>memlen</b>-byte memory chunk at <b>mem</b>. Return as for strcmp.
- *
- * [As fast_memcmp(mem, prefix, strlen(prefix)) but returns -1 if memlen is
- * less than strlen(prefix).]
- */
-int
-fast_memcmpstart(const void *mem, size_t memlen,
- const char *prefix)
-{
- size_t plen = strlen(prefix);
- if (memlen < plen)
- return -1;
- return fast_memcmp(mem, prefix, plen);
-}
-
-/** Return a pointer to the first char of s that is not whitespace and
- * not a comment, or to the terminating NUL if no such character exists.
- */
-const char *
-eat_whitespace(const char *s)
-{
- tor_assert(s);
-
- while (1) {
- switch (*s) {
- case '\0':
- default:
- return s;
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- ++s;
- break;
- case '#':
- ++s;
- while (*s && *s != '\n')
- ++s;
- }
- }
-}
-
-/** Return a pointer to the first char of s that is not whitespace and
- * not a comment, or to the terminating NUL if no such character exists.
- */
-const char *
-eat_whitespace_eos(const char *s, const char *eos)
-{
- tor_assert(s);
- tor_assert(eos && s <= eos);
-
- while (s < eos) {
- switch (*s) {
- case '\0':
- default:
- return s;
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- ++s;
- break;
- case '#':
- ++s;
- while (s < eos && *s && *s != '\n')
- ++s;
- }
- }
- return s;
-}
-
-/** Return a pointer to the first char of s that is not a space or a tab
- * or a \\r, or to the terminating NUL if no such character exists. */
-const char *
-eat_whitespace_no_nl(const char *s)
-{
- while (*s == ' ' || *s == '\t' || *s == '\r')
- ++s;
- return s;
-}
-
-/** As eat_whitespace_no_nl, but stop at <b>eos</b> whether we have
- * found a non-whitespace character or not. */
-const char *
-eat_whitespace_eos_no_nl(const char *s, const char *eos)
-{
- while (s < eos && (*s == ' ' || *s == '\t' || *s == '\r'))
- ++s;
- return s;
-}
-
-/** Return a pointer to the first char of s that is whitespace or <b>#</b>,
- * or to the terminating NUL if no such character exists.
- */
-const char *
-find_whitespace(const char *s)
-{
- /* tor_assert(s); */
- while (1) {
- switch (*s)
- {
- case '\0':
- case '#':
- case ' ':
- case '\r':
- case '\n':
- case '\t':
- return s;
- default:
- ++s;
- }
- }
-}
-
-/** As find_whitespace, but stop at <b>eos</b> whether we have found a
- * whitespace or not. */
-const char *
-find_whitespace_eos(const char *s, const char *eos)
-{
- /* tor_assert(s); */
- while (s < eos) {
- switch (*s)
- {
- case '\0':
- case '#':
- case ' ':
- case '\r':
- case '\n':
- case '\t':
- return s;
- default:
- ++s;
- }
- }
- return s;
-}
-
-/** Return the first occurrence of <b>needle</b> in <b>haystack</b> that
- * occurs at the start of a line (that is, at the beginning of <b>haystack</b>
- * or immediately after a newline). Return NULL if no such string is found.
- */
-const char *
-find_str_at_start_of_line(const char *haystack, const char *needle)
-{
- size_t needle_len = strlen(needle);
-
- do {
- if (!strncmp(haystack, needle, needle_len))
- return haystack;
-
- haystack = strchr(haystack, '\n');
- if (!haystack)
- return NULL;
- else
- ++haystack;
- } while (*haystack);
-
- return NULL;
-}
-
-/** Returns true if <b>string</b> could be a C identifier.
- A C identifier must begin with a letter or an underscore and the
- rest of its characters can be letters, numbers or underscores. No
- length limit is imposed. */
-int
-string_is_C_identifier(const char *string)
-{
- size_t iter;
- size_t length = strlen(string);
- if (!length)
- return 0;
-
- for (iter = 0; iter < length ; iter++) {
- if (iter == 0) {
- if (!(TOR_ISALPHA(string[iter]) ||
- string[iter] == '_'))
- return 0;
- } else {
- if (!(TOR_ISALPHA(string[iter]) ||
- TOR_ISDIGIT(string[iter]) ||
- string[iter] == '_'))
- return 0;
- }
- }
-
- return 1;
-}
-
-/** Return true iff the 'len' bytes at 'mem' are all zero. */
-int
-tor_mem_is_zero(const char *mem, size_t len)
-{
- static const char ZERO[] = {
- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
- };
- while (len >= sizeof(ZERO)) {
- /* It's safe to use fast_memcmp here, since the very worst thing an
- * attacker could learn is how many initial bytes of a secret were zero */
- if (fast_memcmp(mem, ZERO, sizeof(ZERO)))
- return 0;
- len -= sizeof(ZERO);
- mem += sizeof(ZERO);
- }
- /* Deal with leftover bytes. */
- if (len)
- return fast_memeq(mem, ZERO, len);
-
- return 1;
-}
-
-/** Return true iff the DIGEST_LEN bytes in digest are all zero. */
-int
-tor_digest_is_zero(const char *digest)
-{
- static const uint8_t ZERO_DIGEST[] = {
- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
- };
- return tor_memeq(digest, ZERO_DIGEST, DIGEST_LEN);
-}
-
-/** Return true if <b>string</b> is a valid 'key=[value]' string.
- * "value" is optional, to indicate the empty string. Log at logging
- * <b>severity</b> if something ugly happens. */
-int
-string_is_key_value(int severity, const char *string)
-{
- /* position of equal sign in string */
- const char *equal_sign_pos = NULL;
-
- tor_assert(string);
-
- if (strlen(string) < 2) { /* "x=" is shortest args string */
- tor_log(severity, LD_GENERAL, "'%s' is too short to be a k=v value.",
- escaped(string));
- return 0;
- }
-
- equal_sign_pos = strchr(string, '=');
- if (!equal_sign_pos) {
- tor_log(severity, LD_GENERAL, "'%s' is not a k=v value.", escaped(string));
- return 0;
- }
-
- /* validate that the '=' is not in the beginning of the string. */
- if (equal_sign_pos == string) {
- tor_log(severity, LD_GENERAL, "'%s' is not a valid k=v value.",
- escaped(string));
- return 0;
- }
-
- return 1;
-}
-
-/** Return true if <b>string</b> represents a valid IPv4 adddress in
- * 'a.b.c.d' form.
- */
-int
-string_is_valid_ipv4_address(const char *string)
-{
- struct in_addr addr;
-
- return (tor_inet_pton(AF_INET,string,&addr) == 1);
-}
-
-/** Return true if <b>string</b> represents a valid IPv6 address in
- * a form that inet_pton() can parse.
- */
-int
-string_is_valid_ipv6_address(const char *string)
-{
- struct in6_addr addr;
-
- return (tor_inet_pton(AF_INET6,string,&addr) == 1);
-}
-
-/** Return true iff <b>string</b> is a valid destination address,
- * i.e. either a DNS hostname or IPv4/IPv6 address string.
- */
-int
-string_is_valid_dest(const char *string)
-{
- char *tmp = NULL;
- int retval;
- size_t len;
-
- if (string == NULL)
- return 0;
-
- len = strlen(string);
-
- if (len == 0)
- return 0;
-
- if (string[0] == '[' && string[len - 1] == ']')
- string = tmp = tor_strndup(string + 1, len - 2);
-
- retval = string_is_valid_ipv4_address(string) ||
- string_is_valid_ipv6_address(string) ||
- string_is_valid_nonrfc_hostname(string);
-
- tor_free(tmp);
-
- return retval;
-}
-
-/** Return true iff <b>string</b> matches a pattern of DNS names
- * that we allow Tor clients to connect to.
- *
- * Note: This allows certain technically invalid characters ('_') to cope
- * with misconfigured zones that have been encountered in the wild.
- */
-int
-string_is_valid_nonrfc_hostname(const char *string)
-{
- int result = 1;
- int has_trailing_dot;
- char *last_label;
- smartlist_t *components;
-
- if (!string || strlen(string) == 0)
- return 0;
-
- if (string_is_valid_ipv4_address(string))
- return 0;
-
- components = smartlist_new();
-
- smartlist_split_string(components,string,".",0,0);
-
- if (BUG(smartlist_len(components) == 0))
- return 0; // LCOV_EXCL_LINE should be impossible given the earlier checks.
-
- /* Allow a single terminating '.' used rarely to indicate domains
- * are FQDNs rather than relative. */
- last_label = (char *)smartlist_get(components,
- smartlist_len(components) - 1);
- has_trailing_dot = (last_label[0] == '\0');
- if (has_trailing_dot) {
- smartlist_pop_last(components);
- tor_free(last_label);
- last_label = NULL;
- }
-
- SMARTLIST_FOREACH_BEGIN(components, char *, c) {
- if ((c[0] == '-') || (*c == '_')) {
- result = 0;
- break;
- }
-
- do {
- result = (TOR_ISALNUM(*c) || (*c == '-') || (*c == '_'));
- c++;
- } while (result && *c);
-
- if (result == 0) {
- break;
- }
- } SMARTLIST_FOREACH_END(c);
-
- SMARTLIST_FOREACH_BEGIN(components, char *, c) {
- tor_free(c);
- } SMARTLIST_FOREACH_END(c);
-
- smartlist_free(components);
-
- return result;
-}
-
-/** Return true iff the DIGEST256_LEN bytes in digest are all zero. */
-int
-tor_digest256_is_zero(const char *digest)
-{
- return tor_mem_is_zero(digest, DIGEST256_LEN);
-}
-
-/* Helper: common code to check whether the result of a strtol or strtoul or
- * strtoll is correct. */
-#define CHECK_STRTOX_RESULT() \
- /* Did an overflow occur? */ \
- if (errno == ERANGE) \
- goto err; \
- /* Was at least one character converted? */ \
- if (endptr == s) \
- goto err; \
- /* Were there unexpected unconverted characters? */ \
- if (!next && *endptr) \
- goto err; \
- /* Illogical (max, min) inputs? */ \
- if (BUG(max < min)) \
- goto err; \
- /* Is r within limits? */ \
- if (r < min || r > max) \
- goto err; \
- if (ok) *ok = 1; \
- if (next) *next = endptr; \
- return r; \
- err: \
- if (ok) *ok = 0; \
- if (next) *next = endptr; \
- return 0
-
-/** Extract a long from the start of <b>s</b>, in the given numeric
- * <b>base</b>. If <b>base</b> is 0, <b>s</b> is parsed as a decimal,
- * octal, or hex number in the syntax of a C integer literal. If
- * there is unconverted data and <b>next</b> is provided, set
- * *<b>next</b> to the first unconverted character. An error has
- * occurred if no characters are converted; or if there are
- * unconverted characters and <b>next</b> is NULL; or if the parsed
- * value is not between <b>min</b> and <b>max</b>. When no error
- * occurs, return the parsed value and set *<b>ok</b> (if provided) to
- * 1. When an error occurs, return 0 and set *<b>ok</b> (if provided)
- * to 0.
- */
-long
-tor_parse_long(const char *s, int base, long min, long max,
- int *ok, char **next)
-{
- char *endptr;
- long r;
-
- if (BUG(base < 0)) {
- if (ok)
- *ok = 0;
- return 0;
- }
-
- errno = 0;
- r = strtol(s, &endptr, base);
- CHECK_STRTOX_RESULT();
-}
-
-/** As tor_parse_long(), but return an unsigned long. */
-unsigned long
-tor_parse_ulong(const char *s, int base, unsigned long min,
- unsigned long max, int *ok, char **next)
-{
- char *endptr;
- unsigned long r;
-
- if (BUG(base < 0)) {
- if (ok)
- *ok = 0;
- return 0;
- }
-
- errno = 0;
- r = strtoul(s, &endptr, base);
- CHECK_STRTOX_RESULT();
-}
-
-/** As tor_parse_long(), but return a double. */
-double
-tor_parse_double(const char *s, double min, double max, int *ok, char **next)
-{
- char *endptr;
- double r;
-
- errno = 0;
- r = strtod(s, &endptr);
- CHECK_STRTOX_RESULT();
-}
-
-/** As tor_parse_long, but return a uint64_t. Only base 10 is guaranteed to
- * work for now. */
-uint64_t
-tor_parse_uint64(const char *s, int base, uint64_t min,
- uint64_t max, int *ok, char **next)
-{
- char *endptr;
- uint64_t r;
-
- if (BUG(base < 0)) {
- if (ok)
- *ok = 0;
- return 0;
- }
-
- errno = 0;
-#ifdef HAVE_STRTOULL
- r = (uint64_t)strtoull(s, &endptr, base);
-#elif defined(_WIN32)
- r = (uint64_t)_strtoui64(s, &endptr, base);
-#elif SIZEOF_LONG == 8
- r = (uint64_t)strtoul(s, &endptr, base);
-#else
-#error "I don't know how to parse 64-bit numbers."
-#endif /* defined(HAVE_STRTOULL) || ... */
-
- CHECK_STRTOX_RESULT();
-}
-
-/** Allocate and return a new string representing the contents of <b>s</b>,
- * surrounded by quotes and using standard C escapes.
- *
- * Generally, we use this for logging values that come in over the network to
- * keep them from tricking users, and for sending certain values to the
- * controller.
- *
- * We trust values from the resolver, OS, configuration file, and command line
- * to not be maliciously ill-formed. We validate incoming routerdescs and
- * SOCKS requests and addresses from BEGIN cells as they're parsed;
- * afterwards, we trust them as non-malicious.
- */
-char *
-esc_for_log(const char *s)
-{
- const char *cp;
- char *result, *outp;
- size_t len = 3;
- if (!s) {
- return tor_strdup("(null)");
- }
-
- for (cp = s; *cp; ++cp) {
- switch (*cp) {
- case '\\':
- case '\"':
- case '\'':
- case '\r':
- case '\n':
- case '\t':
- len += 2;
- break;
- default:
- if (TOR_ISPRINT(*cp) && ((uint8_t)*cp)<127)
- ++len;
- else
- len += 4;
- break;
- }
- }
-
- tor_assert(len <= SSIZE_MAX);
-
- result = outp = tor_malloc(len);
- *outp++ = '\"';
- for (cp = s; *cp; ++cp) {
- /* This assertion should always succeed, since we will write at least
- * one char here, and two chars for closing quote and nul later */
- tor_assert((outp-result) < (ssize_t)len-2);
- switch (*cp) {
- case '\\':
- case '\"':
- case '\'':
- *outp++ = '\\';
- *outp++ = *cp;
- break;
- case '\n':
- *outp++ = '\\';
- *outp++ = 'n';
- break;
- case '\t':
- *outp++ = '\\';
- *outp++ = 't';
- break;
- case '\r':
- *outp++ = '\\';
- *outp++ = 'r';
- break;
- default:
- if (TOR_ISPRINT(*cp) && ((uint8_t)*cp)<127) {
- *outp++ = *cp;
- } else {
- tor_assert((outp-result) < (ssize_t)len-4);
- tor_snprintf(outp, 5, "\\%03o", (int)(uint8_t) *cp);
- outp += 4;
- }
- break;
- }
- }
-
- tor_assert((outp-result) <= (ssize_t)len-2);
- *outp++ = '\"';
- *outp++ = 0;
-
- return result;
-}
-
-/** Similar to esc_for_log. Allocate and return a new string representing
- * the first n characters in <b>chars</b>, surround by quotes and using
- * standard C escapes. If a NUL character is encountered in <b>chars</b>,
- * the resulting string will be terminated there.
- */
-char *
-esc_for_log_len(const char *chars, size_t n)
-{
- char *string = tor_strndup(chars, n);
- char *string_escaped = esc_for_log(string);
- tor_free(string);
- return string_escaped;
-}
-
-/** Allocate and return a new string representing the contents of <b>s</b>,
- * surrounded by quotes and using standard C escapes.
- *
- * THIS FUNCTION IS NOT REENTRANT. Don't call it from outside the main
- * thread. Also, each call invalidates the last-returned value, so don't
- * try log_warn(LD_GENERAL, "%s %s", escaped(a), escaped(b));
- */
-const char *
-escaped(const char *s)
-{
- static char *escaped_val_ = NULL;
- tor_free(escaped_val_);
-
- if (s)
- escaped_val_ = esc_for_log(s);
- else
- escaped_val_ = NULL;
-
- return escaped_val_;
-}
-
-/** Return a newly allocated string equal to <b>string</b>, except that every
- * character in <b>chars_to_escape</b> is preceded by a backslash. */
-char *
-tor_escape_str_for_pt_args(const char *string, const char *chars_to_escape)
-{
- char *new_string = NULL;
- char *new_cp = NULL;
- size_t length, new_length;
-
- tor_assert(string);
-
- length = strlen(string);
-
- if (!length) /* If we were given the empty string, return the same. */
- return tor_strdup("");
- /* (new_length > SIZE_MAX) => ((length * 2) + 1 > SIZE_MAX) =>
- (length*2 > SIZE_MAX - 1) => (length > (SIZE_MAX - 1)/2) */
- if (length > (SIZE_MAX - 1)/2) /* check for overflow */
- return NULL;
-
- /* this should be enough even if all characters must be escaped */
- new_length = (length * 2) + 1;
-
- new_string = new_cp = tor_malloc(new_length);
-
- while (*string) {
- if (strchr(chars_to_escape, *string))
- *new_cp++ = '\\';
-
- *new_cp++ = *string++;
- }
-
- *new_cp = '\0'; /* NUL-terminate the new string */
-
- return new_string;
-}
-
-/* =====
- * Time
- * ===== */
-
-#define TOR_USEC_PER_SEC 1000000
-
-/** Return the difference between start->tv_sec and end->tv_sec.
- * Returns INT64_MAX on overflow and underflow.
- */
-static int64_t
-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,
- * but it's easy to see that it's correct and doesn't overflow */
-
- if (s > 0 && e < INT64_MIN + s) {
- /* s is positive: equivalent to e - s < INT64_MIN, but without any
- * overflow */
- return INT64_MAX;
- } else if (s < 0 && e > INT64_MAX + s) {
- /* s is negative: equivalent to e - s > INT64_MAX, but without any
- * overflow */
- return INT64_MAX;
- }
-
- return e - s;
-}
-
-/** Return the number of microseconds elapsed between *start and *end.
- * Returns LONG_MAX on overflow and underflow.
- */
-long
-tv_udiff(const struct timeval *start, const struct timeval *end)
-{
- /* Sanity check tv_usec */
- if (start->tv_usec > TOR_USEC_PER_SEC || start->tv_usec < 0) {
- log_warn(LD_GENERAL, "comparing times on microsecond detail with bad "
- "start tv_usec: " I64_FORMAT " microseconds",
- I64_PRINTF_ARG(start->tv_usec));
- return LONG_MAX;
- }
-
- if (end->tv_usec > TOR_USEC_PER_SEC || end->tv_usec < 0) {
- log_warn(LD_GENERAL, "comparing times on microsecond detail with bad "
- "end tv_usec: " I64_FORMAT " microseconds",
- I64_PRINTF_ARG(end->tv_usec));
- return LONG_MAX;
- }
-
- /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
- */
- int64_t udiff;
- const int64_t secdiff = tv_secdiff_impl(start, end);
-
- /* end->tv_usec - start->tv_usec can be up to 1 second either way */
- if (secdiff > (int64_t)(LONG_MAX/1000000 - 1) ||
- secdiff < (int64_t)(LONG_MIN/1000000 + 1)) {
- log_warn(LD_GENERAL, "comparing times on microsecond detail too far "
- "apart: " I64_FORMAT " seconds", I64_PRINTF_ARG(secdiff));
- return LONG_MAX;
- }
-
- /* we'll never get an overflow here, because we check that both usecs are
- * between 0 and TV_USEC_PER_SEC. */
- udiff = secdiff*1000000 + ((int64_t)end->tv_usec - (int64_t)start->tv_usec);
-
- /* Some compilers are smart enough to work out this is a no-op on L64 */
-#if SIZEOF_LONG < 8
- if (udiff > (int64_t)LONG_MAX || udiff < (int64_t)LONG_MIN) {
- return LONG_MAX;
- }
-#endif
-
- return (long)udiff;
-}
-
-/** Return the number of milliseconds elapsed between *start and *end.
- * If the tv_usec difference is 500, rounds away from zero.
- * Returns LONG_MAX on overflow and underflow.
- */
-long
-tv_mdiff(const struct timeval *start, const struct timeval *end)
-{
- /* Sanity check tv_usec */
- if (start->tv_usec > TOR_USEC_PER_SEC || start->tv_usec < 0) {
- log_warn(LD_GENERAL, "comparing times on millisecond detail with bad "
- "start tv_usec: " I64_FORMAT " microseconds",
- I64_PRINTF_ARG(start->tv_usec));
- return LONG_MAX;
- }
-
- if (end->tv_usec > TOR_USEC_PER_SEC || end->tv_usec < 0) {
- log_warn(LD_GENERAL, "comparing times on millisecond detail with bad "
- "end tv_usec: " I64_FORMAT " microseconds",
- I64_PRINTF_ARG(end->tv_usec));
- return LONG_MAX;
- }
-
- /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
- */
- int64_t mdiff;
- const int64_t secdiff = tv_secdiff_impl(start, end);
-
- /* end->tv_usec - start->tv_usec can be up to 1 second either way, but the
- * mdiff calculation may add another temporary second for rounding.
- * Whether this actually causes overflow depends on the compiler's constant
- * folding and order of operations. */
- if (secdiff > (int64_t)(LONG_MAX/1000 - 2) ||
- secdiff < (int64_t)(LONG_MIN/1000 + 1)) {
- log_warn(LD_GENERAL, "comparing times on millisecond detail too far "
- "apart: " I64_FORMAT " seconds", I64_PRINTF_ARG(secdiff));
- return LONG_MAX;
- }
-
- /* Subtract and round */
- mdiff = secdiff*1000 +
- /* We add a million usec here to ensure that the result is positive,
- * so that the round-towards-zero behavior of the division will give
- * the right result for rounding to the nearest msec. Later we subtract
- * 1000 in order to get the correct result.
- * We'll never get an overflow here, because we check that both usecs are
- * between 0 and TV_USEC_PER_SEC. */
- ((int64_t)end->tv_usec - (int64_t)start->tv_usec + 500 + 1000000) / 1000
- - 1000;
-
- /* Some compilers are smart enough to work out this is a no-op on L64 */
-#if SIZEOF_LONG < 8
- if (mdiff > (int64_t)LONG_MAX || mdiff < (int64_t)LONG_MIN) {
- return LONG_MAX;
- }
-#endif
-
- return (long)mdiff;
-}
-
-/**
- * Converts timeval to milliseconds.
- */
-int64_t
-tv_to_msec(const struct timeval *tv)
-{
- int64_t conv = ((int64_t)tv->tv_sec)*1000L;
- /* Round ghetto-style */
- conv += ((int64_t)tv->tv_usec+500)/1000L;
- return conv;
-}
-
-/** Yield true iff <b>y</b> is a leap-year. */
-#define IS_LEAPYEAR(y) (!(y % 4) && ((y % 100) || !(y % 400)))
-/** Helper: Return the number of leap-days between Jan 1, y1 and Jan 1, y2. */
-static int
-n_leapdays(int year1, int year2)
-{
- --year1;
- --year2;
- return (year2/4 - year1/4) - (year2/100 - year1/100)
- + (year2/400 - year1/400);
-}
-/** Number of days per month in non-leap year; used by tor_timegm and
- * parse_rfc1123_time. */
-static const int days_per_month[] =
- { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-/** Compute a time_t given a struct tm. The result is given in UTC, and
- * does not account for leap seconds. Return 0 on success, -1 on failure.
- */
-int
-tor_timegm(const struct tm *tm, time_t *time_out)
-{
- /* This is a pretty ironclad timegm implementation, snarfed from Python2.2.
- * It's way more brute-force than fiddling with tzset().
- *
- * We use int64_t rather than time_t to avoid overflow on multiplication on
- * platforms with 32-bit time_t. Since year is clipped to INT32_MAX, and
- * since 365 * 24 * 60 * 60 is approximately 31 million, it's not possible
- * for INT32_MAX years to overflow int64_t when converted to seconds. */
- int64_t year, days, hours, minutes, seconds;
- int i, invalid_year, dpm;
-
- /* Initialize time_out to 0 for now, to avoid bad usage in case this function
- fails and the caller ignores the return value. */
- tor_assert(time_out);
- *time_out = 0;
-
- /* avoid int overflow on addition */
- if (tm->tm_year < INT32_MAX-1900) {
- year = tm->tm_year + 1900;
- } else {
- /* clamp year */
- year = INT32_MAX;
- }
- invalid_year = (year < 1970 || tm->tm_year >= INT32_MAX-1900);
-
- if (tm->tm_mon >= 0 && tm->tm_mon <= 11) {
- dpm = days_per_month[tm->tm_mon];
- if (tm->tm_mon == 1 && !invalid_year && IS_LEAPYEAR(tm->tm_year)) {
- dpm = 29;
- }
- } else {
- /* invalid month - default to 0 days per month */
- dpm = 0;
- }
-
- if (invalid_year ||
- tm->tm_mon < 0 || tm->tm_mon > 11 ||
- tm->tm_mday < 1 || tm->tm_mday > dpm ||
- tm->tm_hour < 0 || tm->tm_hour > 23 ||
- tm->tm_min < 0 || tm->tm_min > 59 ||
- tm->tm_sec < 0 || tm->tm_sec > 60) {
- log_warn(LD_BUG, "Out-of-range argument to tor_timegm");
- return -1;
- }
- days = 365 * (year-1970) + n_leapdays(1970,(int)year);
- for (i = 0; i < tm->tm_mon; ++i)
- days += days_per_month[i];
- if (tm->tm_mon > 1 && IS_LEAPYEAR(year))
- ++days;
- days += tm->tm_mday - 1;
- hours = days*24 + tm->tm_hour;
-
- minutes = hours*60 + tm->tm_min;
- seconds = minutes*60 + tm->tm_sec;
- /* Check that "seconds" will fit in a time_t. On platforms where time_t is
- * 32-bit, this check will fail for dates in and after 2038.
- *
- * We already know that "seconds" can't be negative because "year" >= 1970 */
-#if SIZEOF_TIME_T < 8
- if (seconds < TIME_MIN || seconds > TIME_MAX) {
- log_warn(LD_BUG, "Result does not fit in tor_timegm");
- return -1;
- }
-#endif /* SIZEOF_TIME_T < 8 */
- *time_out = (time_t)seconds;
- return 0;
-}
-
-/* strftime is locale-specific, so we need to replace those parts */
-
-/** A c-locale array of 3-letter names of weekdays, starting with Sun. */
-static const char *WEEKDAY_NAMES[] =
- { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
-/** A c-locale array of 3-letter names of months, starting with Jan. */
-static const char *MONTH_NAMES[] =
- { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-
-/** Set <b>buf</b> to the RFC1123 encoding of the UTC value of <b>t</b>.
- * The buffer must be at least RFC1123_TIME_LEN+1 bytes long.
- *
- * (RFC1123 format is "Fri, 29 Sep 2006 15:54:20 GMT". Note the "GMT"
- * rather than "UTC".)
- */
-void
-format_rfc1123_time(char *buf, time_t t)
-{
- struct tm tm;
-
- tor_gmtime_r(&t, &tm);
-
- strftime(buf, RFC1123_TIME_LEN+1, "___, %d ___ %Y %H:%M:%S GMT", &tm);
- tor_assert(tm.tm_wday >= 0);
- tor_assert(tm.tm_wday <= 6);
- memcpy(buf, WEEKDAY_NAMES[tm.tm_wday], 3);
- tor_assert(tm.tm_mon >= 0);
- tor_assert(tm.tm_mon <= 11);
- memcpy(buf+8, MONTH_NAMES[tm.tm_mon], 3);
-}
-
-/** Parse the (a subset of) the RFC1123 encoding of some time (in UTC) from
- * <b>buf</b>, and store the result in *<b>t</b>.
- *
- * Note that we only accept the subset generated by format_rfc1123_time above,
- * not the full range of formats suggested by RFC 1123.
- *
- * Return 0 on success, -1 on failure.
-*/
-int
-parse_rfc1123_time(const char *buf, time_t *t)
-{
- struct tm tm;
- char month[4];
- char weekday[4];
- int i, m, invalid_year;
- unsigned tm_mday, tm_year, tm_hour, tm_min, tm_sec;
- unsigned dpm;
-
- if (strlen(buf) != RFC1123_TIME_LEN)
- return -1;
- memset(&tm, 0, sizeof(tm));
- if (tor_sscanf(buf, "%3s, %2u %3s %u %2u:%2u:%2u GMT", weekday,
- &tm_mday, month, &tm_year, &tm_hour,
- &tm_min, &tm_sec) < 7) {
- char *esc = esc_for_log(buf);
- log_warn(LD_GENERAL, "Got invalid RFC1123 time %s", esc);
- tor_free(esc);
- return -1;
- }
-
- m = -1;
- for (i = 0; i < 12; ++i) {
- if (!strcmp(month, MONTH_NAMES[i])) {
- m = i;
- break;
- }
- }
- if (m<0) {
- char *esc = esc_for_log(buf);
- log_warn(LD_GENERAL, "Got invalid RFC1123 time %s: No such month", esc);
- tor_free(esc);
- return -1;
- }
- tm.tm_mon = m;
-
- invalid_year = (tm_year >= INT32_MAX || tm_year < 1970);
- tor_assert(m >= 0 && m <= 11);
- dpm = days_per_month[m];
- if (m == 1 && !invalid_year && IS_LEAPYEAR(tm_year)) {
- dpm = 29;
- }
-
- if (invalid_year || tm_mday < 1 || tm_mday > dpm ||
- tm_hour > 23 || tm_min > 59 || tm_sec > 60) {
- char *esc = esc_for_log(buf);
- log_warn(LD_GENERAL, "Got invalid RFC1123 time %s", esc);
- tor_free(esc);
- return -1;
- }
- tm.tm_mday = (int)tm_mday;
- tm.tm_year = (int)tm_year;
- tm.tm_hour = (int)tm_hour;
- tm.tm_min = (int)tm_min;
- tm.tm_sec = (int)tm_sec;
-
- if (tm.tm_year < 1970) {
- /* LCOV_EXCL_START
- * XXXX I think this is dead code; we already checked for
- * invalid_year above. */
- tor_assert_nonfatal_unreached();
- char *esc = esc_for_log(buf);
- log_warn(LD_GENERAL,
- "Got invalid RFC1123 time %s. (Before 1970)", esc);
- tor_free(esc);
- return -1;
- /* LCOV_EXCL_STOP */
- }
- tm.tm_year -= 1900;
-
- return tor_timegm(&tm, t);
-}
-
-/** Set <b>buf</b> to the ISO8601 encoding of the local value of <b>t</b>.
- * The buffer must be at least ISO_TIME_LEN+1 bytes long.
- *
- * (ISO8601 format is 2006-10-29 10:57:20)
- */
-void
-format_local_iso_time(char *buf, time_t t)
-{
- struct tm tm;
- strftime(buf, ISO_TIME_LEN+1, "%Y-%m-%d %H:%M:%S", tor_localtime_r(&t, &tm));
-}
-
-/** Set <b>buf</b> to the ISO8601 encoding of the GMT value of <b>t</b>.
- * The buffer must be at least ISO_TIME_LEN+1 bytes long.
- */
-void
-format_iso_time(char *buf, time_t t)
-{
- struct tm tm;
- strftime(buf, ISO_TIME_LEN+1, "%Y-%m-%d %H:%M:%S", tor_gmtime_r(&t, &tm));
-}
-
-/** As format_local_iso_time, but use the yyyy-mm-ddThh:mm:ss format to avoid
- * embedding an internal space. */
-void
-format_local_iso_time_nospace(char *buf, time_t t)
-{
- format_local_iso_time(buf, t);
- buf[10] = 'T';
-}
-
-/** As format_iso_time, but use the yyyy-mm-ddThh:mm:ss format to avoid
- * embedding an internal space. */
-void
-format_iso_time_nospace(char *buf, time_t t)
-{
- format_iso_time(buf, t);
- buf[10] = 'T';
-}
-
-/** As format_iso_time_nospace, but include microseconds in decimal
- * fixed-point format. Requires that buf be at least ISO_TIME_USEC_LEN+1
- * bytes long. */
-void
-format_iso_time_nospace_usec(char *buf, const struct timeval *tv)
-{
- tor_assert(tv);
- format_iso_time_nospace(buf, (time_t)tv->tv_sec);
- tor_snprintf(buf+ISO_TIME_LEN, 8, ".%06d", (int)tv->tv_usec);
-}
-
-/** Given an ISO-formatted UTC time value (after the epoch) in <b>cp</b>,
- * parse it and store its value in *<b>t</b>. Return 0 on success, -1 on
- * failure. Ignore extraneous stuff in <b>cp</b> after the end of the time
- * string, unless <b>strict</b> is set. If <b>nospace</b> is set,
- * expect the YYYY-MM-DDTHH:MM:SS format. */
-int
-parse_iso_time_(const char *cp, time_t *t, int strict, int nospace)
-{
- struct tm st_tm;
- unsigned int year=0, month=0, day=0, hour=0, minute=0, second=0;
- int n_fields;
- char extra_char, separator_char;
- n_fields = tor_sscanf(cp, "%u-%2u-%2u%c%2u:%2u:%2u%c",
- &year, &month, &day,
- &separator_char,
- &hour, &minute, &second, &extra_char);
- if (strict ? (n_fields != 7) : (n_fields < 7)) {
- char *esc = esc_for_log(cp);
- log_warn(LD_GENERAL, "ISO time %s was unparseable", esc);
- tor_free(esc);
- return -1;
- }
- if (separator_char != (nospace ? 'T' : ' ')) {
- char *esc = esc_for_log(cp);
- log_warn(LD_GENERAL, "ISO time %s was unparseable", esc);
- tor_free(esc);
- return -1;
- }
- if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
- hour > 23 || minute > 59 || second > 60 || year >= INT32_MAX) {
- char *esc = esc_for_log(cp);
- log_warn(LD_GENERAL, "ISO time %s was nonsensical", esc);
- tor_free(esc);
- return -1;
- }
- st_tm.tm_year = (int)year-1900;
- st_tm.tm_mon = month-1;
- st_tm.tm_mday = day;
- st_tm.tm_hour = hour;
- st_tm.tm_min = minute;
- st_tm.tm_sec = second;
- st_tm.tm_wday = 0; /* Should be ignored. */
-
- if (st_tm.tm_year < 70) {
- /* LCOV_EXCL_START
- * XXXX I think this is dead code; we already checked for
- * year < 1970 above. */
- tor_assert_nonfatal_unreached();
- char *esc = esc_for_log(cp);
- log_warn(LD_GENERAL, "Got invalid ISO time %s. (Before 1970)", esc);
- tor_free(esc);
- return -1;
- /* LCOV_EXCL_STOP */
- }
- return tor_timegm(&st_tm, t);
-}
-
-/** Given an ISO-formatted UTC time value (after the epoch) in <b>cp</b>,
- * parse it and store its value in *<b>t</b>. Return 0 on success, -1 on
- * failure. Reject the string if any characters are present after the time.
- */
-int
-parse_iso_time(const char *cp, time_t *t)
-{
- return parse_iso_time_(cp, t, 1, 0);
-}
-
-/**
- * As parse_iso_time, but parses a time encoded by format_iso_time_nospace().
- */
-int
-parse_iso_time_nospace(const char *cp, time_t *t)
-{
- return parse_iso_time_(cp, t, 1, 1);
-}
-
-/** Given a <b>date</b> in one of the three formats allowed by HTTP (ugh),
- * parse it into <b>tm</b>. Return 0 on success, negative on failure. */
-int
-parse_http_time(const char *date, struct tm *tm)
-{
- const char *cp;
- char month[4];
- char wkday[4];
- int i;
- unsigned tm_mday, tm_year, tm_hour, tm_min, tm_sec;
-
- tor_assert(tm);
- memset(tm, 0, sizeof(*tm));
-
- /* First, try RFC1123 or RFC850 format: skip the weekday. */
- if ((cp = strchr(date, ','))) {
- ++cp;
- if (*cp != ' ')
- return -1;
- ++cp;
- if (tor_sscanf(cp, "%2u %3s %4u %2u:%2u:%2u GMT",
- &tm_mday, month, &tm_year,
- &tm_hour, &tm_min, &tm_sec) == 6) {
- /* rfc1123-date */
- tm_year -= 1900;
- } else if (tor_sscanf(cp, "%2u-%3s-%2u %2u:%2u:%2u GMT",
- &tm_mday, month, &tm_year,
- &tm_hour, &tm_min, &tm_sec) == 6) {
- /* rfc850-date */
- } else {
- return -1;
- }
- } else {
- /* No comma; possibly asctime() format. */
- if (tor_sscanf(date, "%3s %3s %2u %2u:%2u:%2u %4u",
- wkday, month, &tm_mday,
- &tm_hour, &tm_min, &tm_sec, &tm_year) == 7) {
- tm_year -= 1900;
- } else {
- return -1;
- }
- }
- tm->tm_mday = (int)tm_mday;
- tm->tm_year = (int)tm_year;
- tm->tm_hour = (int)tm_hour;
- tm->tm_min = (int)tm_min;
- tm->tm_sec = (int)tm_sec;
- tm->tm_wday = 0; /* Leave this unset. */
-
- month[3] = '\0';
- /* Okay, now decode the month. */
- /* set tm->tm_mon to dummy value so the check below fails. */
- tm->tm_mon = -1;
- for (i = 0; i < 12; ++i) {
- if (!strcasecmp(MONTH_NAMES[i], month)) {
- tm->tm_mon = i;
- }
- }
-
- if (tm->tm_year < 0 ||
- tm->tm_mon < 0 || tm->tm_mon > 11 ||
- tm->tm_mday < 1 || tm->tm_mday > 31 ||
- tm->tm_hour < 0 || tm->tm_hour > 23 ||
- tm->tm_min < 0 || tm->tm_min > 59 ||
- tm->tm_sec < 0 || tm->tm_sec > 60)
- return -1; /* Out of range, or bad month. */
-
- return 0;
-}
-
-/** Given an <b>interval</b> in seconds, try to write it to the
- * <b>out_len</b>-byte buffer in <b>out</b> in a human-readable form.
- * Returns a non-negative integer on success, -1 on failure.
- */
-int
-format_time_interval(char *out, size_t out_len, long interval)
-{
- /* We only report seconds if there's no hours. */
- long sec = 0, min = 0, hour = 0, day = 0;
-
- /* -LONG_MIN is LONG_MAX + 1, which causes signed overflow */
- if (interval < -LONG_MAX)
- interval = LONG_MAX;
- else if (interval < 0)
- interval = -interval;
-
- if (interval >= 86400) {
- day = interval / 86400;
- interval %= 86400;
- }
- if (interval >= 3600) {
- hour = interval / 3600;
- interval %= 3600;
- }
- if (interval >= 60) {
- min = interval / 60;
- interval %= 60;
- }
- sec = interval;
-
- if (day) {
- return tor_snprintf(out, out_len, "%ld days, %ld hours, %ld minutes",
- day, hour, min);
- } else if (hour) {
- return tor_snprintf(out, out_len, "%ld hours, %ld minutes", hour, min);
- } else if (min) {
- return tor_snprintf(out, out_len, "%ld minutes, %ld seconds", min, sec);
- } else {
- return tor_snprintf(out, out_len, "%ld seconds", sec);
- }
-}
-
-/* =====
- * Cached time
- * ===== */
-
-#ifndef TIME_IS_FAST
-/** Cached estimate of the current time. Updated around once per second;
- * may be a few seconds off if we are really busy. This is a hack to avoid
- * calling time(NULL) (which not everybody has optimized) on critical paths.
- */
-static time_t cached_approx_time = 0;
-
-/** Return a cached estimate of the current time from when
- * update_approx_time() was last called. This is a hack to avoid calling
- * time(NULL) on critical paths: please do not even think of calling it
- * anywhere else. */
-time_t
-approx_time(void)
-{
- return cached_approx_time;
-}
-
-/** Update the cached estimate of the current time. This function SHOULD be
- * called once per second, and MUST be called before the first call to
- * get_approx_time. */
-void
-update_approx_time(time_t now)
-{
- cached_approx_time = now;
-}
-#endif /* !defined(TIME_IS_FAST) */
-
-/* =====
- * Rate limiting
- * ===== */
-
-/** 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
- * rate_limit_is_ready returned nonzero. Otherwise return 0.
- * If the call number hits <b>RATELIM_TOOMANY</b> limit, drop a warning
- * about this event and stop counting. */
-static int
-rate_limit_is_ready(ratelim_t *lim, time_t now)
-{
- if (lim->rate + lim->last_allowed <= now) {
- int res = lim->n_calls_since_last_time + 1;
- lim->last_allowed = now;
- lim->n_calls_since_last_time = 0;
- return res;
- } else {
- if (lim->n_calls_since_last_time <= RATELIM_TOOMANY) {
- ++lim->n_calls_since_last_time;
- }
-
- return 0;
- }
-}
-
-/** If the rate-limiter <b>lim</b> is ready at <b>now</b>, return a newly
- * allocated string indicating how many messages were suppressed, suitable to
- * append to a log message. Otherwise return NULL. */
-char *
-rate_limit_log(ratelim_t *lim, time_t now)
-{
- int n;
- if ((n = rate_limit_is_ready(lim, now))) {
- 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. */
- tor_asprintf(&cp,
- " [%s%d similar message(s) suppressed in last %d seconds]",
- opt_over, n-1, lim->rate);
- return cp;
- }
- } else {
- return NULL;
- }
-}
-
-/* =====
- * File helpers
- * ===== */
-
-/** Write <b>count</b> bytes from <b>buf</b> to <b>fd</b>. <b>isSocket</b>
- * must be 1 if fd was returned by socket() or accept(), and 0 if fd
- * was returned by open(). Return the number of bytes written, or -1
- * on error. Only use if fd is a blocking fd. */
-ssize_t
-write_all(tor_socket_t fd, const char *buf, size_t count, int isSocket)
-{
- size_t written = 0;
- ssize_t result;
- tor_assert(count < SSIZE_MAX);
-
- while (written != count) {
- if (isSocket)
- result = tor_socket_send(fd, buf+written, count-written, 0);
- else
- result = write((int)fd, buf+written, count-written);
- if (result<0)
- return -1;
- written += result;
- }
- return (ssize_t)count;
-}
-
-/** Read from <b>fd</b> to <b>buf</b>, until we get <b>count</b> bytes
- * or reach the end of the file. <b>isSocket</b> must be 1 if fd
- * was returned by socket() or accept(), and 0 if fd was returned by
- * open(). Return the number of bytes read, or -1 on error. Only use
- * if fd is a blocking fd. */
-ssize_t
-read_all(tor_socket_t fd, char *buf, size_t count, int isSocket)
-{
- size_t numread = 0;
- ssize_t result;
-
- if (count > SIZE_T_CEILING || count > SSIZE_MAX) {
- errno = EINVAL;
- return -1;
- }
-
- while (numread < count) {
- if (isSocket)
- result = tor_socket_recv(fd, buf+numread, count-numread, 0);
- else
- result = read((int)fd, buf+numread, count-numread);
- if (result<0)
- return -1;
- else if (result == 0)
- break;
- numread += result;
- }
- return (ssize_t)numread;
-}
-
-/*
- * Filesystem operations.
- */
-
-/** Clean up <b>name</b> so that we can use it in a call to "stat". On Unix,
- * we do nothing. On Windows, we remove a trailing slash, unless the path is
- * the root of a disk. */
-static void
-clean_name_for_stat(char *name)
-{
-#ifdef _WIN32
- size_t len = strlen(name);
- if (!len)
- return;
- if (name[len-1]=='\\' || name[len-1]=='/') {
- if (len == 1 || (len==3 && name[1]==':'))
- return;
- name[len-1]='\0';
- }
-#else /* !(defined(_WIN32)) */
- (void)name;
-#endif /* defined(_WIN32) */
-}
-
-/** Wrapper for unlink() to make it mockable for the test suite; returns 0
- * if unlinking the file succeeded, -1 and sets errno if unlinking fails.
- */
-
-MOCK_IMPL(int,
-tor_unlink,(const char *pathname))
-{
- return unlink(pathname);
-}
-
-/** Return:
- * FN_ERROR if filename can't be read, is NULL, or is zero-length,
- * FN_NOENT if it doesn't exist,
- * FN_FILE if it is a non-empty regular file, or a FIFO on unix-like systems,
- * FN_EMPTY for zero-byte regular files,
- * FN_DIR if it's a directory, and
- * FN_ERROR for any other file type.
- * On FN_ERROR and FN_NOENT, sets errno. (errno is not set when FN_ERROR
- * is returned due to an unhandled file type.) */
-file_status_t
-file_status(const char *fname)
-{
- struct stat st;
- char *f;
- int r;
- if (!fname || strlen(fname) == 0) {
- return FN_ERROR;
- }
- f = tor_strdup(fname);
- clean_name_for_stat(f);
- log_debug(LD_FS, "stat()ing %s", f);
- r = stat(sandbox_intern_string(f), &st);
- tor_free(f);
- if (r) {
- if (errno == ENOENT) {
- return FN_NOENT;
- }
- return FN_ERROR;
- }
- if (st.st_mode & S_IFDIR) {
- return FN_DIR;
- } else if (st.st_mode & S_IFREG) {
- if (st.st_size > 0) {
- return FN_FILE;
- } else if (st.st_size == 0) {
- return FN_EMPTY;
- } else {
- return FN_ERROR;
- }
-#ifndef _WIN32
- } else if (st.st_mode & S_IFIFO) {
- return FN_FILE;
-#endif
- } else {
- return FN_ERROR;
- }
-}
-
-/** Check whether <b>dirname</b> exists and is private. If yes return 0.
- * If <b>dirname</b> does not exist:
- * - if <b>check</b>&CPD_CREATE, try to create it and return 0 on success.
- * - if <b>check</b>&CPD_CHECK, and we think we can create it, return 0.
- * - if <b>check</b>&CPD_CHECK is false, and the directory exists, return 0.
- * - otherwise, return -1.
- * If CPD_GROUP_OK is set, then it's okay if the directory
- * is group-readable, but in all cases we create the directory mode 0700.
- * If CPD_GROUP_READ is set, existing directory behaves as CPD_GROUP_OK and
- * if the directory is created it will use mode 0750 with group read
- * permission. Group read privileges also assume execute permission
- * as norm for directories. If CPD_CHECK_MODE_ONLY is set, then we don't
- * alter the directory permissions if they are too permissive:
- * we just return -1.
- * When effective_user is not NULL, check permissions against the given user
- * and its primary group.
- */
-MOCK_IMPL(int,
-check_private_dir,(const char *dirname, cpd_check_t check,
- const char *effective_user))
-{
- int r;
- struct stat st;
-
- tor_assert(dirname);
-
-#ifndef _WIN32
- int fd;
- const struct passwd *pw = NULL;
- uid_t running_uid;
- gid_t running_gid;
-
- /*
- * Goal is to harden the implementation by removing any
- * potential for race between stat() and chmod().
- * chmod() accepts filename as argument. If an attacker can move
- * the file between stat() and chmod(), a potential race exists.
- *
- * Several suggestions taken from:
- * https://developer.apple.com/library/mac/documentation/
- * Security/Conceptual/SecureCodingGuide/Articles/RaceConditions.html
- */
-
- /* Open directory.
- * O_NOFOLLOW to ensure that it does not follow symbolic links */
- fd = open(sandbox_intern_string(dirname), O_NOFOLLOW);
-
- /* Was there an error? Maybe the directory does not exist? */
- if (fd == -1) {
-
- if (errno != ENOENT) {
- /* Other directory error */
- log_warn(LD_FS, "Directory %s cannot be read: %s", dirname,
- strerror(errno));
- return -1;
- }
-
- /* Received ENOENT: Directory does not exist */
-
- /* Should we create the directory? */
- if (check & CPD_CREATE) {
- log_info(LD_GENERAL, "Creating directory %s", dirname);
- if (check & CPD_GROUP_READ) {
- r = mkdir(dirname, 0750);
- } else {
- r = mkdir(dirname, 0700);
- }
-
- /* check for mkdir() error */
- if (r) {
- log_warn(LD_FS, "Error creating directory %s: %s", dirname,
- strerror(errno));
- return -1;
- }
-
- /* we just created the directory. try to open it again.
- * permissions on the directory will be checked again below.*/
- fd = open(sandbox_intern_string(dirname), O_NOFOLLOW);
-
- if (fd == -1) {
- log_warn(LD_FS, "Could not reopen recently created directory %s: %s",
- dirname,
- strerror(errno));
- return -1;
- } else {
- close(fd);
- }
-
- } else if (!(check & CPD_CHECK)) {
- log_warn(LD_FS, "Directory %s does not exist.", dirname);
- return -1;
- }
-
- /* XXXX In the case where check==CPD_CHECK, we should look at the
- * parent directory a little harder. */
- return 0;
- }
-
- tor_assert(fd >= 0);
-
- //f = tor_strdup(dirname);
- //clean_name_for_stat(f);
- log_debug(LD_FS, "stat()ing %s", dirname);
- //r = stat(sandbox_intern_string(f), &st);
- r = fstat(fd, &st);
- if (r == -1) {
- log_warn(LD_FS, "fstat() on directory %s failed.", dirname);
- close(fd);
- return -1;
- }
- //tor_free(f);
-
- /* check that dirname is a directory */
- if (!(st.st_mode & S_IFDIR)) {
- log_warn(LD_FS, "%s is not a directory", dirname);
- close(fd);
- return -1;
- }
-
- if (effective_user) {
- /* Look up the user and group information.
- * If we have a problem, bail out. */
- pw = tor_getpwnam(effective_user);
- if (pw == NULL) {
- log_warn(LD_CONFIG, "Error setting configured user: %s not found",
- effective_user);
- close(fd);
- return -1;
- }
- running_uid = pw->pw_uid;
- running_gid = pw->pw_gid;
- } else {
- running_uid = getuid();
- running_gid = getgid();
- }
- if (st.st_uid != running_uid) {
- char *process_ownername = NULL, *file_ownername = NULL;
-
- {
- const struct passwd *pw_running = tor_getpwuid(running_uid);
- process_ownername = pw_running ? tor_strdup(pw_running->pw_name) :
- tor_strdup("<unknown>");
- }
-
- {
- const struct passwd *pw_stat = tor_getpwuid(st.st_uid);
- file_ownername = pw_stat ? tor_strdup(pw_stat->pw_name) :
- tor_strdup("<unknown>");
- }
-
- log_warn(LD_FS, "%s is not owned by this user (%s, %d) but by "
- "%s (%d). Perhaps you are running Tor as the wrong user?",
- dirname, process_ownername, (int)running_uid,
- file_ownername, (int)st.st_uid);
-
- tor_free(process_ownername);
- tor_free(file_ownername);
- close(fd);
- return -1;
- }
- if ( (check & (CPD_GROUP_OK|CPD_GROUP_READ))
- && (st.st_gid != running_gid) && (st.st_gid != 0)) {
- struct group *gr;
- char *process_groupname = NULL;
- gr = getgrgid(running_gid);
- process_groupname = gr ? tor_strdup(gr->gr_name) : tor_strdup("<unknown>");
- gr = getgrgid(st.st_gid);
-
- log_warn(LD_FS, "%s is not owned by this group (%s, %d) but by group "
- "%s (%d). Are you running Tor as the wrong user?",
- dirname, process_groupname, (int)running_gid,
- gr ? gr->gr_name : "<unknown>", (int)st.st_gid);
-
- tor_free(process_groupname);
- close(fd);
- return -1;
- }
- unsigned unwanted_bits = 0;
- if (check & (CPD_GROUP_OK|CPD_GROUP_READ)) {
- unwanted_bits = 0027;
- } else {
- unwanted_bits = 0077;
- }
- unsigned check_bits_filter = ~0;
- if (check & CPD_RELAX_DIRMODE_CHECK) {
- check_bits_filter = 0022;
- }
- if ((st.st_mode & unwanted_bits & check_bits_filter) != 0) {
- unsigned new_mode;
- if (check & CPD_CHECK_MODE_ONLY) {
- log_warn(LD_FS, "Permissions on directory %s are too permissive.",
- dirname);
- close(fd);
- return -1;
- }
- log_warn(LD_FS, "Fixing permissions on directory %s", dirname);
- new_mode = st.st_mode;
- new_mode |= 0700; /* Owner should have rwx */
- if (check & CPD_GROUP_READ) {
- new_mode |= 0050; /* Group should have rx */
- }
- new_mode &= ~unwanted_bits; /* Clear the bits that we didn't want set...*/
- if (fchmod(fd, new_mode)) {
- log_warn(LD_FS, "Could not chmod directory %s: %s", dirname,
- strerror(errno));
- close(fd);
- return -1;
- } else {
- close(fd);
- return 0;
- }
- }
- close(fd);
-#else /* !(!defined(_WIN32)) */
- /* Win32 case: we can't open() a directory. */
- (void)effective_user;
-
- char *f = tor_strdup(dirname);
- clean_name_for_stat(f);
- log_debug(LD_FS, "stat()ing %s", f);
- r = stat(sandbox_intern_string(f), &st);
- tor_free(f);
- if (r) {
- if (errno != ENOENT) {
- log_warn(LD_FS, "Directory %s cannot be read: %s", dirname,
- strerror(errno));
- return -1;
- }
- if (check & CPD_CREATE) {
- log_info(LD_GENERAL, "Creating directory %s", dirname);
- r = mkdir(dirname);
- if (r) {
- log_warn(LD_FS, "Error creating directory %s: %s", dirname,
- strerror(errno));
- return -1;
- }
- } else if (!(check & CPD_CHECK)) {
- log_warn(LD_FS, "Directory %s does not exist.", dirname);
- return -1;
- }
- return 0;
- }
- if (!(st.st_mode & S_IFDIR)) {
- log_warn(LD_FS, "%s is not a directory", dirname);
- return -1;
- }
-
-#endif /* !defined(_WIN32) */
- return 0;
-}
-
-/** 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.
- *
- * This function replaces the old file atomically, if possible. This
- * function, and all other functions in util.c that create files, create them
- * with mode 0600.
- */
-MOCK_IMPL(int,
-write_str_to_file,(const char *fname, const char *str, int bin))
-{
-#ifdef _WIN32
- if (!bin && strchr(str, '\r')) {
- log_warn(LD_BUG,
- "We're writing a text string that already contains a CR to %s",
- escaped(fname));
- }
-#endif /* defined(_WIN32) */
- return write_bytes_to_file(fname, str, strlen(str), bin);
-}
-
-/** Represents a file that we're writing to, with support for atomic commit:
- * we can write into a temporary file, and either remove the file on
- * failure, or replace the original file on success. */
-struct open_file_t {
- char *tempname; /**< Name of the temporary file. */
- char *filename; /**< Name of the original file. */
- unsigned rename_on_close:1; /**< Are we using the temporary file or not? */
- unsigned binary:1; /**< Did we open in binary mode? */
- int fd; /**< fd for the open file. */
- FILE *stdio_file; /**< stdio wrapper for <b>fd</b>. */
-};
-
-/** Try to start writing to the file in <b>fname</b>, passing the flags
- * <b>open_flags</b> to the open() syscall, creating the file (if needed) with
- * access value <b>mode</b>. If the O_APPEND flag is set, we append to the
- * original file. Otherwise, we open a new temporary file in the same
- * directory, and either replace the original or remove the temporary file
- * when we're done.
- *
- * Return the fd for the newly opened file, and store working data in
- * *<b>data_out</b>. The caller should not close the fd manually:
- * instead, call finish_writing_to_file() or abort_writing_to_file().
- * Returns -1 on failure.
- *
- * NOTE: When not appending, the flags O_CREAT and O_TRUNC are treated
- * as true and the flag O_EXCL is treated as false.
- *
- * NOTE: Ordinarily, O_APPEND means "seek to the end of the file before each
- * write()". We don't do that.
- */
-int
-start_writing_to_file(const char *fname, int open_flags, int mode,
- open_file_t **data_out)
-{
- open_file_t *new_file = tor_malloc_zero(sizeof(open_file_t));
- const char *open_name;
- int append = 0;
-
- tor_assert(fname);
- tor_assert(data_out);
-#if (O_BINARY != 0 && O_TEXT != 0)
- tor_assert((open_flags & (O_BINARY|O_TEXT)) != 0);
-#endif
- new_file->fd = -1;
- new_file->filename = tor_strdup(fname);
- if (open_flags & O_APPEND) {
- open_name = fname;
- new_file->rename_on_close = 0;
- append = 1;
- open_flags &= ~O_APPEND;
- } else {
- tor_asprintf(&new_file->tempname, "%s.tmp", fname);
- open_name = new_file->tempname;
- /* We always replace an existing temporary file if there is one. */
- open_flags |= O_CREAT|O_TRUNC;
- open_flags &= ~O_EXCL;
- new_file->rename_on_close = 1;
- }
-#if O_BINARY != 0
- if (open_flags & O_BINARY)
- new_file->binary = 1;
-#endif
-
- new_file->fd = tor_open_cloexec(open_name, open_flags, mode);
- if (new_file->fd < 0) {
- log_warn(LD_FS, "Couldn't open \"%s\" (%s) for writing: %s",
- open_name, fname, strerror(errno));
- goto err;
- }
- if (append) {
- if (tor_fd_seekend(new_file->fd) < 0) {
- log_warn(LD_FS, "Couldn't seek to end of file \"%s\": %s", open_name,
- strerror(errno));
- goto err;
- }
- }
-
- *data_out = new_file;
-
- return new_file->fd;
-
- err:
- if (new_file->fd >= 0)
- close(new_file->fd);
- *data_out = NULL;
- tor_free(new_file->filename);
- tor_free(new_file->tempname);
- tor_free(new_file);
- return -1;
-}
-
-/** Given <b>file_data</b> from start_writing_to_file(), return a stdio FILE*
- * that can be used to write to the same file. The caller should not mix
- * stdio calls with non-stdio calls. */
-FILE *
-fdopen_file(open_file_t *file_data)
-{
- tor_assert(file_data);
- if (file_data->stdio_file)
- return file_data->stdio_file;
- tor_assert(file_data->fd >= 0);
- if (!(file_data->stdio_file = fdopen(file_data->fd,
- file_data->binary?"ab":"a"))) {
- log_warn(LD_FS, "Couldn't fdopen \"%s\" [%d]: %s", file_data->filename,
- file_data->fd, strerror(errno));
- }
- return file_data->stdio_file;
-}
-
-/** Combines start_writing_to_file with fdopen_file(): arguments are as
- * for start_writing_to_file, but */
-FILE *
-start_writing_to_stdio_file(const char *fname, int open_flags, int mode,
- open_file_t **data_out)
-{
- FILE *res;
- if (start_writing_to_file(fname, open_flags, mode, data_out)<0)
- return NULL;
- if (!(res = fdopen_file(*data_out))) {
- abort_writing_to_file(*data_out);
- *data_out = NULL;
- }
- return res;
-}
-
-/** Helper function: close and free the underlying file and memory in
- * <b>file_data</b>. If we were writing into a temporary file, then delete
- * that file (if abort_write is true) or replaces the target file with
- * the temporary file (if abort_write is false). */
-static int
-finish_writing_to_file_impl(open_file_t *file_data, int abort_write)
-{
- int r = 0;
-
- tor_assert(file_data && file_data->filename);
- if (file_data->stdio_file) {
- if (fclose(file_data->stdio_file)) {
- log_warn(LD_FS, "Error closing \"%s\": %s", file_data->filename,
- strerror(errno));
- abort_write = r = -1;
- }
- } else if (file_data->fd >= 0 && close(file_data->fd) < 0) {
- log_warn(LD_FS, "Error flushing \"%s\": %s", file_data->filename,
- strerror(errno));
- abort_write = r = -1;
- }
-
- if (file_data->rename_on_close) {
- tor_assert(file_data->tempname && file_data->filename);
- if (!abort_write) {
- tor_assert(strcmp(file_data->filename, file_data->tempname));
- if (replace_file(file_data->tempname, file_data->filename)) {
- log_warn(LD_FS, "Error replacing \"%s\": %s", file_data->filename,
- strerror(errno));
- abort_write = r = -1;
- }
- }
- if (abort_write) {
- int res = unlink(file_data->tempname);
- if (res != 0) {
- /* We couldn't unlink and we'll leave a mess behind */
- log_warn(LD_FS, "Failed to unlink %s: %s",
- file_data->tempname, strerror(errno));
- r = -1;
- }
- }
- }
-
- tor_free(file_data->filename);
- tor_free(file_data->tempname);
- tor_free(file_data);
-
- return r;
-}
-
-/** Finish writing to <b>file_data</b>: close the file handle, free memory as
- * needed, and if using a temporary file, replace the original file with
- * the temporary file. */
-int
-finish_writing_to_file(open_file_t *file_data)
-{
- return finish_writing_to_file_impl(file_data, 0);
-}
-
-/** Finish writing to <b>file_data</b>: close the file handle, free memory as
- * needed, and if using a temporary file, delete it. */
-int
-abort_writing_to_file(open_file_t *file_data)
-{
- return finish_writing_to_file_impl(file_data, 1);
-}
-
-/** Helper: given a set of flags as passed to open(2), open the file
- * <b>fname</b> and write all the sized_chunk_t structs in <b>chunks</b> to
- * the file. Do so as atomically as possible e.g. by opening temp files and
- * renaming. */
-static int
-write_chunks_to_file_impl(const char *fname, const smartlist_t *chunks,
- int open_flags)
-{
- open_file_t *file = NULL;
- int fd;
- ssize_t result;
- fd = start_writing_to_file(fname, open_flags, 0600, &file);
- if (fd<0)
- return -1;
- SMARTLIST_FOREACH(chunks, sized_chunk_t *, chunk,
- {
- result = write_all(fd, chunk->bytes, chunk->len, 0);
- if (result < 0) {
- log_warn(LD_FS, "Error writing to \"%s\": %s", fname,
- strerror(errno));
- goto err;
- }
- tor_assert((size_t)result == chunk->len);
- });
-
- return finish_writing_to_file(file);
- err:
- abort_writing_to_file(file);
- return -1;
-}
-
-/** Given a smartlist of sized_chunk_t, write them to a file
- * <b>fname</b>, overwriting or creating the file as necessary.
- * If <b>no_tempfile</b> is 0 then the file will be written
- * atomically. */
-int
-write_chunks_to_file(const char *fname, const smartlist_t *chunks, int bin,
- int no_tempfile)
-{
- int flags = OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT);
-
- if (no_tempfile) {
- /* O_APPEND stops write_chunks_to_file from using tempfiles */
- flags |= O_APPEND;
- }
- return write_chunks_to_file_impl(fname, chunks, flags);
-}
-
-/** Write <b>len</b> bytes, starting at <b>str</b>, to <b>fname</b>
- using the open() flags passed in <b>flags</b>. */
-static int
-write_bytes_to_file_impl(const char *fname, const char *str, size_t len,
- int flags)
-{
- int r;
- sized_chunk_t c = { str, len };
- smartlist_t *chunks = smartlist_new();
- smartlist_add(chunks, &c);
- r = write_chunks_to_file_impl(fname, chunks, flags);
- smartlist_free(chunks);
- return r;
-}
-
-/** As write_str_to_file, but does not assume a NUL-terminated
- * string. Instead, we write <b>len</b> bytes, starting at <b>str</b>. */
-MOCK_IMPL(int,
-write_bytes_to_file,(const char *fname, const char *str, size_t len,
- int bin))
-{
- return write_bytes_to_file_impl(fname, str, len,
- OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT));
-}
-
-/** As write_bytes_to_file, but if the file already exists, append the bytes
- * to the end of the file instead of overwriting it. */
-int
-append_bytes_to_file(const char *fname, const char *str, size_t len,
- int bin)
-{
- return write_bytes_to_file_impl(fname, str, len,
- OPEN_FLAGS_APPEND|(bin?O_BINARY:O_TEXT));
-}
-
-/** Like write_str_to_file(), but also return -1 if there was a file
- already residing in <b>fname</b>. */
-int
-write_bytes_to_new_file(const char *fname, const char *str, size_t len,
- int bin)
-{
- return write_bytes_to_file_impl(fname, str, len,
- OPEN_FLAGS_DONT_REPLACE|
- (bin?O_BINARY:O_TEXT));
-}
-
-/**
- * Read the contents of the open file <b>fd</b> presuming it is a FIFO
- * (or similar) file descriptor for which the size of the file isn't
- * known ahead of time. Return NULL on failure, and a NUL-terminated
- * string on success. On success, set <b>sz_out</b> to the number of
- * bytes read.
- */
-char *
-read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out)
-{
- ssize_t r;
- size_t pos = 0;
- char *string = NULL;
- size_t string_max = 0;
-
- if (max_bytes_to_read+1 >= SIZE_T_CEILING) {
- errno = EINVAL;
- return NULL;
- }
-
- do {
- /* XXXX This "add 1K" approach is a little goofy; if we care about
- * performance here, we should be doubling. But in practice we shouldn't
- * be using this function on big files anyway. */
- string_max = pos + 1024;
- if (string_max > max_bytes_to_read)
- string_max = max_bytes_to_read + 1;
- string = tor_realloc(string, string_max);
- r = read(fd, string + pos, string_max - pos - 1);
- if (r < 0) {
- int save_errno = errno;
- tor_free(string);
- errno = save_errno;
- return NULL;
- }
-
- pos += r;
- } while (r > 0 && pos < max_bytes_to_read);
-
- tor_assert(pos < string_max);
- *sz_out = pos;
- string[pos] = '\0';
- return string;
-}
-
-/** Read the contents of <b>filename</b> into a newly allocated
- * string; return the string on success or NULL on failure.
- *
- * If <b>stat_out</b> is provided, store the result of stat()ing the
- * file into <b>stat_out</b>.
- *
- * If <b>flags</b> &amp; RFTS_BIN, open the file in binary mode.
- * If <b>flags</b> &amp; RFTS_IGNORE_MISSING, don't warn if the file
- * doesn't exist.
- */
-/*
- * This function <em>may</em> return an erroneous result if the file
- * is modified while it is running, but must not crash or overflow.
- * Right now, the error case occurs when the file length grows between
- * the call to stat and the call to read_all: the resulting string will
- * be truncated.
- */
-MOCK_IMPL(char *,
-read_file_to_str, (const char *filename, int flags, struct stat *stat_out))
-{
- int fd; /* router file */
- struct stat statbuf;
- char *string;
- ssize_t r;
- int bin = flags & RFTS_BIN;
-
- tor_assert(filename);
-
- fd = tor_open_cloexec(filename,O_RDONLY|(bin?O_BINARY:O_TEXT),0);
- if (fd<0) {
- int severity = LOG_WARN;
- int save_errno = errno;
- if (errno == ENOENT && (flags & RFTS_IGNORE_MISSING))
- severity = LOG_INFO;
- log_fn(severity, LD_FS,"Could not open \"%s\": %s",filename,
- strerror(errno));
- errno = save_errno;
- return NULL;
- }
-
- if (fstat(fd, &statbuf)<0) {
- int save_errno = errno;
- close(fd);
- log_warn(LD_FS,"Could not fstat \"%s\".",filename);
- errno = save_errno;
- return NULL;
- }
-
-#ifndef _WIN32
-/** When we detect that we're reading from a FIFO, don't read more than
- * this many bytes. It's insane overkill for most uses. */
-#define FIFO_READ_MAX (1024*1024)
- if (S_ISFIFO(statbuf.st_mode)) {
- size_t sz = 0;
- string = read_file_to_str_until_eof(fd, FIFO_READ_MAX, &sz);
- int save_errno = errno;
- if (string && stat_out) {
- statbuf.st_size = sz;
- memcpy(stat_out, &statbuf, sizeof(struct stat));
- }
- close(fd);
- if (!string)
- errno = save_errno;
- return string;
- }
-#endif /* !defined(_WIN32) */
-
- if ((uint64_t)(statbuf.st_size)+1 >= SIZE_T_CEILING) {
- close(fd);
- errno = EINVAL;
- return NULL;
- }
-
- string = tor_malloc((size_t)(statbuf.st_size+1));
-
- r = read_all(fd,string,(size_t)statbuf.st_size,0);
- if (r<0) {
- int save_errno = errno;
- log_warn(LD_FS,"Error reading from file \"%s\": %s", filename,
- strerror(errno));
- tor_free(string);
- close(fd);
- errno = save_errno;
- return NULL;
- }
- string[r] = '\0'; /* NUL-terminate the result. */
-
-#if defined(_WIN32) || defined(__CYGWIN__)
- if (!bin && strchr(string, '\r')) {
- log_debug(LD_FS, "We didn't convert CRLF to LF as well as we hoped "
- "when reading %s. Coping.",
- filename);
- tor_strstrip(string, "\r");
- r = strlen(string);
- }
- if (!bin) {
- statbuf.st_size = (size_t) r;
- } else
-#endif /* defined(_WIN32) || defined(__CYGWIN__) */
- if (r != statbuf.st_size) {
- /* Unless we're using text mode on win32, we'd better have an exact
- * match for size. */
- int save_errno = errno;
- log_warn(LD_FS,"Could read only %d of %ld bytes of file \"%s\".",
- (int)r, (long)statbuf.st_size,filename);
- tor_free(string);
- close(fd);
- errno = save_errno;
- return NULL;
- }
- close(fd);
- if (stat_out) {
- memcpy(stat_out, &statbuf, sizeof(struct stat));
- }
-
- return string;
-}
-
-#define TOR_ISODIGIT(c) ('0' <= (c) && (c) <= '7')
-
-/** Given a c-style double-quoted escaped string in <b>s</b>, extract and
- * decode its contents into a newly allocated string. On success, assign this
- * string to *<b>result</b>, assign its length to <b>size_out</b> (if
- * provided), and return a pointer to the position in <b>s</b> immediately
- * after the string. On failure, return NULL.
- */
-const char *
-unescape_string(const char *s, char **result, size_t *size_out)
-{
- const char *cp;
- char *out;
- if (s[0] != '\"')
- return NULL;
- cp = s+1;
- while (1) {
- switch (*cp) {
- case '\0':
- case '\n':
- return NULL;
- case '\"':
- goto end_of_loop;
- case '\\':
- if (cp[1] == 'x' || cp[1] == 'X') {
- if (!(TOR_ISXDIGIT(cp[2]) && TOR_ISXDIGIT(cp[3])))
- return NULL;
- cp += 4;
- } else if (TOR_ISODIGIT(cp[1])) {
- cp += 2;
- if (TOR_ISODIGIT(*cp)) ++cp;
- if (TOR_ISODIGIT(*cp)) ++cp;
- } else if (cp[1] == 'n' || cp[1] == 'r' || cp[1] == 't' || cp[1] == '"'
- || cp[1] == '\\' || cp[1] == '\'') {
- cp += 2;
- } else {
- return NULL;
- }
- break;
- default:
- ++cp;
- break;
- }
- }
- end_of_loop:
- out = *result = tor_malloc(cp-s + 1);
- cp = s+1;
- while (1) {
- switch (*cp)
- {
- case '\"':
- *out = '\0';
- if (size_out) *size_out = out - *result;
- return cp+1;
-
- /* LCOV_EXCL_START -- we caught this in parse_config_from_line. */
- case '\0':
- tor_fragile_assert();
- tor_free(*result);
- return NULL;
- /* LCOV_EXCL_STOP */
- case '\\':
- switch (cp[1])
- {
- case 'n': *out++ = '\n'; cp += 2; break;
- case 'r': *out++ = '\r'; cp += 2; break;
- case 't': *out++ = '\t'; cp += 2; break;
- case 'x': case 'X':
- {
- int x1, x2;
-
- x1 = hex_decode_digit(cp[2]);
- x2 = hex_decode_digit(cp[3]);
- if (x1 == -1 || x2 == -1) {
- /* LCOV_EXCL_START */
- /* we caught this above in the initial loop. */
- tor_assert_nonfatal_unreached();
- tor_free(*result);
- return NULL;
- /* LCOV_EXCL_STOP */
- }
-
- *out++ = ((x1<<4) + x2);
- cp += 4;
- }
- break;
- case '0': case '1': case '2': case '3': case '4': case '5':
- case '6': case '7':
- {
- int n = cp[1]-'0';
- cp += 2;
- if (TOR_ISODIGIT(*cp)) { n = n*8 + *cp-'0'; cp++; }
- if (TOR_ISODIGIT(*cp)) { n = n*8 + *cp-'0'; cp++; }
- if (n > 255) { tor_free(*result); return NULL; }
- *out++ = (char)n;
- }
- break;
- case '\'':
- case '\"':
- case '\\':
- case '\?':
- *out++ = cp[1];
- cp += 2;
- break;
-
- /* LCOV_EXCL_START */
- default:
- /* we caught this above in the initial loop. */
- tor_assert_nonfatal_unreached();
- tor_free(*result); return NULL;
- /* LCOV_EXCL_STOP */
- }
- break;
- default:
- *out++ = *cp++;
- }
- }
-}
-
-/** Removes enclosing quotes from <b>path</b> and unescapes quotes between the
- * enclosing quotes. Backslashes are not unescaped. Return the unquoted
- * <b>path</b> on success or 0 if <b>path</b> is not quoted correctly. */
-char *
-get_unquoted_path(const char *path)
-{
- size_t len = strlen(path);
-
- if (len == 0) {
- return tor_strdup("");
- }
-
- int has_start_quote = (path[0] == '\"');
- int has_end_quote = (len > 0 && path[len-1] == '\"');
- if (has_start_quote != has_end_quote || (len == 1 && has_start_quote)) {
- return NULL;
- }
-
- char *unquoted_path = tor_malloc(len - has_start_quote - has_end_quote + 1);
- char *s = unquoted_path;
- size_t i;
- for (i = has_start_quote; i < len - has_end_quote; i++) {
- if (path[i] == '\"' && (i > 0 && path[i-1] == '\\')) {
- *(s-1) = path[i];
- } else if (path[i] != '\"') {
- *s++ = path[i];
- } else { /* unescaped quote */
- tor_free(unquoted_path);
- return NULL;
- }
- }
- *s = '\0';
- return unquoted_path;
-}
-
-/** Expand any homedir prefix on <b>filename</b>; return a newly allocated
- * string. */
-char *
-expand_filename(const char *filename)
-{
- tor_assert(filename);
-#ifdef _WIN32
- /* Might consider using GetFullPathName() as described here:
- * http://etutorials.org/Programming/secure+programming/
- * Chapter+3.+Input+Validation/3.7+Validating+Filenames+and+Paths/
- */
- return tor_strdup(filename);
-#else /* !(defined(_WIN32)) */
- if (*filename == '~') {
- char *home, *result=NULL;
- const char *rest;
-
- if (filename[1] == '/' || filename[1] == '\0') {
- home = getenv("HOME");
- if (!home) {
- log_warn(LD_CONFIG, "Couldn't find $HOME environment variable while "
- "expanding \"%s\"; defaulting to \"\".", filename);
- home = tor_strdup("");
- } else {
- home = tor_strdup(home);
- }
- rest = strlen(filename)>=2?(filename+2):"";
- } else {
-#ifdef HAVE_PWD_H
- char *username, *slash;
- slash = strchr(filename, '/');
- if (slash)
- username = tor_strndup(filename+1,slash-filename-1);
- else
- username = tor_strdup(filename+1);
- if (!(home = get_user_homedir(username))) {
- log_warn(LD_CONFIG,"Couldn't get homedir for \"%s\"",username);
- tor_free(username);
- return NULL;
- }
- tor_free(username);
- rest = slash ? (slash+1) : "";
-#else /* !(defined(HAVE_PWD_H)) */
- log_warn(LD_CONFIG, "Couldn't expand homedir on system without pwd.h");
- return tor_strdup(filename);
-#endif /* defined(HAVE_PWD_H) */
- }
- tor_assert(home);
- /* Remove trailing slash. */
- if (strlen(home)>1 && !strcmpend(home,PATH_SEPARATOR)) {
- home[strlen(home)-1] = '\0';
- }
- tor_asprintf(&result,"%s"PATH_SEPARATOR"%s",home,rest);
- tor_free(home);
- return result;
- } else {
- return tor_strdup(filename);
- }
-#endif /* defined(_WIN32) */
-}
-
-#define MAX_SCANF_WIDTH 9999
-
-/** Helper: given an ASCII-encoded decimal digit, return its numeric value.
- * NOTE: requires that its input be in-bounds. */
-static int
-digit_to_num(char d)
-{
- int num = ((int)d) - (int)'0';
- tor_assert(num <= 9 && num >= 0);
- return num;
-}
-
-/** Helper: Read an unsigned int from *<b>bufp</b> of up to <b>width</b>
- * characters. (Handle arbitrary width if <b>width</b> is less than 0.) On
- * success, store the result in <b>out</b>, advance bufp to the next
- * character, and return 0. On failure, return -1. */
-static int
-scan_unsigned(const char **bufp, unsigned long *out, int width, unsigned base)
-{
- unsigned long result = 0;
- int scanned_so_far = 0;
- const int hex = base==16;
- tor_assert(base == 10 || base == 16);
- if (!bufp || !*bufp || !out)
- return -1;
- if (width<0)
- width=MAX_SCANF_WIDTH;
-
- while (**bufp && (hex?TOR_ISXDIGIT(**bufp):TOR_ISDIGIT(**bufp))
- && scanned_so_far < width) {
- unsigned digit = hex?hex_decode_digit(*(*bufp)++):digit_to_num(*(*bufp)++);
- // Check for overflow beforehand, without actually causing any overflow
- // This preserves functionality on compilers that don't wrap overflow
- // (i.e. that trap or optimise away overflow)
- // result * base + digit > ULONG_MAX
- // result * base > ULONG_MAX - digit
- if (result > (ULONG_MAX - digit)/base)
- return -1; /* Processing this digit would overflow */
- result = result * base + digit;
- ++scanned_so_far;
- }
-
- if (!scanned_so_far) /* No actual digits scanned */
- return -1;
-
- *out = result;
- return 0;
-}
-
-/** Helper: Read an signed int from *<b>bufp</b> of up to <b>width</b>
- * characters. (Handle arbitrary width if <b>width</b> is less than 0.) On
- * success, store the result in <b>out</b>, advance bufp to the next
- * character, and return 0. On failure, return -1. */
-static int
-scan_signed(const char **bufp, long *out, int width)
-{
- int neg = 0;
- unsigned long result = 0;
-
- if (!bufp || !*bufp || !out)
- return -1;
- if (width<0)
- width=MAX_SCANF_WIDTH;
-
- if (**bufp == '-') {
- neg = 1;
- ++*bufp;
- --width;
- }
-
- if (scan_unsigned(bufp, &result, width, 10) < 0)
- return -1;
-
- if (neg && result > 0) {
- if (result > ((unsigned long)LONG_MAX) + 1)
- return -1; /* Underflow */
- else if (result == ((unsigned long)LONG_MAX) + 1)
- *out = LONG_MIN;
- else {
- /* We once had a far more clever no-overflow conversion here, but
- * some versions of GCC apparently ran it into the ground. Now
- * we just check for LONG_MIN explicitly.
- */
- *out = -(long)result;
- }
- } else {
- if (result > LONG_MAX)
- return -1; /* Overflow */
- *out = (long)result;
- }
-
- return 0;
-}
-
-/** Helper: Read a decimal-formatted double from *<b>bufp</b> of up to
- * <b>width</b> characters. (Handle arbitrary width if <b>width</b> is less
- * than 0.) On success, store the result in <b>out</b>, advance bufp to the
- * next character, and return 0. On failure, return -1. */
-static int
-scan_double(const char **bufp, double *out, int width)
-{
- int neg = 0;
- double result = 0;
- int scanned_so_far = 0;
-
- if (!bufp || !*bufp || !out)
- return -1;
- if (width<0)
- width=MAX_SCANF_WIDTH;
-
- if (**bufp == '-') {
- neg = 1;
- ++*bufp;
- }
-
- while (**bufp && TOR_ISDIGIT(**bufp) && scanned_so_far < width) {
- const int digit = digit_to_num(*(*bufp)++);
- result = result * 10 + digit;
- ++scanned_so_far;
- }
- if (**bufp == '.') {
- double fracval = 0, denominator = 1;
- ++*bufp;
- ++scanned_so_far;
- while (**bufp && TOR_ISDIGIT(**bufp) && scanned_so_far < width) {
- const int digit = digit_to_num(*(*bufp)++);
- fracval = fracval * 10 + digit;
- denominator *= 10;
- ++scanned_so_far;
- }
- result += fracval / denominator;
- }
-
- if (!scanned_so_far) /* No actual digits scanned */
- return -1;
-
- *out = neg ? -result : result;
- return 0;
-}
-
-/** Helper: copy up to <b>width</b> non-space characters from <b>bufp</b> to
- * <b>out</b>. Make sure <b>out</b> is nul-terminated. Advance <b>bufp</b>
- * to the next non-space character or the EOS. */
-static int
-scan_string(const char **bufp, char *out, int width)
-{
- int scanned_so_far = 0;
- if (!bufp || !out || width < 0)
- return -1;
- while (**bufp && ! TOR_ISSPACE(**bufp) && scanned_so_far < width) {
- *out++ = *(*bufp)++;
- ++scanned_so_far;
- }
- *out = '\0';
- return 0;
-}
-
-/** Locale-independent, minimal, no-surprises scanf variant, accepting only a
- * restricted pattern format. For more info on what it supports, see
- * tor_sscanf() documentation. */
-int
-tor_vsscanf(const char *buf, const char *pattern, va_list ap)
-{
- int n_matched = 0;
-
- while (*pattern) {
- if (*pattern != '%') {
- if (*buf == *pattern) {
- ++buf;
- ++pattern;
- continue;
- } else {
- return n_matched;
- }
- } else {
- int width = -1;
- int longmod = 0;
- ++pattern;
- if (TOR_ISDIGIT(*pattern)) {
- width = digit_to_num(*pattern++);
- while (TOR_ISDIGIT(*pattern)) {
- width *= 10;
- width += digit_to_num(*pattern++);
- if (width > MAX_SCANF_WIDTH)
- return -1;
- }
- if (!width) /* No zero-width things. */
- return -1;
- }
- if (*pattern == 'l') {
- longmod = 1;
- ++pattern;
- }
- if (*pattern == 'u' || *pattern == 'x') {
- unsigned long u;
- const int base = (*pattern == 'u') ? 10 : 16;
- if (!*buf)
- return n_matched;
- if (scan_unsigned(&buf, &u, width, base)<0)
- return n_matched;
- if (longmod) {
- unsigned long *out = va_arg(ap, unsigned long *);
- *out = u;
- } else {
- unsigned *out = va_arg(ap, unsigned *);
- if (u > UINT_MAX)
- return n_matched;
- *out = (unsigned) u;
- }
- ++pattern;
- ++n_matched;
- } else if (*pattern == 'f') {
- double *d = va_arg(ap, double *);
- if (!longmod)
- return -1; /* float not supported */
- if (!*buf)
- return n_matched;
- if (scan_double(&buf, d, width)<0)
- return n_matched;
- ++pattern;
- ++n_matched;
- } else if (*pattern == 'd') {
- long lng=0;
- if (scan_signed(&buf, &lng, width)<0)
- return n_matched;
- if (longmod) {
- long *out = va_arg(ap, long *);
- *out = lng;
- } else {
- int *out = va_arg(ap, int *);
-#if LONG_MAX > INT_MAX
- if (lng < INT_MIN || lng > INT_MAX)
- return n_matched;
-#endif
- *out = (int)lng;
- }
- ++pattern;
- ++n_matched;
- } else if (*pattern == 's') {
- char *s = va_arg(ap, char *);
- if (longmod)
- return -1;
- if (width < 0)
- return -1;
- if (scan_string(&buf, s, width)<0)
- return n_matched;
- ++pattern;
- ++n_matched;
- } else if (*pattern == 'c') {
- char *ch = va_arg(ap, char *);
- if (longmod)
- return -1;
- if (width != -1)
- return -1;
- if (!*buf)
- return n_matched;
- *ch = *buf++;
- ++pattern;
- ++n_matched;
- } else if (*pattern == '%') {
- if (*buf != '%')
- return n_matched;
- if (longmod)
- return -1;
- ++buf;
- ++pattern;
- } else {
- return -1; /* Unrecognized pattern component. */
- }
- }
- }
-
- return n_matched;
-}
-
-/** Minimal sscanf replacement: parse <b>buf</b> according to <b>pattern</b>
- * and store the results in the corresponding argument fields. Differs from
- * sscanf in that:
- * <ul><li>It only handles %u, %lu, %x, %lx, %[NUM]s, %d, %ld, %lf, and %c.
- * <li>It only handles decimal inputs for %lf. (12.3, not 1.23e1)
- * <li>It does not handle arbitrarily long widths.
- * <li>Numbers do not consume any space characters.
- * <li>It is locale-independent.
- * <li>%u and %x do not consume any space.
- * <li>It returns -1 on malformed patterns.</ul>
- *
- * (As with other locale-independent functions, we need this to parse data that
- * is in ASCII without worrying that the C library's locale-handling will make
- * miscellaneous characters look like numbers, spaces, and so on.)
- */
-int
-tor_sscanf(const char *buf, const char *pattern, ...)
-{
- int r;
- va_list ap;
- va_start(ap, pattern);
- r = tor_vsscanf(buf, pattern, ap);
- va_end(ap);
- return r;
-}
-
-/** Append the string produced by tor_asprintf(<b>pattern</b>, <b>...</b>)
- * to <b>sl</b>. */
-void
-smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern, ...)
-{
- va_list ap;
- va_start(ap, pattern);
- smartlist_add_vasprintf(sl, pattern, ap);
- va_end(ap);
-}
-
-/** va_list-based backend of smartlist_add_asprintf. */
-void
-smartlist_add_vasprintf(struct smartlist_t *sl, const char *pattern,
- va_list args)
-{
- char *str = NULL;
-
- tor_vasprintf(&str, pattern, args);
- tor_assert(str != NULL);
-
- smartlist_add(sl, str);
-}
-
-/** Append a copy of string to sl */
-void
-smartlist_add_strdup(struct smartlist_t *sl, const char *string)
-{
- char *copy;
-
- copy = tor_strdup(string);
-
- smartlist_add(sl, copy);
-}
-
-/** Return a new list containing the filenames in the directory <b>dirname</b>.
- * Return NULL on error or if <b>dirname</b> is not a directory.
- */
-MOCK_IMPL(smartlist_t *,
-tor_listdir, (const char *dirname))
-{
- smartlist_t *result;
-#ifdef _WIN32
- char *pattern=NULL;
- TCHAR tpattern[MAX_PATH] = {0};
- char name[MAX_PATH*2+1] = {0};
- HANDLE handle;
- WIN32_FIND_DATA findData;
- tor_asprintf(&pattern, "%s\\*", dirname);
-#ifdef UNICODE
- mbstowcs(tpattern,pattern,MAX_PATH);
-#else
- strlcpy(tpattern, pattern, MAX_PATH);
-#endif
- if (INVALID_HANDLE_VALUE == (handle = FindFirstFile(tpattern, &findData))) {
- tor_free(pattern);
- return NULL;
- }
- result = smartlist_new();
- while (1) {
-#ifdef UNICODE
- wcstombs(name,findData.cFileName,MAX_PATH);
- name[sizeof(name)-1] = '\0';
-#else
- strlcpy(name,findData.cFileName,sizeof(name));
-#endif /* defined(UNICODE) */
- if (strcmp(name, ".") &&
- strcmp(name, "..")) {
- smartlist_add_strdup(result, name);
- }
- if (!FindNextFile(handle, &findData)) {
- DWORD err;
- if ((err = GetLastError()) != ERROR_NO_MORE_FILES) {
- char *errstr = format_win32_error(err);
- log_warn(LD_FS, "Error reading directory '%s': %s", dirname, errstr);
- tor_free(errstr);
- }
- break;
- }
- }
- FindClose(handle);
- tor_free(pattern);
-#else /* !(defined(_WIN32)) */
- const char *prot_dname = sandbox_intern_string(dirname);
- DIR *d;
- struct dirent *de;
- if (!(d = opendir(prot_dname)))
- return NULL;
-
- result = smartlist_new();
- while ((de = readdir(d))) {
- if (!strcmp(de->d_name, ".") ||
- !strcmp(de->d_name, ".."))
- continue;
- smartlist_add_strdup(result, de->d_name);
- }
- closedir(d);
-#endif /* defined(_WIN32) */
- return result;
-}
-
-/** Return true iff <b>filename</b> is a relative path. */
-int
-path_is_relative(const char *filename)
-{
- if (filename && filename[0] == '/')
- return 0;
-#ifdef _WIN32
- else if (filename && filename[0] == '\\')
- return 0;
- else if (filename && strlen(filename)>3 && TOR_ISALPHA(filename[0]) &&
- filename[1] == ':' && filename[2] == '\\')
- return 0;
-#endif /* defined(_WIN32) */
- else
- return 1;
-}
-
-/* =====
- * Process helpers
- * ===== */
-
-#ifndef _WIN32
-/* Based on code contributed by christian grothoff */
-/** True iff we've called start_daemon(). */
-static int start_daemon_called = 0;
-/** True iff we've called finish_daemon(). */
-static int finish_daemon_called = 0;
-/** Socketpair used to communicate between parent and child process while
- * daemonizing. */
-static int daemon_filedes[2];
-/** Start putting the process into daemon mode: fork and drop all resources
- * except standard fds. The parent process never returns, but stays around
- * until finish_daemon is called. (Note: it's safe to call this more
- * than once: calls after the first are ignored.)
- */
-void
-start_daemon(void)
-{
- pid_t pid;
-
- if (start_daemon_called)
- return;
- start_daemon_called = 1;
-
- if (pipe(daemon_filedes)) {
- /* LCOV_EXCL_START */
- log_err(LD_GENERAL,"pipe failed; exiting. Error was %s", strerror(errno));
- exit(1); // exit ok: during daemonize, pipe failed.
- /* LCOV_EXCL_STOP */
- }
- pid = fork();
- if (pid < 0) {
- /* LCOV_EXCL_START */
- log_err(LD_GENERAL,"fork failed. Exiting.");
- exit(1); // exit ok: during daemonize, fork failed
- /* LCOV_EXCL_STOP */
- }
- if (pid) { /* Parent */
- int ok;
- char c;
-
- close(daemon_filedes[1]); /* we only read */
- ok = -1;
- while (0 < read(daemon_filedes[0], &c, sizeof(char))) {
- if (c == '.')
- ok = 1;
- }
- fflush(stdout);
- if (ok == 1)
- exit(0); // exit ok: during daemonize, daemonizing.
- else
- exit(1); /* child reported error. exit ok: daemonize failed. */
- } else { /* Child */
- close(daemon_filedes[0]); /* we only write */
-
- (void) setsid(); /* Detach from controlling terminal */
- /*
- * Fork one more time, so the parent (the session group leader) can exit.
- * This means that we, as a non-session group leader, can never regain a
- * controlling terminal. This part is recommended by Stevens's
- * _Advanced Programming in the Unix Environment_.
- */
- if (fork() != 0) {
- exit(0); // exit ok: during daemonize, fork failed (2)
- }
- set_main_thread(); /* We are now the main thread. */
-
- return;
- }
-}
-
-/** Finish putting the process into daemon mode: drop standard fds, and tell
- * the parent process to exit. (Note: it's safe to call this more than once:
- * calls after the first are ignored. Calls start_daemon first if it hasn't
- * been called already.)
- */
-void
-finish_daemon(const char *desired_cwd)
-{
- int nullfd;
- char c = '.';
- if (finish_daemon_called)
- return;
- if (!start_daemon_called)
- start_daemon();
- finish_daemon_called = 1;
-
- if (!desired_cwd)
- desired_cwd = "/";
- /* Don't hold the wrong FS mounted */
- if (chdir(desired_cwd) < 0) {
- log_err(LD_GENERAL,"chdir to \"%s\" failed. Exiting.",desired_cwd);
- exit(1); // exit ok: during daemonize, chdir failed.
- }
-
- nullfd = tor_open_cloexec("/dev/null", O_RDWR, 0);
- if (nullfd < 0) {
- /* LCOV_EXCL_START */
- log_err(LD_GENERAL,"/dev/null can't be opened. Exiting.");
- exit(1); // exit ok: during daemonize, couldn't open /dev/null
- /* LCOV_EXCL_STOP */
- }
- /* close fds linking to invoking terminal, but
- * close usual incoming fds, but redirect them somewhere
- * useful so the fds don't get reallocated elsewhere.
- */
- if (dup2(nullfd,0) < 0 ||
- dup2(nullfd,1) < 0 ||
- dup2(nullfd,2) < 0) {
- /* LCOV_EXCL_START */
- log_err(LD_GENERAL,"dup2 failed. Exiting.");
- exit(1); // exit ok: during daemonize, dup2 failed.
- /* LCOV_EXCL_STOP */
- }
- if (nullfd > 2)
- close(nullfd);
- /* signal success */
- if (write(daemon_filedes[1], &c, sizeof(char)) != sizeof(char)) {
- log_err(LD_GENERAL,"write failed. Exiting.");
- }
- close(daemon_filedes[1]);
-}
-#else /* !(!defined(_WIN32)) */
-/* defined(_WIN32) */
-void
-start_daemon(void)
-{
-}
-void
-finish_daemon(const char *cp)
-{
- (void)cp;
-}
-#endif /* !defined(_WIN32) */
-
-/** Write the current process ID, followed by NL, into <b>filename</b>.
- * Return 0 on success, -1 on failure.
- */
-int
-write_pidfile(const char *filename)
-{
- FILE *pidfile;
-
- if ((pidfile = fopen(filename, "w")) == NULL) {
- log_warn(LD_FS, "Unable to open \"%s\" for writing: %s", filename,
- strerror(errno));
- return -1;
- } else {
-#ifdef _WIN32
- int pid = (int)_getpid();
-#else
- int pid = (int)getpid();
-#endif
- int rv = 0;
- if (fprintf(pidfile, "%d\n", pid) < 0)
- rv = -1;
- if (fclose(pidfile) < 0)
- rv = -1;
- return rv;
- }
-}
-
-#ifdef _WIN32
-HANDLE
-load_windows_system_library(const TCHAR *library_name)
-{
- TCHAR path[MAX_PATH];
- unsigned n;
- n = GetSystemDirectory(path, MAX_PATH);
- if (n == 0 || n + _tcslen(library_name) + 2 >= MAX_PATH)
- return 0;
- _tcscat(path, TEXT("\\"));
- _tcscat(path, library_name);
- return LoadLibrary(path);
-}
-#endif /* defined(_WIN32) */
-
-/** Format a single argument for being put on a Windows command line.
- * Returns a newly allocated string */
-static char *
-format_win_cmdline_argument(const char *arg)
-{
- char *formatted_arg;
- char need_quotes;
- const char *c;
- int i;
- int bs_counter = 0;
- /* Backslash we can point to when one is inserted into the string */
- const char backslash = '\\';
-
- /* Smartlist of *char */
- smartlist_t *arg_chars;
- arg_chars = smartlist_new();
-
- /* Quote string if it contains whitespace or is empty */
- need_quotes = (strchr(arg, ' ') || strchr(arg, '\t') || '\0' == arg[0]);
-
- /* Build up smartlist of *chars */
- for (c=arg; *c != '\0'; c++) {
- if ('"' == *c) {
- /* Double up backslashes preceding a quote */
- for (i=0; i<(bs_counter*2); i++)
- smartlist_add(arg_chars, (void*)&backslash);
- bs_counter = 0;
- /* Escape the quote */
- smartlist_add(arg_chars, (void*)&backslash);
- smartlist_add(arg_chars, (void*)c);
- } else if ('\\' == *c) {
- /* Count backslashes until we know whether to double up */
- bs_counter++;
- } else {
- /* Don't double up slashes preceding a non-quote */
- for (i=0; i<bs_counter; i++)
- smartlist_add(arg_chars, (void*)&backslash);
- bs_counter = 0;
- smartlist_add(arg_chars, (void*)c);
- }
- }
- /* Don't double up trailing backslashes */
- for (i=0; i<bs_counter; i++)
- smartlist_add(arg_chars, (void*)&backslash);
-
- /* Allocate space for argument, quotes (if needed), and terminator */
- const size_t formatted_arg_len = smartlist_len(arg_chars) +
- (need_quotes ? 2 : 0) + 1;
- formatted_arg = tor_malloc_zero(formatted_arg_len);
-
- /* Add leading quote */
- i=0;
- if (need_quotes)
- formatted_arg[i++] = '"';
-
- /* Add characters */
- SMARTLIST_FOREACH(arg_chars, char*, ch,
- {
- formatted_arg[i++] = *ch;
- });
-
- /* Add trailing quote */
- if (need_quotes)
- formatted_arg[i++] = '"';
- formatted_arg[i] = '\0';
-
- smartlist_free(arg_chars);
- return formatted_arg;
-}
-
-/** Format a command line for use on Windows, which takes the command as a
- * string rather than string array. Follows the rules from "Parsing C++
- * Command-Line Arguments" in MSDN. Algorithm based on list2cmdline in the
- * Python subprocess module. Returns a newly allocated string */
-char *
-tor_join_win_cmdline(const char *argv[])
-{
- smartlist_t *argv_list;
- char *joined_argv;
- int i;
-
- /* Format each argument and put the result in a smartlist */
- argv_list = smartlist_new();
- for (i=0; argv[i] != NULL; i++) {
- smartlist_add(argv_list, (void *)format_win_cmdline_argument(argv[i]));
- }
-
- /* Join the arguments with whitespace */
- joined_argv = smartlist_join_strings(argv_list, " ", 0, NULL);
-
- /* Free the newly allocated arguments, and the smartlist */
- SMARTLIST_FOREACH(argv_list, char *, arg,
- {
- tor_free(arg);
- });
- smartlist_free(argv_list);
-
- return joined_argv;
-}
-
-/* As format_{hex,dex}_number_sigsafe, but takes a <b>radix</b> argument
- * in range 2..16 inclusive. */
-static int
-format_number_sigsafe(unsigned long x, char *buf, int buf_len,
- unsigned int radix)
-{
- unsigned long tmp;
- int len;
- char *cp;
-
- /* NOT tor_assert. This needs to be safe to run from within a signal handler,
- * and from within the 'tor_assert() has failed' code. */
- if (radix < 2 || radix > 16)
- return 0;
-
- /* Count how many digits we need. */
- tmp = x;
- len = 1;
- while (tmp >= radix) {
- tmp /= radix;
- ++len;
- }
-
- /* Not long enough */
- if (!buf || len >= buf_len)
- return 0;
-
- cp = buf + len;
- *cp = '\0';
- do {
- unsigned digit = (unsigned) (x % radix);
- tor_assert(cp > buf);
- --cp;
- *cp = "0123456789ABCDEF"[digit];
- x /= radix;
- } while (x);
-
- /* NOT tor_assert; see above. */
- if (cp != buf) {
- abort(); // LCOV_EXCL_LINE
- }
-
- return len;
-}
-
-/**
- * Helper function to output hex numbers from within a signal handler.
- *
- * Writes the nul-terminated hexadecimal digits of <b>x</b> into a buffer
- * <b>buf</b> of size <b>buf_len</b>, and return the actual number of digits
- * written, not counting the terminal NUL.
- *
- * If there is insufficient space, write nothing and return 0.
- *
- * This accepts an unsigned int because format_helper_exit_status() needs to
- * call it with a signed int and an unsigned char, and since the C standard
- * does not guarantee that an int is wider than a char (an int must be at
- * least 16 bits but it is permitted for a char to be that wide as well), we
- * can't assume a signed int is sufficient to accommodate an unsigned char.
- * Thus, format_helper_exit_status() will still need to emit any require '-'
- * on its own.
- *
- * For most purposes, you'd want to use tor_snprintf("%x") instead of this
- * function; it's designed to be used in code paths where you can't call
- * arbitrary C functions.
- */
-int
-format_hex_number_sigsafe(unsigned long x, char *buf, int buf_len)
-{
- return format_number_sigsafe(x, buf, buf_len, 16);
-}
-
-/** As format_hex_number_sigsafe, but format the number in base 10. */
-int
-format_dec_number_sigsafe(unsigned long x, char *buf, int buf_len)
-{
- return format_number_sigsafe(x, buf, buf_len, 10);
-}
-
-#ifndef _WIN32
-/** Format <b>child_state</b> and <b>saved_errno</b> as a hex string placed in
- * <b>hex_errno</b>. Called between fork and _exit, so must be signal-handler
- * safe.
- *
- * <b>hex_errno</b> must have at least HEX_ERRNO_SIZE+1 bytes available.
- *
- * The format of <b>hex_errno</b> is: "CHILD_STATE/ERRNO\n", left-padded
- * with spaces. CHILD_STATE indicates where
- * in the process of starting the child process did the failure occur (see
- * CHILD_STATE_* macros for definition), and SAVED_ERRNO is the value of
- * errno when the failure occurred.
- *
- * On success return the number of characters added to hex_errno, not counting
- * the terminating NUL; return -1 on error.
- */
-STATIC int
-format_helper_exit_status(unsigned char child_state, int saved_errno,
- char *hex_errno)
-{
- unsigned int unsigned_errno;
- int written, left;
- char *cur;
- size_t i;
- int res = -1;
-
- /* Fill hex_errno with spaces, and a trailing newline (memset may
- not be signal handler safe, so we can't use it) */
- for (i = 0; i < (HEX_ERRNO_SIZE - 1); i++)
- hex_errno[i] = ' ';
- hex_errno[HEX_ERRNO_SIZE - 1] = '\n';
-
- /* Convert errno to be unsigned for hex conversion */
- if (saved_errno < 0) {
- // Avoid overflow on the cast to unsigned int when result is INT_MIN
- // by adding 1 to the signed int negative value,
- // then, after it has been negated and cast to unsigned,
- // adding the original 1 back (the double-addition is intentional).
- // Otherwise, the cast to signed could cause a temporary int
- // to equal INT_MAX + 1, which is undefined.
- unsigned_errno = ((unsigned int) -(saved_errno + 1)) + 1;
- } else {
- unsigned_errno = (unsigned int) saved_errno;
- }
-
- /*
- * Count how many chars of space we have left, and keep a pointer into the
- * current point in the buffer.
- */
- left = HEX_ERRNO_SIZE+1;
- cur = hex_errno;
-
- /* Emit child_state */
- written = format_hex_number_sigsafe(child_state, cur, left);
-
- if (written <= 0)
- goto err;
-
- /* Adjust left and cur */
- left -= written;
- cur += written;
- if (left <= 0)
- goto err;
-
- /* Now the '/' */
- *cur = '/';
-
- /* Adjust left and cur */
- ++cur;
- --left;
- if (left <= 0)
- goto err;
-
- /* Need minus? */
- if (saved_errno < 0) {
- *cur = '-';
- ++cur;
- --left;
- if (left <= 0)
- goto err;
- }
-
- /* Emit unsigned_errno */
- written = format_hex_number_sigsafe(unsigned_errno, cur, left);
-
- if (written <= 0)
- goto err;
-
- /* Adjust left and cur */
- left -= written;
- cur += written;
-
- /* Check that we have enough space left for a newline and a NUL */
- if (left <= 1)
- goto err;
-
- /* Emit the newline and NUL */
- *cur++ = '\n';
- *cur++ = '\0';
-
- res = (int)(cur - hex_errno - 1);
-
- goto done;
-
- err:
- /*
- * In error exit, just write a '\0' in the first char so whatever called
- * this at least won't fall off the end.
- */
- *hex_errno = '\0';
-
- done:
- return res;
-}
-#endif /* !defined(_WIN32) */
-
-/* Maximum number of file descriptors, if we cannot get it via sysconf() */
-#define DEFAULT_MAX_FD 256
-
-/** Terminate the process of <b>process_handle</b>, if that process has not
- * already exited.
- *
- * Return 0 if we succeeded in terminating the process (or if the process
- * already exited), and -1 if we tried to kill the process but failed.
- *
- * Based on code originally borrowed from Python's os.kill. */
-int
-tor_terminate_process(process_handle_t *process_handle)
-{
-#ifdef _WIN32
- if (tor_get_exit_code(process_handle, 0, NULL) == PROCESS_EXIT_RUNNING) {
- HANDLE handle = process_handle->pid.hProcess;
-
- if (!TerminateProcess(handle, 0))
- return -1;
- else
- return 0;
- }
-#else /* !(defined(_WIN32)) */
- if (process_handle->waitpid_cb) {
- /* We haven't got a waitpid yet, so we can just kill off the process. */
- return kill(process_handle->pid, SIGTERM);
- }
-#endif /* defined(_WIN32) */
-
- return 0; /* We didn't need to kill the process, so report success */
-}
-
-/** Return the Process ID of <b>process_handle</b>. */
-int
-tor_process_get_pid(process_handle_t *process_handle)
-{
-#ifdef _WIN32
- return (int) process_handle->pid.dwProcessId;
-#else
- return (int) process_handle->pid;
-#endif
-}
-
-#ifdef _WIN32
-HANDLE
-tor_process_get_stdout_pipe(process_handle_t *process_handle)
-{
- return process_handle->stdout_pipe;
-}
-#else /* !(defined(_WIN32)) */
-/* DOCDOC tor_process_get_stdout_pipe */
-int
-tor_process_get_stdout_pipe(process_handle_t *process_handle)
-{
- return process_handle->stdout_pipe;
-}
-#endif /* defined(_WIN32) */
-
-/* DOCDOC process_handle_new */
-static process_handle_t *
-process_handle_new(void)
-{
- process_handle_t *out = tor_malloc_zero(sizeof(process_handle_t));
-
-#ifdef _WIN32
- out->stdin_pipe = INVALID_HANDLE_VALUE;
- out->stdout_pipe = INVALID_HANDLE_VALUE;
- out->stderr_pipe = INVALID_HANDLE_VALUE;
-#else
- out->stdin_pipe = -1;
- out->stdout_pipe = -1;
- out->stderr_pipe = -1;
-#endif /* defined(_WIN32) */
-
- return out;
-}
-
-#ifndef _WIN32
-/** Invoked when a process that we've launched via tor_spawn_background() has
- * been found to have terminated.
- */
-static void
-process_handle_waitpid_cb(int status, void *arg)
-{
- process_handle_t *process_handle = arg;
-
- process_handle->waitpid_exit_status = status;
- clear_waitpid_callback(process_handle->waitpid_cb);
- if (process_handle->status == PROCESS_STATUS_RUNNING)
- process_handle->status = PROCESS_STATUS_NOTRUNNING;
- process_handle->waitpid_cb = 0;
-}
-#endif /* !defined(_WIN32) */
-
-/**
- * @name child-process states
- *
- * Each of these values represents a possible state that a child process can
- * be in. They're used to determine what to say when telling the parent how
- * far along we were before failure.
- *
- * @{
- */
-#define CHILD_STATE_INIT 0
-#define CHILD_STATE_PIPE 1
-#define CHILD_STATE_MAXFD 2
-#define CHILD_STATE_FORK 3
-#define CHILD_STATE_DUPOUT 4
-#define CHILD_STATE_DUPERR 5
-#define CHILD_STATE_DUPIN 6
-#define CHILD_STATE_CLOSEFD 7
-#define CHILD_STATE_EXEC 8
-#define CHILD_STATE_FAILEXEC 9
-/** @} */
-/**
- * Boolean. If true, then Tor may call execve or CreateProcess via
- * tor_spawn_background.
- **/
-static int may_spawn_background_process = 1;
-/**
- * Turn off may_spawn_background_process, so that all future calls to
- * tor_spawn_background are guaranteed to fail.
- **/
-void
-tor_disable_spawning_background_processes(void)
-{
- may_spawn_background_process = 0;
-}
-/** Start a program in the background. If <b>filename</b> contains a '/', then
- * it will be treated as an absolute or relative path. Otherwise, on
- * non-Windows systems, the system path will be searched for <b>filename</b>.
- * On Windows, only the current directory will be searched. Here, to search the
- * system path (as well as the application directory, current working
- * directory, and system directories), set filename to NULL.
- *
- * The strings in <b>argv</b> will be passed as the command line arguments of
- * the child program (following convention, argv[0] should normally be the
- * filename of the executable, and this must be the case if <b>filename</b> is
- * NULL). The last element of argv must be NULL. A handle to the child process
- * will be returned in process_handle (which must be non-NULL). Read
- * process_handle.status to find out if the process was successfully launched.
- * For convenience, process_handle.status is returned by this function.
- *
- * Some parts of this code are based on the POSIX subprocess module from
- * Python, and example code from
- * http://msdn.microsoft.com/en-us/library/ms682499%28v=vs.85%29.aspx.
- */
-int
-tor_spawn_background(const char *const filename, const char **argv,
- process_environment_t *env,
- process_handle_t **process_handle_out)
-{
- if (BUG(may_spawn_background_process == 0)) {
- /* We should never reach this point if we're forbidden to spawn
- * processes. Instead we should have caught the attempt earlier. */
- return PROCESS_STATUS_ERROR;
- }
-
-#ifdef _WIN32
- HANDLE stdout_pipe_read = NULL;
- HANDLE stdout_pipe_write = NULL;
- HANDLE stderr_pipe_read = NULL;
- HANDLE stderr_pipe_write = NULL;
- HANDLE stdin_pipe_read = NULL;
- HANDLE stdin_pipe_write = NULL;
- process_handle_t *process_handle;
- int status;
-
- STARTUPINFOA siStartInfo;
- BOOL retval = FALSE;
-
- SECURITY_ATTRIBUTES saAttr;
- char *joined_argv;
-
- saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
- saAttr.bInheritHandle = TRUE;
- /* TODO: should we set explicit security attributes? (#2046, comment 5) */
- saAttr.lpSecurityDescriptor = NULL;
-
- /* Assume failure to start process */
- status = PROCESS_STATUS_ERROR;
-
- /* Set up pipe for stdout */
- if (!CreatePipe(&stdout_pipe_read, &stdout_pipe_write, &saAttr, 0)) {
- log_warn(LD_GENERAL,
- "Failed to create pipe for stdout communication with child process: %s",
- format_win32_error(GetLastError()));
- return status;
- }
- if (!SetHandleInformation(stdout_pipe_read, HANDLE_FLAG_INHERIT, 0)) {
- log_warn(LD_GENERAL,
- "Failed to configure pipe for stdout communication with child "
- "process: %s", format_win32_error(GetLastError()));
- return status;
- }
-
- /* Set up pipe for stderr */
- if (!CreatePipe(&stderr_pipe_read, &stderr_pipe_write, &saAttr, 0)) {
- log_warn(LD_GENERAL,
- "Failed to create pipe for stderr communication with child process: %s",
- format_win32_error(GetLastError()));
- return status;
- }
- if (!SetHandleInformation(stderr_pipe_read, HANDLE_FLAG_INHERIT, 0)) {
- log_warn(LD_GENERAL,
- "Failed to configure pipe for stderr communication with child "
- "process: %s", format_win32_error(GetLastError()));
- return status;
- }
-
- /* Set up pipe for stdin */
- if (!CreatePipe(&stdin_pipe_read, &stdin_pipe_write, &saAttr, 0)) {
- log_warn(LD_GENERAL,
- "Failed to create pipe for stdin communication with child process: %s",
- format_win32_error(GetLastError()));
- return status;
- }
- if (!SetHandleInformation(stdin_pipe_write, HANDLE_FLAG_INHERIT, 0)) {
- log_warn(LD_GENERAL,
- "Failed to configure pipe for stdin communication with child "
- "process: %s", format_win32_error(GetLastError()));
- return status;
- }
-
- /* Create the child process */
-
- /* Windows expects argv to be a whitespace delimited string, so join argv up
- */
- joined_argv = tor_join_win_cmdline(argv);
-
- process_handle = process_handle_new();
- process_handle->status = status;
-
- ZeroMemory(&(process_handle->pid), sizeof(PROCESS_INFORMATION));
- ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
- siStartInfo.cb = sizeof(STARTUPINFO);
- siStartInfo.hStdError = stderr_pipe_write;
- siStartInfo.hStdOutput = stdout_pipe_write;
- siStartInfo.hStdInput = stdin_pipe_read;
- siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
-
- /* Create the child process */
-
- retval = CreateProcessA(filename, // module name
- joined_argv, // command line
- /* TODO: should we set explicit security attributes? (#2046, comment 5) */
- NULL, // process security attributes
- NULL, // primary thread security attributes
- TRUE, // handles are inherited
- /*(TODO: set CREATE_NEW CONSOLE/PROCESS_GROUP to make GetExitCodeProcess()
- * work?) */
- CREATE_NO_WINDOW, // creation flags
- (env==NULL) ? NULL : env->windows_environment_block,
- NULL, // use parent's current directory
- &siStartInfo, // STARTUPINFO pointer
- &(process_handle->pid)); // receives PROCESS_INFORMATION
-
- tor_free(joined_argv);
-
- if (!retval) {
- log_warn(LD_GENERAL,
- "Failed to create child process %s: %s", filename?filename:argv[0],
- format_win32_error(GetLastError()));
- tor_free(process_handle);
- } else {
- /* TODO: Close hProcess and hThread in process_handle->pid? */
- process_handle->stdout_pipe = stdout_pipe_read;
- process_handle->stderr_pipe = stderr_pipe_read;
- process_handle->stdin_pipe = stdin_pipe_write;
- status = process_handle->status = PROCESS_STATUS_RUNNING;
- }
-
- /* TODO: Close pipes on exit */
- *process_handle_out = process_handle;
- return status;
-#else /* !(defined(_WIN32)) */
- pid_t pid;
- int stdout_pipe[2];
- int stderr_pipe[2];
- int stdin_pipe[2];
- int fd, retval;
- process_handle_t *process_handle;
- int status;
-
- const char *error_message = SPAWN_ERROR_MESSAGE;
- size_t error_message_length;
-
- /* Represents where in the process of spawning the program is;
- this is used for printing out the error message */
- unsigned char child_state = CHILD_STATE_INIT;
-
- char hex_errno[HEX_ERRNO_SIZE + 2]; /* + 1 should be sufficient actually */
-
- static int max_fd = -1;
-
- status = PROCESS_STATUS_ERROR;
-
- /* We do the strlen here because strlen() is not signal handler safe,
- and we are not allowed to use unsafe functions between fork and exec */
- error_message_length = strlen(error_message);
-
- // child_state = CHILD_STATE_PIPE;
-
- /* Set up pipe for redirecting stdout, stderr, and stdin of child */
- retval = pipe(stdout_pipe);
- if (-1 == retval) {
- log_warn(LD_GENERAL,
- "Failed to set up pipe for stdout communication with child process: %s",
- strerror(errno));
- return status;
- }
-
- retval = pipe(stderr_pipe);
- if (-1 == retval) {
- log_warn(LD_GENERAL,
- "Failed to set up pipe for stderr communication with child process: %s",
- strerror(errno));
-
- close(stdout_pipe[0]);
- close(stdout_pipe[1]);
-
- return status;
- }
-
- retval = pipe(stdin_pipe);
- if (-1 == retval) {
- log_warn(LD_GENERAL,
- "Failed to set up pipe for stdin communication with child process: %s",
- strerror(errno));
-
- close(stdout_pipe[0]);
- close(stdout_pipe[1]);
- close(stderr_pipe[0]);
- close(stderr_pipe[1]);
-
- return status;
- }
-
- // child_state = CHILD_STATE_MAXFD;
-
-#ifdef _SC_OPEN_MAX
- if (-1 == max_fd) {
- max_fd = (int) sysconf(_SC_OPEN_MAX);
- if (max_fd == -1) {
- max_fd = DEFAULT_MAX_FD;
- log_warn(LD_GENERAL,
- "Cannot find maximum file descriptor, assuming %d", max_fd);
- }
- }
-#else /* !(defined(_SC_OPEN_MAX)) */
- max_fd = DEFAULT_MAX_FD;
-#endif /* defined(_SC_OPEN_MAX) */
-
- // child_state = CHILD_STATE_FORK;
-
- pid = fork();
- if (0 == pid) {
- /* In child */
-
-#if defined(HAVE_SYS_PRCTL_H) && defined(__linux__)
- /* Attempt to have the kernel issue a SIGTERM if the parent
- * goes away. Certain attributes of the binary being execve()ed
- * will clear this during the execve() call, but it's better
- * than nothing.
- */
- prctl(PR_SET_PDEATHSIG, SIGTERM);
-#endif /* defined(HAVE_SYS_PRCTL_H) && defined(__linux__) */
-
- child_state = CHILD_STATE_DUPOUT;
-
- /* Link child stdout to the write end of the pipe */
- retval = dup2(stdout_pipe[1], STDOUT_FILENO);
- if (-1 == retval)
- goto error;
-
- child_state = CHILD_STATE_DUPERR;
-
- /* Link child stderr to the write end of the pipe */
- retval = dup2(stderr_pipe[1], STDERR_FILENO);
- if (-1 == retval)
- goto error;
-
- child_state = CHILD_STATE_DUPIN;
-
- /* Link child stdin to the read end of the pipe */
- retval = dup2(stdin_pipe[0], STDIN_FILENO);
- if (-1 == retval)
- goto error;
-
- // child_state = CHILD_STATE_CLOSEFD;
-
- close(stderr_pipe[0]);
- close(stderr_pipe[1]);
- close(stdout_pipe[0]);
- close(stdout_pipe[1]);
- close(stdin_pipe[0]);
- close(stdin_pipe[1]);
-
- /* Close all other fds, including the read end of the pipe */
- /* XXX: We should now be doing enough FD_CLOEXEC setting to make
- * this needless. */
- for (fd = STDERR_FILENO + 1; fd < max_fd; fd++) {
- close(fd);
- }
-
- // child_state = CHILD_STATE_EXEC;
-
- /* Call the requested program. We need the cast because
- execvp doesn't define argv as const, even though it
- does not modify the arguments */
- if (env)
- execve(filename, (char *const *) argv, env->unixoid_environment_block);
- else {
- static char *new_env[] = { NULL };
- execve(filename, (char *const *) argv, new_env);
- }
-
- /* If we got here, the exec or open(/dev/null) failed */
-
- child_state = CHILD_STATE_FAILEXEC;
-
- error:
- {
- /* XXX: are we leaking fds from the pipe? */
- int n, err=0;
- ssize_t nbytes;
-
- n = format_helper_exit_status(child_state, errno, hex_errno);
-
- if (n >= 0) {
- /* Write the error message. GCC requires that we check the return
- value, but there is nothing we can do if it fails */
- /* TODO: Don't use STDOUT, use a pipe set up just for this purpose */
- nbytes = write(STDOUT_FILENO, error_message, error_message_length);
- err = (nbytes < 0);
- nbytes = write(STDOUT_FILENO, hex_errno, n);
- err += (nbytes < 0);
- }
-
- _exit(err?254:255); // exit ok: in child.
- }
-
- /* Never reached, but avoids compiler warning */
- return status; // LCOV_EXCL_LINE
- }
-
- /* In parent */
-
- if (-1 == pid) {
- log_warn(LD_GENERAL, "Failed to fork child process: %s", strerror(errno));
- close(stdin_pipe[0]);
- close(stdin_pipe[1]);
- close(stdout_pipe[0]);
- close(stdout_pipe[1]);
- close(stderr_pipe[0]);
- close(stderr_pipe[1]);
- return status;
- }
-
- process_handle = process_handle_new();
- process_handle->status = status;
- process_handle->pid = pid;
-
- /* TODO: If the child process forked but failed to exec, waitpid it */
-
- /* Return read end of the pipes to caller, and close write end */
- process_handle->stdout_pipe = stdout_pipe[0];
- retval = close(stdout_pipe[1]);
-
- if (-1 == retval) {
- log_warn(LD_GENERAL,
- "Failed to close write end of stdout pipe in parent process: %s",
- strerror(errno));
- }
-
- process_handle->waitpid_cb = set_waitpid_callback(pid,
- process_handle_waitpid_cb,
- process_handle);
-
- process_handle->stderr_pipe = stderr_pipe[0];
- retval = close(stderr_pipe[1]);
-
- if (-1 == retval) {
- log_warn(LD_GENERAL,
- "Failed to close write end of stderr pipe in parent process: %s",
- strerror(errno));
- }
-
- /* Return write end of the stdin pipe to caller, and close the read end */
- process_handle->stdin_pipe = stdin_pipe[1];
- retval = close(stdin_pipe[0]);
-
- if (-1 == retval) {
- log_warn(LD_GENERAL,
- "Failed to close read end of stdin pipe in parent process: %s",
- strerror(errno));
- }
-
- status = process_handle->status = PROCESS_STATUS_RUNNING;
- /* Set stdin/stdout/stderr pipes to be non-blocking */
- if (fcntl(process_handle->stdout_pipe, F_SETFL, O_NONBLOCK) < 0 ||
- fcntl(process_handle->stderr_pipe, F_SETFL, O_NONBLOCK) < 0 ||
- fcntl(process_handle->stdin_pipe, F_SETFL, O_NONBLOCK) < 0) {
- log_warn(LD_GENERAL, "Failed to set stderror/stdout/stdin pipes "
- "nonblocking in parent process: %s", strerror(errno));
- }
-
- *process_handle_out = process_handle;
- return status;
-#endif /* defined(_WIN32) */
-}
-
-/** Destroy all resources allocated by the process handle in
- * <b>process_handle</b>.
- * If <b>also_terminate_process</b> is true, also terminate the
- * process of the process handle. */
-MOCK_IMPL(void,
-tor_process_handle_destroy,(process_handle_t *process_handle,
- int also_terminate_process))
-{
- if (!process_handle)
- return;
-
- if (also_terminate_process) {
- if (tor_terminate_process(process_handle) < 0) {
- const char *errstr =
-#ifdef _WIN32
- format_win32_error(GetLastError());
-#else
- strerror(errno);
-#endif
- log_notice(LD_GENERAL, "Failed to terminate process with "
- "PID '%d' ('%s').", tor_process_get_pid(process_handle),
- errstr);
- } else {
- log_info(LD_GENERAL, "Terminated process with PID '%d'.",
- tor_process_get_pid(process_handle));
- }
- }
-
- process_handle->status = PROCESS_STATUS_NOTRUNNING;
-
-#ifdef _WIN32
- if (process_handle->stdout_pipe)
- CloseHandle(process_handle->stdout_pipe);
-
- if (process_handle->stderr_pipe)
- CloseHandle(process_handle->stderr_pipe);
-
- if (process_handle->stdin_pipe)
- CloseHandle(process_handle->stdin_pipe);
-#else /* !(defined(_WIN32)) */
- close(process_handle->stdout_pipe);
- close(process_handle->stderr_pipe);
- close(process_handle->stdin_pipe);
-
- clear_waitpid_callback(process_handle->waitpid_cb);
-#endif /* defined(_WIN32) */
-
- memset(process_handle, 0x0f, sizeof(process_handle_t));
- tor_free(process_handle);
-}
-
-/** Get the exit code of a process specified by <b>process_handle</b> and store
- * it in <b>exit_code</b>, if set to a non-NULL value. If <b>block</b> is set
- * to true, the call will block until the process has exited. Otherwise if
- * the process is still running, the function will return
- * PROCESS_EXIT_RUNNING, and exit_code will be left unchanged. Returns
- * PROCESS_EXIT_EXITED if the process did exit. If there is a failure,
- * PROCESS_EXIT_ERROR will be returned and the contents of exit_code (if
- * non-NULL) will be undefined. N.B. Under *nix operating systems, this will
- * probably not work in Tor, because waitpid() is called in main.c to reap any
- * terminated child processes.*/
-int
-tor_get_exit_code(process_handle_t *process_handle,
- int block, int *exit_code)
-{
-#ifdef _WIN32
- DWORD retval;
- BOOL success;
-
- if (block) {
- /* Wait for the process to exit */
- retval = WaitForSingleObject(process_handle->pid.hProcess, INFINITE);
- if (retval != WAIT_OBJECT_0) {
- log_warn(LD_GENERAL, "WaitForSingleObject() failed (%d): %s",
- (int)retval, format_win32_error(GetLastError()));
- return PROCESS_EXIT_ERROR;
- }
- } else {
- retval = WaitForSingleObject(process_handle->pid.hProcess, 0);
- if (WAIT_TIMEOUT == retval) {
- /* Process has not exited */
- return PROCESS_EXIT_RUNNING;
- } else if (retval != WAIT_OBJECT_0) {
- log_warn(LD_GENERAL, "WaitForSingleObject() failed (%d): %s",
- (int)retval, format_win32_error(GetLastError()));
- return PROCESS_EXIT_ERROR;
- }
- }
-
- if (exit_code != NULL) {
- success = GetExitCodeProcess(process_handle->pid.hProcess,
- (PDWORD)exit_code);
- if (!success) {
- log_warn(LD_GENERAL, "GetExitCodeProcess() failed: %s",
- format_win32_error(GetLastError()));
- return PROCESS_EXIT_ERROR;
- }
- }
-#else /* !(defined(_WIN32)) */
- int stat_loc;
- int retval;
-
- if (process_handle->waitpid_cb) {
- /* We haven't processed a SIGCHLD yet. */
- retval = waitpid(process_handle->pid, &stat_loc, block?0:WNOHANG);
- if (retval == process_handle->pid) {
- clear_waitpid_callback(process_handle->waitpid_cb);
- process_handle->waitpid_cb = NULL;
- process_handle->waitpid_exit_status = stat_loc;
- }
- } else {
- /* We already got a SIGCHLD for this process, and handled it. */
- retval = process_handle->pid;
- stat_loc = process_handle->waitpid_exit_status;
- }
-
- if (!block && 0 == retval) {
- /* Process has not exited */
- return PROCESS_EXIT_RUNNING;
- } else if (retval != process_handle->pid) {
- log_warn(LD_GENERAL, "waitpid() failed for PID %d: %s",
- (int)process_handle->pid, strerror(errno));
- return PROCESS_EXIT_ERROR;
- }
-
- if (!WIFEXITED(stat_loc)) {
- log_warn(LD_GENERAL, "Process %d did not exit normally",
- (int)process_handle->pid);
- return PROCESS_EXIT_ERROR;
- }
-
- if (exit_code != NULL)
- *exit_code = WEXITSTATUS(stat_loc);
-#endif /* defined(_WIN32) */
-
- return PROCESS_EXIT_EXITED;
-}
-
-/** Helper: return the number of characters in <b>s</b> preceding the first
- * occurrence of <b>ch</b>. If <b>ch</b> does not occur in <b>s</b>, return
- * the length of <b>s</b>. Should be equivalent to strspn(s, "ch"). */
-static inline size_t
-str_num_before(const char *s, char ch)
-{
- const char *cp = strchr(s, ch);
- if (cp)
- return cp - s;
- else
- return strlen(s);
-}
-
-/** Return non-zero iff getenv would consider <b>s1</b> and <b>s2</b>
- * to have the same name as strings in a process's environment. */
-int
-environment_variable_names_equal(const char *s1, const char *s2)
-{
- size_t s1_name_len = str_num_before(s1, '=');
- size_t s2_name_len = str_num_before(s2, '=');
-
- return (s1_name_len == s2_name_len &&
- tor_memeq(s1, s2, s1_name_len));
-}
-
-/** Free <b>env</b> (assuming it was produced by
- * process_environment_make). */
-void
-process_environment_free_(process_environment_t *env)
-{
- if (env == NULL) return;
-
- /* As both an optimization hack to reduce consing on Unixoid systems
- * and a nice way to ensure that some otherwise-Windows-specific
- * code will always get tested before changes to it get merged, the
- * strings which env->unixoid_environment_block points to are packed
- * into env->windows_environment_block. */
- tor_free(env->unixoid_environment_block);
- tor_free(env->windows_environment_block);
-
- tor_free(env);
-}
-
-/** Make a process_environment_t containing the environment variables
- * specified in <b>env_vars</b> (as C strings of the form
- * "NAME=VALUE"). */
-process_environment_t *
-process_environment_make(struct smartlist_t *env_vars)
-{
- process_environment_t *env = tor_malloc_zero(sizeof(process_environment_t));
- int n_env_vars = smartlist_len(env_vars);
- int i;
- size_t total_env_length;
- smartlist_t *env_vars_sorted;
-
- tor_assert(n_env_vars + 1 != 0);
- env->unixoid_environment_block = tor_calloc(n_env_vars + 1, sizeof(char *));
- /* env->unixoid_environment_block is already NULL-terminated,
- * because we assume that NULL == 0 (and check that during compilation). */
-
- total_env_length = 1; /* terminating NUL of terminating empty string */
- for (i = 0; i < n_env_vars; ++i) {
- const char *s = smartlist_get(env_vars, i);
- size_t slen = strlen(s);
-
- tor_assert(slen + 1 != 0);
- tor_assert(slen + 1 < SIZE_MAX - total_env_length);
- total_env_length += slen + 1;
- }
-
- env->windows_environment_block = tor_malloc_zero(total_env_length);
- /* env->windows_environment_block is already
- * (NUL-terminated-empty-string)-terminated. */
-
- /* Some versions of Windows supposedly require that environment
- * blocks be sorted. Or maybe some Windows programs (or their
- * runtime libraries) fail to look up strings in non-sorted
- * environment blocks.
- *
- * Also, sorting strings makes it easy to find duplicate environment
- * variables and environment-variable strings without an '=' on all
- * OSes, and they can cause badness. Let's complain about those. */
- env_vars_sorted = smartlist_new();
- smartlist_add_all(env_vars_sorted, env_vars);
- smartlist_sort_strings(env_vars_sorted);
-
- /* Now copy the strings into the environment blocks. */
- {
- char *cp = env->windows_environment_block;
- const char *prev_env_var = NULL;
-
- for (i = 0; i < n_env_vars; ++i) {
- const char *s = smartlist_get(env_vars_sorted, i);
- size_t slen = strlen(s);
- size_t s_name_len = str_num_before(s, '=');
-
- if (s_name_len == slen) {
- log_warn(LD_GENERAL,
- "Preparing an environment containing a variable "
- "without a value: %s",
- s);
- }
- if (prev_env_var != NULL &&
- environment_variable_names_equal(s, prev_env_var)) {
- log_warn(LD_GENERAL,
- "Preparing an environment containing two variables "
- "with the same name: %s and %s",
- prev_env_var, s);
- }
-
- prev_env_var = s;
-
- /* Actually copy the string into the environment. */
- memcpy(cp, s, slen+1);
- env->unixoid_environment_block[i] = cp;
- cp += slen+1;
- }
-
- tor_assert(cp == env->windows_environment_block + total_env_length - 1);
- }
-
- smartlist_free(env_vars_sorted);
-
- return env;
-}
-
-/** Return a newly allocated smartlist containing every variable in
- * this process's environment, as a NUL-terminated string of the form
- * "NAME=VALUE". Note that on some/many/most/all OSes, the parent
- * process can put strings not of that form in our environment;
- * callers should try to not get crashed by that.
- *
- * The returned strings are heap-allocated, and must be freed by the
- * caller. */
-struct smartlist_t *
-get_current_process_environment_variables(void)
-{
- smartlist_t *sl = smartlist_new();
-
- char **environ_tmp; /* Not const char ** ? Really? */
- for (environ_tmp = get_environment(); *environ_tmp; ++environ_tmp) {
- smartlist_add_strdup(sl, *environ_tmp);
- }
-
- return sl;
-}
-
-/** For each string s in <b>env_vars</b> such that
- * environment_variable_names_equal(s, <b>new_var</b>), remove it; if
- * <b>free_p</b> is non-zero, call <b>free_old</b>(s). If
- * <b>new_var</b> contains '=', insert it into <b>env_vars</b>. */
-void
-set_environment_variable_in_smartlist(struct smartlist_t *env_vars,
- const char *new_var,
- void (*free_old)(void*),
- int free_p)
-{
- SMARTLIST_FOREACH_BEGIN(env_vars, const char *, s) {
- if (environment_variable_names_equal(s, new_var)) {
- SMARTLIST_DEL_CURRENT(env_vars, s);
- if (free_p) {
- free_old((void *)s);
- }
- }
- } SMARTLIST_FOREACH_END(s);
-
- if (strchr(new_var, '=') != NULL) {
- smartlist_add(env_vars, (void *)new_var);
- }
-}
-
-#ifdef _WIN32
-/** Read from a handle <b>h</b> into <b>buf</b>, up to <b>count</b> bytes. If
- * <b>hProcess</b> is NULL, the function will return immediately if there is
- * nothing more to read. Otherwise <b>hProcess</b> should be set to the handle
- * to the process owning the <b>h</b>. In this case, the function will exit
- * only once the process has exited, or <b>count</b> bytes are read. Returns
- * the number of bytes read, or -1 on error. */
-ssize_t
-tor_read_all_handle(HANDLE h, char *buf, size_t count,
- const process_handle_t *process)
-{
- size_t numread = 0;
- BOOL retval;
- DWORD byte_count;
- BOOL process_exited = FALSE;
-
- if (count > SIZE_T_CEILING || count > SSIZE_MAX)
- return -1;
-
- while (numread < count) {
- /* Check if there is anything to read */
- retval = PeekNamedPipe(h, NULL, 0, NULL, &byte_count, NULL);
- if (!retval) {
- log_warn(LD_GENERAL,
- "Failed to peek from handle: %s",
- format_win32_error(GetLastError()));
- return -1;
- } else if (0 == byte_count) {
- /* Nothing available: process exited or it is busy */
-
- /* Exit if we don't know whether the process is running */
- if (NULL == process)
- break;
-
- /* The process exited and there's nothing left to read from it */
- if (process_exited)
- break;
-
- /* If process is not running, check for output one more time in case
- it wrote something after the peek was performed. Otherwise keep on
- waiting for output */
- tor_assert(process != NULL);
- byte_count = WaitForSingleObject(process->pid.hProcess, 0);
- if (WAIT_TIMEOUT != byte_count)
- process_exited = TRUE;
-
- continue;
- }
-
- /* There is data to read; read it */
- retval = ReadFile(h, buf+numread, count-numread, &byte_count, NULL);
- tor_assert(byte_count + numread <= count);
- if (!retval) {
- log_warn(LD_GENERAL, "Failed to read from handle: %s",
- format_win32_error(GetLastError()));
- return -1;
- } else if (0 == byte_count) {
- /* End of file */
- break;
- }
- numread += byte_count;
- }
- return (ssize_t)numread;
-}
-#else /* !(defined(_WIN32)) */
-/** Read from a handle <b>fd</b> into <b>buf</b>, up to <b>count</b> bytes. If
- * <b>process</b> is NULL, the function will return immediately if there is
- * nothing more to read. Otherwise data will be read until end of file, or
- * <b>count</b> bytes are read. Returns the number of bytes read, or -1 on
- * error. Sets <b>eof</b> to true if <b>eof</b> is not NULL and the end of the
- * file has been reached. */
-ssize_t
-tor_read_all_handle(int fd, char *buf, size_t count,
- const process_handle_t *process,
- int *eof)
-{
- size_t numread = 0;
- ssize_t result;
-
- if (eof)
- *eof = 0;
-
- if (count > SIZE_T_CEILING || count > SSIZE_MAX)
- return -1;
-
- while (numread < count) {
- result = read(fd, buf+numread, count-numread);
-
- if (result == 0) {
- log_debug(LD_GENERAL, "read() reached end of file");
- if (eof)
- *eof = 1;
- break;
- } else if (result < 0 && errno == EAGAIN) {
- if (process)
- continue;
- else
- break;
- } else if (result < 0) {
- log_warn(LD_GENERAL, "read() failed: %s", strerror(errno));
- return -1;
- }
-
- numread += result;
- }
-
- log_debug(LD_GENERAL, "read() read %d bytes from handle", (int)numread);
- return (ssize_t)numread;
-}
-#endif /* defined(_WIN32) */
-
-/** Read from stdout of a process until the process exits. */
-ssize_t
-tor_read_all_from_process_stdout(const process_handle_t *process_handle,
- char *buf, size_t count)
-{
-#ifdef _WIN32
- return tor_read_all_handle(process_handle->stdout_pipe, buf, count,
- process_handle);
-#else
- return tor_read_all_handle(process_handle->stdout_pipe, buf, count,
- process_handle, NULL);
-#endif /* defined(_WIN32) */
-}
-
-/** Read from stdout of a process until the process exits. */
-ssize_t
-tor_read_all_from_process_stderr(const process_handle_t *process_handle,
- char *buf, size_t count)
-{
-#ifdef _WIN32
- return tor_read_all_handle(process_handle->stderr_pipe, buf, count,
- process_handle);
-#else
- return tor_read_all_handle(process_handle->stderr_pipe, buf, count,
- process_handle, NULL);
-#endif /* defined(_WIN32) */
-}
-
-/** Split buf into lines, and add to smartlist. The buffer <b>buf</b> will be
- * modified. The resulting smartlist will consist of pointers to buf, so there
- * is no need to free the contents of sl. <b>buf</b> must be a NUL-terminated
- * string. <b>len</b> should be set to the length of the buffer excluding the
- * NUL. Non-printable characters (including NUL) will be replaced with "." */
-int
-tor_split_lines(smartlist_t *sl, char *buf, int len)
-{
- /* Index in buf of the start of the current line */
- int start = 0;
- /* Index in buf of the current character being processed */
- int cur = 0;
- /* Are we currently in a line */
- char in_line = 0;
-
- /* Loop over string */
- while (cur < len) {
- /* Loop until end of line or end of string */
- for (; cur < len; cur++) {
- if (in_line) {
- if ('\r' == buf[cur] || '\n' == buf[cur]) {
- /* End of line */
- buf[cur] = '\0';
- /* Point cur to the next line */
- cur++;
- /* Line starts at start and ends with a nul */
- break;
- } else {
- if (!TOR_ISPRINT(buf[cur]))
- buf[cur] = '.';
- }
- } else {
- if ('\r' == buf[cur] || '\n' == buf[cur]) {
- /* Skip leading vertical space */
- ;
- } else {
- in_line = 1;
- start = cur;
- if (!TOR_ISPRINT(buf[cur]))
- buf[cur] = '.';
- }
- }
- }
- /* We are at the end of the line or end of string. If in_line is true there
- * is a line which starts at buf+start and ends at a NUL. cur points to
- * the character after the NUL. */
- if (in_line)
- smartlist_add(sl, (void *)(buf+start));
- in_line = 0;
- }
- return smartlist_len(sl);
-}
-
-/** Return a string corresponding to <b>stream_status</b>. */
-const char *
-stream_status_to_string(enum stream_status stream_status)
-{
- switch (stream_status) {
- case IO_STREAM_OKAY:
- return "okay";
- case IO_STREAM_EAGAIN:
- return "temporarily unavailable";
- case IO_STREAM_TERM:
- return "terminated";
- case IO_STREAM_CLOSED:
- return "closed";
- default:
- tor_fragile_assert();
- return "unknown";
- }
-}
-
-#ifdef _WIN32
-
-/** Return a smartlist containing lines outputted from
- * <b>handle</b>. Return NULL on error, and set
- * <b>stream_status_out</b> appropriately. */
-MOCK_IMPL(smartlist_t *,
-tor_get_lines_from_handle, (HANDLE *handle,
- enum stream_status *stream_status_out))
-{
- int pos;
- char stdout_buf[600] = {0};
- smartlist_t *lines = NULL;
-
- tor_assert(stream_status_out);
-
- *stream_status_out = IO_STREAM_TERM;
-
- pos = tor_read_all_handle(handle, stdout_buf, sizeof(stdout_buf) - 1, NULL);
- if (pos < 0) {
- *stream_status_out = IO_STREAM_TERM;
- return NULL;
- }
- if (pos == 0) {
- *stream_status_out = IO_STREAM_EAGAIN;
- return NULL;
- }
-
- /* End with a null even if there isn't a \r\n at the end */
- /* TODO: What if this is a partial line? */
- stdout_buf[pos] = '\0';
-
- /* Split up the buffer */
- lines = smartlist_new();
- tor_split_lines(lines, stdout_buf, pos);
-
- /* Currently 'lines' is populated with strings residing on the
- stack. Replace them with their exact copies on the heap: */
- SMARTLIST_FOREACH(lines, char *, line,
- SMARTLIST_REPLACE_CURRENT(lines, line, tor_strdup(line)));
-
- *stream_status_out = IO_STREAM_OKAY;
-
- return lines;
-}
-
-#else /* !(defined(_WIN32)) */
-
-/** Return a smartlist containing lines outputted from
- * <b>fd</b>. Return NULL on error, and set
- * <b>stream_status_out</b> appropriately. */
-MOCK_IMPL(smartlist_t *,
-tor_get_lines_from_handle, (int fd, enum stream_status *stream_status_out))
-{
- enum stream_status stream_status;
- char stdout_buf[400];
- smartlist_t *lines = NULL;
-
- while (1) {
- memset(stdout_buf, 0, sizeof(stdout_buf));
-
- stream_status = get_string_from_pipe(fd,
- stdout_buf, sizeof(stdout_buf) - 1);
- if (stream_status != IO_STREAM_OKAY)
- goto done;
-
- if (!lines) lines = smartlist_new();
- smartlist_split_string(lines, stdout_buf, "\n", 0, 0);
- }
-
- done:
- *stream_status_out = stream_status;
- return lines;
-}
-
-#endif /* defined(_WIN32) */
-
-/** Reads from <b>fd</b> and stores input in <b>buf_out</b> making
- * sure it's below <b>count</b> bytes.
- * If the string has a trailing newline, we strip it off.
- *
- * This function is specifically created to handle input from managed
- * proxies, according to the pluggable transports spec. Make sure it
- * fits your needs before using it.
- *
- * Returns:
- * IO_STREAM_CLOSED: If the stream is closed.
- * IO_STREAM_EAGAIN: If there is nothing to read and we should check back
- * later.
- * IO_STREAM_TERM: If something is wrong with the stream.
- * IO_STREAM_OKAY: If everything went okay and we got a string
- * in <b>buf_out</b>. */
-enum stream_status
-get_string_from_pipe(int fd, char *buf_out, size_t count)
-{
- ssize_t ret;
-
- tor_assert(count <= INT_MAX);
-
- ret = read(fd, buf_out, count);
-
- if (ret == 0)
- return IO_STREAM_CLOSED;
- else if (ret < 0 && errno == EAGAIN)
- return IO_STREAM_EAGAIN;
- else if (ret < 0)
- return IO_STREAM_TERM;
-
- if (buf_out[ret - 1] == '\n') {
- /* Remove the trailing newline */
- buf_out[ret - 1] = '\0';
- } else
- buf_out[ret] = '\0';
-
- return IO_STREAM_OKAY;
-}
-
-/** Initialize the insecure RNG <b>rng</b> from a seed value <b>seed</b>. */
-void
-tor_init_weak_random(tor_weak_rng_t *rng, unsigned seed)
-{
- rng->state = (uint32_t)(seed & 0x7fffffff);
-}
-
-/** Return a randomly chosen value in the range 0..TOR_WEAK_RANDOM_MAX based
- * on the RNG state of <b>rng</b>. This entropy will not be cryptographically
- * strong; do not rely on it for anything an adversary should not be able to
- * predict. */
-int32_t
-tor_weak_random(tor_weak_rng_t *rng)
-{
- /* Here's a linear congruential generator. OpenBSD and glibc use these
- * parameters; they aren't too bad, and should have maximal period over the
- * range 0..INT32_MAX. We don't want to use the platform rand() or random(),
- * since some platforms have bad weak RNGs that only return values in the
- * range 0..INT16_MAX, which just isn't enough. */
- rng->state = (rng->state * 1103515245 + 12345) & 0x7fffffff;
- return (int32_t) rng->state;
-}
-
-/** Return a random number in the range [0 , <b>top</b>). {That is, the range
- * of integers i such that 0 <= i < top.} Chooses uniformly. Requires that
- * top is greater than 0. This randomness is not cryptographically strong; do
- * not rely on it for anything an adversary should not be able to predict. */
-int32_t
-tor_weak_random_range(tor_weak_rng_t *rng, int32_t top)
-{
- /* We don't want to just do tor_weak_random() % top, since random() is often
- * implemented with an LCG whose modulus is a power of 2, and those are
- * cyclic in their low-order bits. */
- int divisor, result;
- tor_assert(top > 0);
- divisor = TOR_WEAK_RANDOM_MAX / top;
- do {
- result = (int32_t)(tor_weak_random(rng) / divisor);
- } while (result >= top);
- return result;
-}
-
-/** Cast a given double value to a int64_t. Return 0 if number is NaN.
- * Returns either INT64_MIN or INT64_MAX if number is outside of the int64_t
- * range. */
-int64_t
-clamp_double_to_int64(double number)
-{
- int exponent;
-
-#if defined(MINGW_ANY) && GCC_VERSION >= 409
-/*
- Mingw's math.h uses gcc's __builtin_choose_expr() facility to declare
- isnan, isfinite, and signbit. But as implemented in at least some
- versions of gcc, __builtin_choose_expr() can generate type warnings
- even from branches that are not taken. So, suppress those warnings.
-*/
-#define PROBLEMATIC_FLOAT_CONVERSION_WARNING
-DISABLE_GCC_WARNING(float-conversion)
-#endif /* defined(MINGW_ANY) && GCC_VERSION >= 409 */
-
-/*
- With clang 4.0 we apparently run into "double promotion" warnings here,
- since clang thinks we're promoting a double to a long double.
- */
-#if defined(__clang__)
-#if __has_warning("-Wdouble-promotion")
-#define PROBLEMATIC_DOUBLE_PROMOTION_WARNING
-DISABLE_GCC_WARNING(double-promotion)
-#endif
-#endif /* defined(__clang__) */
-
- /* NaN is a special case that can't be used with the logic below. */
- if (isnan(number)) {
- return 0;
- }
-
- /* Time to validate if result can overflows a int64_t value. Fun with
- * float! Find that exponent exp such that
- * number == x * 2^exp
- * for some x with abs(x) in [0.5, 1.0). Note that this implies that the
- * magnitude of number is strictly less than 2^exp.
- *
- * If number is infinite, the call to frexp is legal but the contents of
- * are exponent unspecified. */
- frexp(number, &exponent);
-
- /* If the magnitude of number is strictly less than 2^63, the truncated
- * version of number is guaranteed to be representable. The only
- * representable integer for which this is not the case is INT64_MIN, but
- * it is covered by the logic below. */
- if (isfinite(number) && exponent <= 63) {
- return (int64_t)number;
- }
-
- /* Handle infinities and finite numbers with magnitude >= 2^63. */
- return signbit(number) ? INT64_MIN : INT64_MAX;
-
-#ifdef PROBLEMATIC_DOUBLE_PROMOTION_WARNING
-ENABLE_GCC_WARNING(double-promotion)
-#endif
-#ifdef PROBLEMATIC_FLOAT_CONVERSION_WARNING
-ENABLE_GCC_WARNING(float-conversion)
-#endif
-}
-
-/** Return a uint64_t value from <b>a</b> in network byte order. */
-uint64_t
-tor_htonll(uint64_t a)
-{
-#ifdef WORDS_BIGENDIAN
- /* Big endian. */
- return a;
-#else /* WORDS_BIGENDIAN */
- /* Little endian. The worst... */
- return htonl((uint32_t)(a>>32)) |
- (((uint64_t)htonl((uint32_t)a))<<32);
-#endif /* defined(WORDS_BIGENDIAN) */
-}
-
-/** Return a uint64_t value from <b>a</b> in host byte order. */
-uint64_t
-tor_ntohll(uint64_t a)
-{
- return tor_htonll(a);
-}
-
diff --git a/src/common/util.h b/src/common/util.h
deleted file mode 100644
index 7172b7da08..0000000000
--- a/src/common/util.h
+++ /dev/null
@@ -1,572 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file util.h
- * \brief Headers for util.c
- **/
-
-#ifndef TOR_UTIL_H
-#define TOR_UTIL_H
-
-#include "orconfig.h"
-#include "torint.h"
-#include "compat.h"
-#include "di_ops.h"
-#include "testsupport.h"
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef _WIN32
-/* for the correct alias to struct stat */
-#include <sys/stat.h>
-#endif
-#include "util_bug.h"
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-#ifndef O_TEXT
-#define O_TEXT 0
-#endif
-#ifndef O_NOFOLLOW
-#define O_NOFOLLOW 0
-#endif
-
-/* If we're building with dmalloc, we want all of our memory allocation
- * functions to take an extra file/line pair of arguments. If not, not.
- * We define DMALLOC_PARAMS to the extra parameters to insert in the
- * function prototypes, and DMALLOC_ARGS to the extra arguments to add
- * to calls. */
-#ifdef USE_DMALLOC
-#define DMALLOC_PARAMS , const char *file, const int line
-#define DMALLOC_ARGS , SHORT_FILE__, __LINE__
-#else
-#define DMALLOC_PARAMS
-#define DMALLOC_ARGS
-#endif /* defined(USE_DMALLOC) */
-
-/* Memory management */
-void *tor_malloc_(size_t size DMALLOC_PARAMS) ATTR_MALLOC;
-void *tor_malloc_zero_(size_t size DMALLOC_PARAMS) ATTR_MALLOC;
-void *tor_calloc_(size_t nmemb, size_t size DMALLOC_PARAMS) ATTR_MALLOC;
-void *tor_realloc_(void *ptr, size_t size DMALLOC_PARAMS);
-void *tor_reallocarray_(void *ptr, size_t size1, size_t size2 DMALLOC_PARAMS);
-char *tor_strdup_(const char *s DMALLOC_PARAMS) ATTR_MALLOC ATTR_NONNULL((1));
-char *tor_strndup_(const char *s, size_t n DMALLOC_PARAMS)
- ATTR_MALLOC ATTR_NONNULL((1));
-void *tor_memdup_(const void *mem, size_t len DMALLOC_PARAMS)
- ATTR_MALLOC ATTR_NONNULL((1));
-void *tor_memdup_nulterm_(const void *mem, size_t len DMALLOC_PARAMS)
- ATTR_MALLOC ATTR_NONNULL((1));
-void tor_free_(void *mem);
-uint64_t tor_htonll(uint64_t a);
-uint64_t tor_ntohll(uint64_t a);
-#ifdef USE_DMALLOC
-extern int dmalloc_free(const char *file, const int line, void *pnt,
- const int func_id);
-#define tor_free(p) STMT_BEGIN \
- if (PREDICT_LIKELY((p)!=NULL)) { \
- dmalloc_free(SHORT_FILE__, __LINE__, (p), 0); \
- (p)=NULL; \
- } \
- STMT_END
-#else /* !(defined(USE_DMALLOC)) */
-/** Release memory allocated by tor_malloc, tor_realloc, tor_strdup,
- * etc. Unlike the free() function, the tor_free() macro sets the
- * pointer value to NULL after freeing it.
- *
- * This is a macro. If you need a function pointer to release memory from
- * tor_malloc(), use tor_free_().
- *
- * Note that this macro takes the address of the pointer it is going to
- * free and clear. If that pointer is stored with a nonstandard
- * alignment (eg because of a "packed" pragma) it is not correct to use
- * tor_free().
- */
-#ifdef __GNUC__
-#define tor_free(p) STMT_BEGIN \
- typeof(&(p)) tor_free__tmpvar = &(p); \
- raw_free(*tor_free__tmpvar); \
- *tor_free__tmpvar=NULL; \
- STMT_END
-#else
-#define tor_free(p) STMT_BEGIN \
- raw_free(p); \
- (p)=NULL; \
- STMT_END
-#endif
-#endif /* defined(USE_DMALLOC) */
-
-#define tor_malloc(size) tor_malloc_(size DMALLOC_ARGS)
-#define tor_malloc_zero(size) tor_malloc_zero_(size DMALLOC_ARGS)
-#define tor_calloc(nmemb,size) tor_calloc_(nmemb, size DMALLOC_ARGS)
-#define tor_realloc(ptr, size) tor_realloc_(ptr, size DMALLOC_ARGS)
-#define tor_reallocarray(ptr, sz1, sz2) \
- tor_reallocarray_((ptr), (sz1), (sz2) DMALLOC_ARGS)
-#define tor_strdup(s) tor_strdup_(s DMALLOC_ARGS)
-#define tor_strndup(s, n) tor_strndup_(s, n DMALLOC_ARGS)
-#define tor_memdup(s, n) tor_memdup_(s, n DMALLOC_ARGS)
-#define tor_memdup_nulterm(s, n) tor_memdup_nulterm_(s, n DMALLOC_ARGS)
-
-/* Aliases for the underlying system malloc/realloc/free. Only use
- * them to indicate "I really want the underlying system function, I know
- * what I'm doing." */
-#define raw_malloc malloc
-#define raw_realloc realloc
-#define raw_free free
-#define raw_strdup strdup
-
-void tor_log_mallinfo(int severity);
-
-/* Helper macro: free a variable of type 'typename' using freefn, and
- * set the variable to NULL.
- */
-#define FREE_AND_NULL(typename, freefn, var) \
- do { \
- /* only evaluate (var) once. */ \
- typename **tmp__free__ptr ## freefn = &(var); \
- freefn(*tmp__free__ptr ## freefn); \
- (*tmp__free__ptr ## freefn) = NULL; \
- } while (0)
-
-/** Macro: yield a pointer to the field at position <b>off</b> within the
- * structure <b>st</b>. Example:
- * <pre>
- * struct a { int foo; int bar; } x;
- * off_t bar_offset = offsetof(struct a, bar);
- * int *bar_p = STRUCT_VAR_P(&x, bar_offset);
- * *bar_p = 3;
- * </pre>
- */
-#define STRUCT_VAR_P(st, off) ((void*) ( ((char*)(st)) + (off) ) )
-
-/** Macro: yield a pointer to an enclosing structure given a pointer to
- * a substructure at offset <b>off</b>. Example:
- * <pre>
- * struct base { ... };
- * struct subtype { int x; struct base b; } x;
- * struct base *bp = &x.base;
- * struct *sp = SUBTYPE_P(bp, struct subtype, b);
- * </pre>
- */
-#define SUBTYPE_P(p, subtype, basemember) \
- ((void*) ( ((char*)(p)) - offsetof(subtype, basemember) ))
-
-/* Logic */
-/** Macro: true if two values have the same boolean value. */
-#define bool_eq(a,b) (!(a)==!(b))
-/** Macro: true if two values have different boolean values. */
-#define bool_neq(a,b) (!(a)!=!(b))
-
-/* Math functions */
-double tor_mathlog(double d) ATTR_CONST;
-long tor_lround(double d) ATTR_CONST;
-int64_t tor_llround(double d) ATTR_CONST;
-int tor_log2(uint64_t u64) ATTR_CONST;
-uint64_t round_to_power_of_2(uint64_t u64);
-unsigned round_to_next_multiple_of(unsigned number, unsigned divisor);
-uint32_t round_uint32_to_next_multiple_of(uint32_t number, uint32_t divisor);
-uint64_t round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor);
-int64_t sample_laplace_distribution(double mu, double b, double p);
-int64_t add_laplace_noise(int64_t signal, double random, double delta_f,
- double epsilon);
-int n_bits_set_u8(uint8_t v);
-int64_t clamp_double_to_int64(double number);
-void simplify_fraction64(uint64_t *numer, uint64_t *denom);
-
-uint32_t tor_add_u32_nowrap(uint32_t a, uint32_t b);
-
-/* Compute the CEIL of <b>a</b> divided by <b>b</b>, for nonnegative <b>a</b>
- * and positive <b>b</b>. Works on integer types only. Not defined if a+(b-1)
- * can overflow. */
-#define CEIL_DIV(a,b) (((a)+((b)-1))/(b))
-
-/* Return <b>v</b> if it's between <b>min</b> and <b>max</b>. Otherwise
- * return <b>min</b> if <b>v</b> is smaller than <b>min</b>, or <b>max</b> if
- * <b>b</b> is larger than <b>max</b>.
- *
- * Requires that <b>min</b> is no more than <b>max</b>. May evaluate any of
- * its arguments more than once! */
-#define CLAMP(min,v,max) \
- ( ((v) < (min)) ? (min) : \
- ((v) > (max)) ? (max) : \
- (v) )
-
-/* String manipulation */
-
-/** Allowable characters in a hexadecimal string. */
-#define HEX_CHARACTERS "0123456789ABCDEFabcdef"
-void tor_strlower(char *s) ATTR_NONNULL((1));
-void tor_strupper(char *s) ATTR_NONNULL((1));
-int tor_strisprint(const char *s) ATTR_NONNULL((1));
-int tor_strisnonupper(const char *s) ATTR_NONNULL((1));
-int tor_strisspace(const char *s);
-int strcmp_opt(const char *s1, const char *s2);
-int strcmpstart(const char *s1, const char *s2) ATTR_NONNULL((1,2));
-int strcmp_len(const char *s1, const char *s2, size_t len) ATTR_NONNULL((1,2));
-int strcasecmpstart(const char *s1, const char *s2) ATTR_NONNULL((1,2));
-int strcmpend(const char *s1, const char *s2) ATTR_NONNULL((1,2));
-int strcasecmpend(const char *s1, const char *s2) ATTR_NONNULL((1,2));
-int fast_memcmpstart(const void *mem, size_t memlen, const char *prefix);
-
-void tor_strstrip(char *s, const char *strip) ATTR_NONNULL((1,2));
-long tor_parse_long(const char *s, int base, long min,
- long max, int *ok, char **next);
-unsigned long tor_parse_ulong(const char *s, int base, unsigned long min,
- unsigned long max, int *ok, char **next);
-double tor_parse_double(const char *s, double min, double max, int *ok,
- char **next);
-uint64_t tor_parse_uint64(const char *s, int base, uint64_t min,
- uint64_t max, int *ok, char **next);
-const char *hex_str(const char *from, size_t fromlen) ATTR_NONNULL((1));
-const char *eat_whitespace(const char *s);
-const char *eat_whitespace_eos(const char *s, const char *eos);
-const char *eat_whitespace_no_nl(const char *s);
-const char *eat_whitespace_eos_no_nl(const char *s, const char *eos);
-const char *find_whitespace(const char *s);
-const char *find_whitespace_eos(const char *s, const char *eos);
-const char *find_str_at_start_of_line(const char *haystack,
- const char *needle);
-int string_is_C_identifier(const char *string);
-int string_is_key_value(int severity, const char *string);
-int string_is_valid_dest(const char *string);
-int string_is_valid_nonrfc_hostname(const char *string);
-int string_is_valid_ipv4_address(const char *string);
-int string_is_valid_ipv6_address(const char *string);
-
-int tor_mem_is_zero(const char *mem, size_t len);
-int tor_digest_is_zero(const char *digest);
-int tor_digest256_is_zero(const char *digest);
-char *esc_for_log(const char *string) ATTR_MALLOC;
-char *esc_for_log_len(const char *chars, size_t n) ATTR_MALLOC;
-const char *escaped(const char *string);
-
-char *tor_escape_str_for_pt_args(const char *string,
- const char *chars_to_escape);
-
-struct smartlist_t;
-int tor_vsscanf(const char *buf, const char *pattern, va_list ap) \
- CHECK_SCANF(2, 0);
-int tor_sscanf(const char *buf, const char *pattern, ...)
- CHECK_SCANF(2, 3);
-
-void smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern, ...)
- CHECK_PRINTF(2, 3);
-void smartlist_add_vasprintf(struct smartlist_t *sl, const char *pattern,
- va_list args)
- CHECK_PRINTF(2, 0);
-void smartlist_add_strdup(struct smartlist_t *sl, const char *string);
-
-/* Time helpers */
-long tv_udiff(const struct timeval *start, const struct timeval *end);
-long tv_mdiff(const struct timeval *start, const struct timeval *end);
-int64_t tv_to_msec(const struct timeval *tv);
-int tor_timegm(const struct tm *tm, time_t *time_out);
-#define RFC1123_TIME_LEN 29
-void format_rfc1123_time(char *buf, time_t t);
-int parse_rfc1123_time(const char *buf, time_t *t);
-#define ISO_TIME_LEN 19
-#define ISO_TIME_USEC_LEN (ISO_TIME_LEN+7)
-void format_local_iso_time(char *buf, time_t t);
-void format_iso_time(char *buf, time_t t);
-void format_local_iso_time_nospace(char *buf, time_t t);
-void format_iso_time_nospace(char *buf, time_t t);
-void format_iso_time_nospace_usec(char *buf, const struct timeval *tv);
-int parse_iso_time_(const char *cp, time_t *t, int strict, int nospace);
-int parse_iso_time(const char *buf, time_t *t);
-int parse_iso_time_nospace(const char *cp, time_t *t);
-int parse_http_time(const char *buf, struct tm *tm);
-int format_time_interval(char *out, size_t out_len, long interval);
-
-/* Cached time */
-#ifdef TIME_IS_FAST
-#define approx_time() time(NULL)
-#define update_approx_time(t) STMT_NIL
-#else
-time_t approx_time(void);
-void update_approx_time(time_t now);
-#endif /* defined(TIME_IS_FAST) */
-
-/* Rate-limiter */
-
-/** A ratelim_t remembers how often an event is occurring, and how often
- * it's allowed to occur. Typical usage is something like:
- *
- <pre>
- if (possibly_very_frequent_event()) {
- const int INTERVAL = 300;
- static ratelim_t warning_limit = RATELIM_INIT(INTERVAL);
- char *m;
- if ((m = rate_limit_log(&warning_limit, approx_time()))) {
- log_warn(LD_GENERAL, "The event occurred!%s", m);
- tor_free(m);
- }
- }
- </pre>
-
- As a convenience wrapper for logging, you can replace the above with:
- <pre>
- if (possibly_very_frequent_event()) {
- static ratelim_t warning_limit = RATELIM_INIT(300);
- log_fn_ratelim(&warning_limit, LOG_WARN, LD_GENERAL,
- "The event occurred!");
- }
- </pre>
- */
-typedef struct ratelim_t {
- int rate;
- time_t last_allowed;
- int n_calls_since_last_time;
-} ratelim_t;
-
-#define RATELIM_INIT(r) { (r), 0, 0 }
-#define RATELIM_TOOMANY (16*1000*1000)
-
-char *rate_limit_log(ratelim_t *lim, time_t now);
-
-/* File helpers */
-ssize_t write_all(tor_socket_t fd, const char *buf, size_t count,int isSocket);
-ssize_t read_all(tor_socket_t fd, char *buf, size_t count, int isSocket);
-
-/** Status of an I/O stream. */
-enum stream_status {
- IO_STREAM_OKAY,
- IO_STREAM_EAGAIN,
- IO_STREAM_TERM,
- IO_STREAM_CLOSED
-};
-
-const char *stream_status_to_string(enum stream_status stream_status);
-
-enum stream_status get_string_from_pipe(int fd, char *buf, size_t count);
-
-MOCK_DECL(int,tor_unlink,(const char *pathname));
-
-/** Return values from file_status(); see that function's documentation
- * for details. */
-typedef enum { FN_ERROR, FN_NOENT, FN_FILE, FN_DIR, FN_EMPTY } file_status_t;
-file_status_t file_status(const char *filename);
-
-/** Possible behaviors for check_private_dir() on encountering a nonexistent
- * directory; see that function's documentation for details. */
-typedef unsigned int cpd_check_t;
-#define CPD_NONE 0
-#define CPD_CREATE (1u << 0)
-#define CPD_CHECK (1u << 1)
-#define CPD_GROUP_OK (1u << 2)
-#define CPD_GROUP_READ (1u << 3)
-#define CPD_CHECK_MODE_ONLY (1u << 4)
-#define CPD_RELAX_DIRMODE_CHECK (1u << 5)
-MOCK_DECL(int, check_private_dir,
- (const char *dirname, cpd_check_t check,
- const char *effective_user));
-
-#define OPEN_FLAGS_REPLACE (O_WRONLY|O_CREAT|O_TRUNC)
-#define OPEN_FLAGS_APPEND (O_WRONLY|O_CREAT|O_APPEND)
-#define OPEN_FLAGS_DONT_REPLACE (O_CREAT|O_EXCL|O_APPEND|O_WRONLY)
-typedef struct open_file_t open_file_t;
-int start_writing_to_file(const char *fname, int open_flags, int mode,
- open_file_t **data_out);
-FILE *start_writing_to_stdio_file(const char *fname, int open_flags, int mode,
- open_file_t **data_out);
-FILE *fdopen_file(open_file_t *file_data);
-int finish_writing_to_file(open_file_t *file_data);
-int abort_writing_to_file(open_file_t *file_data);
-MOCK_DECL(int,
-write_str_to_file,(const char *fname, const char *str, int bin));
-MOCK_DECL(int,
-write_bytes_to_file,(const char *fname, const char *str, size_t len,
- int bin));
-/** An ad-hoc type to hold a string of characters and a count; used by
- * write_chunks_to_file. */
-typedef struct sized_chunk_t {
- const char *bytes;
- size_t len;
-} sized_chunk_t;
-int write_chunks_to_file(const char *fname, const struct smartlist_t *chunks,
- int bin, int no_tempfile);
-int append_bytes_to_file(const char *fname, const char *str, size_t len,
- int bin);
-int write_bytes_to_new_file(const char *fname, const char *str, size_t len,
- int bin);
-
-/** 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. */
-#define RFTS_IGNORE_MISSING 2
-
-#ifndef _WIN32
-struct stat;
-#endif
-MOCK_DECL_ATTR(char *, read_file_to_str,
- (const char *filename, int flags, struct stat *stat_out),
- ATTR_MALLOC);
-char *read_file_to_str_until_eof(int fd, size_t max_bytes_to_read,
- size_t *sz_out)
- ATTR_MALLOC;
-const char *unescape_string(const char *s, char **result, size_t *size_out);
-char *get_unquoted_path(const char *path);
-char *expand_filename(const char *filename);
-MOCK_DECL(struct smartlist_t *, tor_listdir, (const char *dirname));
-int path_is_relative(const char *filename);
-
-/* Process helpers */
-void start_daemon(void);
-void finish_daemon(const char *desired_cwd);
-int write_pidfile(const char *filename);
-
-void tor_disable_spawning_background_processes(void);
-
-typedef struct process_handle_t process_handle_t;
-typedef struct process_environment_t process_environment_t;
-int tor_spawn_background(const char *const filename, const char **argv,
- process_environment_t *env,
- process_handle_t **process_handle_out);
-
-#define SPAWN_ERROR_MESSAGE "ERR: Failed to spawn background process - code "
-
-#ifdef _WIN32
-HANDLE load_windows_system_library(const TCHAR *library_name);
-#endif
-
-int environment_variable_names_equal(const char *s1, const char *s2);
-
-/* DOCDOC process_environment_t */
-struct process_environment_t {
- /** A pointer to a sorted empty-string-terminated sequence of
- * NUL-terminated strings of the form "NAME=VALUE". */
- char *windows_environment_block;
- /** A pointer to a NULL-terminated array of pointers to
- * NUL-terminated strings of the form "NAME=VALUE". */
- char **unixoid_environment_block;
-};
-
-process_environment_t *process_environment_make(struct smartlist_t *env_vars);
-void process_environment_free_(process_environment_t *env);
-#define process_environment_free(env) \
- FREE_AND_NULL(process_environment_t, process_environment_free_, (env))
-
-struct smartlist_t *get_current_process_environment_variables(void);
-
-void set_environment_variable_in_smartlist(struct smartlist_t *env_vars,
- const char *new_var,
- void (*free_old)(void*),
- int free_p);
-
-/* Values of process_handle_t.status. */
-#define PROCESS_STATUS_NOTRUNNING 0
-#define PROCESS_STATUS_RUNNING 1
-#define PROCESS_STATUS_ERROR -1
-
-#ifdef UTIL_PRIVATE
-struct waitpid_callback_t;
-/** Structure to represent the state of a process with which Tor is
- * communicating. The contents of this structure are private to util.c */
-struct process_handle_t {
- /** One of the PROCESS_STATUS_* values */
- int status;
-#ifdef _WIN32
- HANDLE stdin_pipe;
- HANDLE stdout_pipe;
- HANDLE stderr_pipe;
- PROCESS_INFORMATION pid;
-#else /* !(defined(_WIN32)) */
- int stdin_pipe;
- int stdout_pipe;
- int stderr_pipe;
- pid_t pid;
- /** If the process has not given us a SIGCHLD yet, this has the
- * waitpid_callback_t that gets invoked once it has. Otherwise this
- * contains NULL. */
- struct waitpid_callback_t *waitpid_cb;
- /** The exit status reported by waitpid. */
- int waitpid_exit_status;
-#endif /* defined(_WIN32) */
-};
-#endif /* defined(UTIL_PRIVATE) */
-
-/* Return values of tor_get_exit_code() */
-#define PROCESS_EXIT_RUNNING 1
-#define PROCESS_EXIT_EXITED 0
-#define PROCESS_EXIT_ERROR -1
-int tor_get_exit_code(process_handle_t *process_handle,
- int block, int *exit_code);
-int tor_split_lines(struct smartlist_t *sl, char *buf, int len);
-#ifdef _WIN32
-ssize_t tor_read_all_handle(HANDLE h, char *buf, size_t count,
- const process_handle_t *process);
-#else
-ssize_t tor_read_all_handle(int fd, char *buf, size_t count,
- const process_handle_t *process,
- int *eof);
-#endif /* defined(_WIN32) */
-ssize_t tor_read_all_from_process_stdout(
- const process_handle_t *process_handle, char *buf, size_t count);
-ssize_t tor_read_all_from_process_stderr(
- const process_handle_t *process_handle, char *buf, size_t count);
-char *tor_join_win_cmdline(const char *argv[]);
-
-int tor_process_get_pid(process_handle_t *process_handle);
-#ifdef _WIN32
-HANDLE tor_process_get_stdout_pipe(process_handle_t *process_handle);
-#else
-int tor_process_get_stdout_pipe(process_handle_t *process_handle);
-#endif
-
-#ifdef _WIN32
-MOCK_DECL(struct smartlist_t *,
-tor_get_lines_from_handle,(HANDLE *handle,
- enum stream_status *stream_status));
-#else
-MOCK_DECL(struct smartlist_t *,
-tor_get_lines_from_handle,(int fd,
- enum stream_status *stream_status));
-#endif /* defined(_WIN32) */
-
-int
-tor_terminate_process(process_handle_t *process_handle);
-
-MOCK_DECL(void,
-tor_process_handle_destroy,(process_handle_t *process_handle,
- int also_terminate_process));
-
-/* ===== Insecure rng */
-typedef struct tor_weak_rng_t {
- uint32_t state;
-} tor_weak_rng_t;
-
-#define TOR_WEAK_RNG_INIT {383745623}
-#define TOR_WEAK_RANDOM_MAX (INT_MAX)
-void tor_init_weak_random(tor_weak_rng_t *weak_rng, unsigned seed);
-int32_t tor_weak_random(tor_weak_rng_t *weak_rng);
-int32_t tor_weak_random_range(tor_weak_rng_t *rng, int32_t top);
-/** Randomly return true according to <b>rng</b> with probability 1 in
- * <b>n</b> */
-#define tor_weak_random_one_in_n(rng, n) (0==tor_weak_random_range((rng),(n)))
-
-int format_hex_number_sigsafe(unsigned long x, char *buf, int max_len);
-int format_dec_number_sigsafe(unsigned long x, char *buf, int max_len);
-
-#ifdef UTIL_PRIVATE
-/* Prototypes for private functions only used by util.c (and unit tests) */
-
-#ifndef _WIN32
-STATIC int format_helper_exit_status(unsigned char child_state,
- int saved_errno, char *hex_errno);
-
-/* Space for hex values of child state, a slash, saved_errno (with
- leading minus) and newline (no null) */
-#define HEX_ERRNO_SIZE (sizeof(char) * 2 + 1 + \
- 1 + sizeof(int) * 2 + 1)
-#endif /* !defined(_WIN32) */
-
-#endif /* defined(UTIL_PRIVATE) */
-
-int size_mul_check(const size_t x, const size_t y);
-
-#define ARRAY_LENGTH(x) ((sizeof(x)) / sizeof(x[0]))
-
-#endif /* !defined(TOR_UTIL_H) */
-
diff --git a/src/or/hs_ntor.c b/src/core/crypto/hs_ntor.c
index 809fa83bb8..d98d16f7f6 100644
--- a/src/or/hs_ntor.c
+++ b/src/core/crypto/hs_ntor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/** \file hs_ntor.c
@@ -24,9 +24,11 @@
* rendezvous key expansion to setup end-to-end rend circuit keys.
*/
-#include "or.h"
-#include "crypto_util.h"
-#include "hs_ntor.h"
+#include "core/or/or.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "core/crypto/hs_ntor.h"
/* String constants used by the ntor HS protocol */
#define PROTOID "tor-hs-ntor-curve25519-sha3-256-1"
@@ -616,4 +618,3 @@ hs_ntor_circuit_key_expansion(const uint8_t *ntor_key_seed, size_t seed_len,
return 0;
}
-
diff --git a/src/core/crypto/hs_ntor.h b/src/core/crypto/hs_ntor.h
new file mode 100644
index 0000000000..30738c4ae0
--- /dev/null
+++ b/src/core/crypto/hs_ntor.h
@@ -0,0 +1,69 @@
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_HS_NTOR_H
+#define TOR_HS_NTOR_H
+
+#include "core/or/or.h"
+struct ed25519_public_key_t;
+struct curve25519_public_key_t;
+struct curve25519_keypair_t;
+
+/* Output length of KDF for key expansion */
+#define HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN \
+ (DIGEST256_LEN*2 + CIPHER256_KEY_LEN*2)
+
+/* Key material needed to encode/decode INTRODUCE1 cells */
+typedef struct {
+ /* Key used for encryption of encrypted INTRODUCE1 blob */
+ uint8_t enc_key[CIPHER256_KEY_LEN];
+ /* MAC key used to protect encrypted INTRODUCE1 blob */
+ uint8_t mac_key[DIGEST256_LEN];
+} hs_ntor_intro_cell_keys_t;
+
+/* Key material needed to encode/decode RENDEZVOUS1 cells */
+typedef struct {
+ /* This is the MAC of the HANDSHAKE_INFO field */
+ uint8_t rend_cell_auth_mac[DIGEST256_LEN];
+ /* This is the key seed used to derive further rendezvous crypto keys as
+ * detailed in section 4.2.1 of rend-spec-ng.txt. */
+ uint8_t ntor_key_seed[DIGEST256_LEN];
+} hs_ntor_rend_cell_keys_t;
+
+int hs_ntor_client_get_introduce1_keys(
+ const struct ed25519_public_key_t *intro_auth_pubkey,
+ const struct curve25519_public_key_t *intro_enc_pubkey,
+ const struct curve25519_keypair_t *client_ephemeral_enc_keypair,
+ const uint8_t *subcredential,
+ hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out);
+
+int hs_ntor_client_get_rendezvous1_keys(
+ const struct ed25519_public_key_t *intro_auth_pubkey,
+ const struct curve25519_keypair_t *client_ephemeral_enc_keypair,
+ const struct curve25519_public_key_t *intro_enc_pubkey,
+ const struct curve25519_public_key_t *service_ephemeral_rend_pubkey,
+ hs_ntor_rend_cell_keys_t *hs_ntor_rend_cell_keys_out);
+
+int hs_ntor_service_get_introduce1_keys(
+ const struct ed25519_public_key_t *intro_auth_pubkey,
+ const struct curve25519_keypair_t *intro_enc_keypair,
+ const struct curve25519_public_key_t *client_ephemeral_enc_pubkey,
+ const uint8_t *subcredential,
+ hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out);
+
+int hs_ntor_service_get_rendezvous1_keys(
+ const struct ed25519_public_key_t *intro_auth_pubkey,
+ const struct curve25519_keypair_t *intro_enc_keypair,
+ const struct curve25519_keypair_t *service_ephemeral_rend_keypair,
+ const struct curve25519_public_key_t *client_ephemeral_enc_pubkey,
+ hs_ntor_rend_cell_keys_t *hs_ntor_rend_cell_keys_out);
+
+int hs_ntor_circuit_key_expansion(const uint8_t *ntor_key_seed,
+ size_t seed_len,
+ uint8_t *keys_out, size_t keys_out_len);
+
+int hs_ntor_client_rendezvous2_mac_is_good(
+ const hs_ntor_rend_cell_keys_t *hs_ntor_rend_cell_keys,
+ const uint8_t *rcvd_mac);
+
+#endif /* !defined(TOR_HS_NTOR_H) */
diff --git a/src/or/onion.c b/src/core/crypto/onion.c
index 829be12bae..e71bfc1fd9 100644
--- a/src/or/onion.c
+++ b/src/core/crypto/onion.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -62,23 +62,28 @@
* onion_fast.c for more information.
**/
-#include "or.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "config.h"
-#include "cpuworker.h"
-#include "crypto_util.h"
-#include "networkstatus.h"
-#include "onion.h"
-#include "onion_fast.h"
-#include "onion_ntor.h"
-#include "onion_tap.h"
-#include "relay.h"
-#include "rephist.h"
-#include "router.h"
+#include "core/or/or.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "app/config/config.h"
+#include "core/mainloop/cpuworker.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "feature/nodelist/networkstatus.h"
+#include "core/crypto/onion.h"
+#include "core/crypto/onion_fast.h"
+#include "core/crypto/onion_ntor.h"
+#include "core/crypto/onion_tap.h"
+#include "core/or/relay.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/extend_info_st.h"
+#include "core/or/or_circuit_st.h"
// trunnel
-#include "ed25519_cert.h"
+#include "trunnel/ed25519_cert.h"
/** Type for a linked list of circuits that are waiting for a free CPU worker
* to process a waiting onion handshake. */
@@ -554,7 +559,7 @@ onion_skin_server_handshake(int type,
(char*)keys_out, keys_out_len)<0)
return -1;
r = TAP_ONIONSKIN_REPLY_LEN;
- memcpy(rend_nonce_out, reply_out+DH_KEY_LEN, DIGEST_LEN);
+ memcpy(rend_nonce_out, reply_out+DH1024_KEY_LEN, DIGEST_LEN);
break;
case ONION_HANDSHAKE_TYPE_FAST:
if (onionskin_len != CREATE_FAST_LEN)
@@ -631,7 +636,7 @@ onion_skin_client_handshake(int type,
msg_out) < 0)
return -1;
- memcpy(rend_authenticator_out, reply+DH_KEY_LEN, DIGEST_LEN);
+ memcpy(rend_authenticator_out, reply+DH1024_KEY_LEN, DIGEST_LEN);
return 0;
case ONION_HANDSHAKE_TYPE_FAST:
@@ -1339,4 +1344,3 @@ extended_cell_format(uint8_t *command_out, uint16_t *len_out,
return 0;
}
-
diff --git a/src/or/onion.h b/src/core/crypto/onion.h
index 3b738debeb..ff70f299d5 100644
--- a/src/or/onion.h
+++ b/src/core/crypto/onion.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,6 +13,10 @@
#define TOR_ONION_H
struct create_cell_t;
+struct curve25519_keypair_t;
+struct curve25519_public_key_t;
+#include "lib/crypt_ops/crypto_ed25519.h"
+
int onion_pending_add(or_circuit_t *circ, struct create_cell_t *onionskin);
or_circuit_t *onion_next_task(struct create_cell_t **onionskin_out);
int onion_num_pending(uint16_t handshake_type);
@@ -23,8 +27,8 @@ typedef struct server_onion_keys_t {
uint8_t my_identity[DIGEST_LEN];
crypto_pk_t *onion_key;
crypto_pk_t *last_onion_key;
- di_digest256_map_t *curve25519_key_map;
- curve25519_keypair_t *junk_keypair;
+ struct di_digest256_map_t *curve25519_key_map;
+ struct curve25519_keypair_t *junk_keypair;
} server_onion_keys_t;
#define MAX_ONIONSKIN_CHALLENGE_LEN 255
@@ -88,7 +92,7 @@ typedef struct extend_cell_t {
/** Identity fingerprint of the node we're conecting to.*/
uint8_t node_id[DIGEST_LEN];
/** Ed25519 public identity key. Zero if not set. */
- ed25519_public_key_t ed_pubkey;
+ struct ed25519_public_key_t ed_pubkey;
/** The "create cell" embedded in this extend cell. Note that unlike the
* create cells we generate ourself, this once can have a handshake type we
* don't recognize. */
@@ -122,4 +126,3 @@ int extended_cell_format(uint8_t *command_out, uint16_t *len_out,
uint8_t *payload_out, const extended_cell_t *cell_in);
#endif /* !defined(TOR_ONION_H) */
-
diff --git a/src/or/onion_fast.c b/src/core/crypto/onion_fast.c
index 9f9b2199d4..292aeca402 100644
--- a/src/or/onion_fast.c
+++ b/src/core/crypto/onion_fast.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -27,10 +27,11 @@
* many RSA1024 keys.
**/
-#include "or.h"
-#include "onion_fast.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
+#include "core/or/or.h"
+#include "core/crypto/onion_fast.h"
+#include "lib/crypt_ops/crypto_hkdf.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
/** Release all state held in <b>victim</b>. */
void
@@ -141,4 +142,3 @@ fast_client_handshake(const fast_handshake_state_t *handshake_state,
tor_free(out);
return r;
}
-
diff --git a/src/or/onion_fast.h b/src/core/crypto/onion_fast.h
index c56712e2c2..a7b6ec53f4 100644
--- a/src/or/onion_fast.h
+++ b/src/core/crypto/onion_fast.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/or/onion_ntor.c b/src/core/crypto/onion_ntor.c
index 02d43cb722..9e1e273ef6 100644
--- a/src/or/onion_ntor.c
+++ b/src/core/crypto/onion_ntor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -21,12 +21,17 @@
#include "orconfig.h"
#define ONION_NTOR_PRIVATE
-#include "crypto.h"
-#include "crypto_digest.h"
-#include "crypto_util.h"
-#include "onion_ntor.h"
-#include "torlog.h"
-#include "util.h"
+
+#include "lib/crypt_ops/crypto.h"
+#include "lib/crypt_ops/crypto_digest.h"
+#include "lib/crypt_ops/crypto_hkdf.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "core/crypto/onion_ntor.h"
+
+#include <string.h>
/** Free storage held in an ntor handshake state. */
void
@@ -334,4 +339,3 @@ onion_skin_ntor_client_handshake(
return bad ? -1 : 0;
}
-
diff --git a/src/or/onion_ntor.h b/src/core/crypto/onion_ntor.h
index f7c962b7d0..0ba4abe49e 100644
--- a/src/or/onion_ntor.h
+++ b/src/core/crypto/onion_ntor.h
@@ -1,12 +1,14 @@
-/* Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_ONION_NTOR_H
#define TOR_ONION_NTOR_H
-#include "torint.h"
-#include "crypto_curve25519.h"
-#include "di_ops.h"
+#include "lib/cc/torint.h"
+
+struct di_digest256_map_t;
+struct curve25519_public_key_t;
+struct curve25519_keypair_t;
/** State to be maintained by a client between sending an ntor onionskin
* and receiving a reply. */
@@ -22,17 +24,17 @@ void ntor_handshake_state_free_(ntor_handshake_state_t *state);
FREE_AND_NULL(ntor_handshake_state_t, ntor_handshake_state_free_, (state))
int onion_skin_ntor_create(const uint8_t *router_id,
- const curve25519_public_key_t *router_key,
+ const struct curve25519_public_key_t *router_key,
ntor_handshake_state_t **handshake_state_out,
uint8_t *onion_skin_out);
int onion_skin_ntor_server_handshake(const uint8_t *onion_skin,
- const di_digest256_map_t *private_keys,
- const curve25519_keypair_t *junk_keypair,
- const uint8_t *my_node_id,
- uint8_t *handshake_reply_out,
- uint8_t *key_out,
- size_t key_out_len);
+ const struct di_digest256_map_t *private_keys,
+ const struct curve25519_keypair_t *junk_keypair,
+ const uint8_t *my_node_id,
+ uint8_t *handshake_reply_out,
+ uint8_t *key_out,
+ size_t key_out_len);
int onion_skin_ntor_client_handshake(
const ntor_handshake_state_t *handshake_state,
@@ -42,6 +44,7 @@ int onion_skin_ntor_client_handshake(
const char **msg_out);
#ifdef ONION_NTOR_PRIVATE
+#include "lib/crypt_ops/crypto_curve25519.h"
/** Storage held by a client while waiting for an ntor reply from a server. */
struct ntor_handshake_state_t {
@@ -60,4 +63,3 @@ struct ntor_handshake_state_t {
#endif /* defined(ONION_NTOR_PRIVATE) */
#endif /* !defined(TOR_ONION_NTOR_H) */
-
diff --git a/src/or/onion_tap.c b/src/core/crypto/onion_tap.c
index 44737034f4..7ffe0ea5c5 100644
--- a/src/or/onion_tap.c
+++ b/src/core/crypto/onion_tap.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -27,12 +27,13 @@
* invoked from onion.c.
**/
-#include "or.h"
-#include "config.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "onion_tap.h"
-#include "rephist.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "core/crypto/onion_tap.h"
+#include "feature/stats/rephist.h"
/*----------------------------------------------------------------------*/
@@ -53,7 +54,7 @@ onion_skin_TAP_create(crypto_pk_t *dest_router_key,
crypto_dh_t **handshake_state_out,
char *onion_skin_out) /* TAP_ONIONSKIN_CHALLENGE_LEN bytes */
{
- char challenge[DH_KEY_LEN];
+ char challenge[DH1024_KEY_LEN];
crypto_dh_t *dh = NULL;
int dhbytes, pkbytes;
@@ -77,7 +78,7 @@ onion_skin_TAP_create(crypto_pk_t *dest_router_key,
/* set meeting point, meeting cookie, etc here. Leave zero for now. */
if (crypto_pk_obsolete_public_hybrid_encrypt(dest_router_key, onion_skin_out,
TAP_ONIONSKIN_CHALLENGE_LEN,
- challenge, DH_KEY_LEN,
+ challenge, DH1024_KEY_LEN,
PK_PKCS1_OAEP_PADDING, 1)<0)
goto err;
@@ -136,7 +137,7 @@ onion_skin_TAP_server_handshake(
log_info(LD_PROTOCOL,
"Couldn't decrypt onionskin: client may be using old onion key");
goto err;
- } else if (len != DH_KEY_LEN) {
+ } else if (len != DH1024_KEY_LEN) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Unexpected onionskin length after decryption: %ld",
(long)len);
@@ -152,7 +153,7 @@ onion_skin_TAP_server_handshake(
goto err;
/* LCOV_EXCL_STOP */
}
- if (crypto_dh_get_public(dh, handshake_reply_out, DH_KEY_LEN)) {
+ if (crypto_dh_get_public(dh, handshake_reply_out, DH1024_KEY_LEN)) {
/* LCOV_EXCL_START
* This can only fail if the length of the key we just allocated is too
* big. That should be impossible. */
@@ -164,7 +165,7 @@ onion_skin_TAP_server_handshake(
key_material_len = DIGEST_LEN+key_out_len;
key_material = tor_malloc(key_material_len);
len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh, challenge,
- DH_KEY_LEN, key_material,
+ DH1024_KEY_LEN, key_material,
key_material_len);
if (len < 0) {
log_info(LD_GENERAL, "crypto_dh_compute_secret failed.");
@@ -172,7 +173,7 @@ onion_skin_TAP_server_handshake(
}
/* send back H(K|0) as proof that we learned K. */
- memcpy(handshake_reply_out+DH_KEY_LEN, key_material, DIGEST_LEN);
+ memcpy(handshake_reply_out+DH1024_KEY_LEN, key_material, DIGEST_LEN);
/* use the rest of the key material for our shared keys, digests, etc */
memcpy(key_out, key_material+DIGEST_LEN, key_out_len);
@@ -212,12 +213,12 @@ onion_skin_TAP_client_handshake(crypto_dh_t *handshake_state,
ssize_t len;
char *key_material=NULL;
size_t key_material_len;
- tor_assert(crypto_dh_get_bytes(handshake_state) == DH_KEY_LEN);
+ tor_assert(crypto_dh_get_bytes(handshake_state) == DH1024_KEY_LEN);
key_material_len = DIGEST_LEN + key_out_len;
key_material = tor_malloc(key_material_len);
len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, handshake_state,
- handshake_reply, DH_KEY_LEN, key_material,
+ handshake_reply, DH1024_KEY_LEN, key_material,
key_material_len);
if (len < 0) {
if (msg_out)
@@ -225,7 +226,7 @@ onion_skin_TAP_client_handshake(crypto_dh_t *handshake_state,
goto err;
}
- if (tor_memneq(key_material, handshake_reply+DH_KEY_LEN, DIGEST_LEN)) {
+ if (tor_memneq(key_material, handshake_reply+DH1024_KEY_LEN, DIGEST_LEN)) {
/* H(K) does *not* match. Something fishy. */
if (msg_out)
*msg_out = "Digest DOES NOT MATCH on onion handshake. Bug or attack.";
@@ -243,4 +244,3 @@ onion_skin_TAP_client_handshake(crypto_dh_t *handshake_state,
tor_free(key_material);
return -1;
}
-
diff --git a/src/or/onion_tap.h b/src/core/crypto/onion_tap.h
index 713c1d7391..9a3df684d6 100644
--- a/src/or/onion_tap.h
+++ b/src/core/crypto/onion_tap.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,25 +14,27 @@
#define TAP_ONIONSKIN_CHALLENGE_LEN (PKCS1_OAEP_PADDING_OVERHEAD+\
CIPHER_KEY_LEN+\
- DH_KEY_LEN)
-#define TAP_ONIONSKIN_REPLY_LEN (DH_KEY_LEN+DIGEST_LEN)
+ DH1024_KEY_LEN)
+#define TAP_ONIONSKIN_REPLY_LEN (DH1024_KEY_LEN+DIGEST_LEN)
-int onion_skin_TAP_create(crypto_pk_t *router_key,
- crypto_dh_t **handshake_state_out,
+struct crypto_dh_t;
+struct crypto_pk_t;
+
+int onion_skin_TAP_create(struct crypto_pk_t *router_key,
+ struct crypto_dh_t **handshake_state_out,
char *onion_skin_out);
int onion_skin_TAP_server_handshake(const char *onion_skin,
- crypto_pk_t *private_key,
- crypto_pk_t *prev_private_key,
+ struct crypto_pk_t *private_key,
+ struct crypto_pk_t *prev_private_key,
char *handshake_reply_out,
char *key_out,
size_t key_out_len);
-int onion_skin_TAP_client_handshake(crypto_dh_t *handshake_state,
+int onion_skin_TAP_client_handshake(struct crypto_dh_t *handshake_state,
const char *handshake_reply,
char *key_out,
size_t key_out_len,
const char **msg_out);
#endif /* !defined(TOR_ONION_TAP_H) */
-
diff --git a/src/or/relay_crypto.c b/src/core/crypto/relay_crypto.c
index 530c8e5828..b2388d2c45 100644
--- a/src/or/relay_crypto.c
+++ b/src/core/crypto/relay_crypto.c
@@ -4,12 +4,18 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "config.h"
-#include "crypto_util.h"
-#include "hs_ntor.h" // for HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN
-#include "relay.h"
-#include "relay_crypto.h"
+#include "core/or/or.h"
+#include "core/or/circuitlist.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "core/crypto/hs_ntor.h" // for HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN
+#include "core/or/relay.h"
+#include "core/crypto/relay_crypto.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/or_circuit_st.h"
+#include "core/or/origin_circuit_st.h"
/** Update digest from the payload of cell. Assign integrity part to
* cell.
@@ -324,4 +330,3 @@ relay_crypto_assert_ok(const relay_crypto_t *crypto)
tor_assert(crypto->f_digest);
tor_assert(crypto->b_digest);
}
-
diff --git a/src/or/relay_crypto.h b/src/core/crypto/relay_crypto.h
index 66ae02cee9..67da93344f 100644
--- a/src/or/relay_crypto.h
+++ b/src/core/crypto/relay_crypto.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/include.am b/src/core/include.am
new file mode 100644
index 0000000000..1f37044e9a
--- /dev/null
+++ b/src/core/include.am
@@ -0,0 +1,330 @@
+
+noinst_LIBRARIES += \
+ src/core/libtor-app.a
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += \
+ src/core/libtor-app-testing.a
+endif
+
+LIBTOR_APP_A_SOURCES = \
+ src/app/config/config.c \
+ src/app/config/confparse.c \
+ src/app/config/statefile.c \
+ src/core/crypto/hs_ntor.c \
+ src/core/crypto/onion.c \
+ src/core/crypto/onion_fast.c \
+ src/core/crypto/onion_ntor.c \
+ src/core/crypto/onion_tap.c \
+ src/core/crypto/relay_crypto.c \
+ src/core/mainloop/connection.c \
+ src/core/mainloop/cpuworker.c \
+ src/core/mainloop/main.c \
+ src/core/mainloop/periodic.c \
+ src/core/or/address_set.c \
+ src/core/or/channel.c \
+ src/core/or/channelpadding.c \
+ src/core/or/channeltls.c \
+ src/core/or/circuitbuild.c \
+ src/core/or/circuitlist.c \
+ src/core/or/circuitmux.c \
+ src/core/or/circuitmux_ewma.c \
+ src/core/or/circuitstats.c \
+ src/core/or/circuituse.c \
+ src/core/or/command.c \
+ src/core/or/connection_edge.c \
+ src/core/or/connection_or.c \
+ src/core/or/dos.c \
+ src/core/or/git_revision.c \
+ src/core/or/policies.c \
+ src/core/or/protover.c \
+ src/core/or/reasons.c \
+ src/core/or/relay.c \
+ src/core/or/scheduler.c \
+ src/core/or/scheduler_kist.c \
+ src/core/or/scheduler_vanilla.c \
+ src/core/or/status.c \
+ src/core/proto/proto_cell.c \
+ src/core/proto/proto_control0.c \
+ src/core/proto/proto_ext_or.c \
+ src/core/proto/proto_http.c \
+ src/core/proto/proto_socks.c \
+ src/core/proto/protover_rust.c \
+ src/feature/api/tor_api.c \
+ src/feature/client/addressmap.c \
+ src/feature/client/bridges.c \
+ src/feature/client/circpathbias.c \
+ src/feature/client/dnsserv.c \
+ src/feature/client/entrynodes.c \
+ src/feature/client/transports.c \
+ src/feature/control/control.c \
+ src/feature/dirauth/keypin.c \
+ src/feature/dircache/conscache.c \
+ src/feature/dircache/consdiffmgr.c \
+ src/feature/dircache/directory.c \
+ src/feature/dircache/dirserv.c \
+ src/feature/dircommon/consdiff.c \
+ src/feature/dircommon/fp_pair.c \
+ src/feature/dircommon/voting_schedule.c \
+ src/feature/hibernate/hibernate.c \
+ src/feature/hs/hs_cache.c \
+ src/feature/hs/hs_cell.c \
+ src/feature/hs/hs_circuit.c \
+ src/feature/hs/hs_circuitmap.c \
+ src/feature/hs/hs_client.c \
+ src/feature/hs/hs_common.c \
+ src/feature/hs/hs_config.c \
+ src/feature/hs/hs_control.c \
+ src/feature/hs/hs_descriptor.c \
+ src/feature/hs/hs_ident.c \
+ src/feature/hs/hs_intropoint.c \
+ src/feature/hs/hs_service.c \
+ src/feature/hs/hs_stats.c \
+ src/feature/hs_common/replaycache.c \
+ src/feature/hs_common/shared_random_client.c \
+ src/feature/nodelist/microdesc.c \
+ src/feature/nodelist/networkstatus.c \
+ src/feature/nodelist/nodelist.c \
+ src/feature/nodelist/parsecommon.c \
+ src/feature/nodelist/routerlist.c \
+ src/feature/nodelist/routerparse.c \
+ src/feature/nodelist/routerset.c \
+ src/feature/nodelist/torcert.c \
+ src/feature/relay/dns.c \
+ src/feature/relay/ext_orport.c \
+ src/feature/relay/router.c \
+ src/feature/relay/routerkeys.c \
+ src/feature/rend/rendcache.c \
+ src/feature/rend/rendclient.c \
+ src/feature/rend/rendcommon.c \
+ src/feature/rend/rendmid.c \
+ src/feature/rend/rendservice.c \
+ src/feature/stats/geoip.c \
+ src/feature/stats/rephist.c
+
+if BUILD_NT_SERVICES
+LIBTOR_APP_A_SOURCES += src/app/main/ntmain.c
+endif
+
+#
+# Modules are conditionnally compiled in tor starting here. We add the C files
+# only if the modules has been enabled at configure time. We always add the
+# source files of every module to libtor-testing.a so we can build the unit
+# tests for everything. See the UNITTESTS_ENABLED branch below.
+#
+LIBTOR_APP_TESTING_A_SOURCES = $(LIBTOR_APP_A_SOURCES)
+
+# The Directory Authority module.
+MODULE_DIRAUTH_SOURCES = \
+ src/feature/dirauth/dircollate.c \
+ src/feature/dirauth/dirvote.c \
+ src/feature/dirauth/shared_random.c \
+ src/feature/dirauth/shared_random_state.c
+
+if BUILD_MODULE_DIRAUTH
+LIBTOR_APP_A_SOURCES += $(MODULE_DIRAUTH_SOURCES)
+endif
+
+src_core_libtor_app_a_SOURCES = $(LIBTOR_APP_A_SOURCES)
+if UNITTESTS_ENABLED
+
+# Add the sources of the modules that are needed for tests to work here.
+LIBTOR_APP_TESTING_A_SOURCES += $(MODULE_DIRAUTH_SOURCES)
+
+src_core_libtor_app_testing_a_SOURCES = $(LIBTOR_APP_TESTING_A_SOURCES)
+else
+src_core_libtor_app_testing_a_SOURCES =
+endif
+
+src/core/or/git_revision.$(OBJEXT) \
+ src/core/or/src_core_libtor_app_testing_a-git_revision.$(OBJEXT): \
+ micro-revision.i
+
+AM_CPPFLAGS += -DSHARE_DATADIR="\"$(datadir)\"" \
+ -DLOCALSTATEDIR="\"$(localstatedir)\"" \
+ -DBINDIR="\"$(bindir)\""
+
+src_core_libtor_app_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_core_libtor_app_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/app/config/config.h \
+ src/app/config/confparse.h \
+ src/app/config/or_options_st.h \
+ src/app/config/or_state_st.h \
+ src/app/config/statefile.h \
+ src/app/main/ntmain.h \
+ src/core/crypto/hs_ntor.h \
+ src/core/crypto/onion.h \
+ src/core/crypto/onion_fast.h \
+ src/core/crypto/onion_ntor.h \
+ src/core/crypto/onion_tap.h \
+ src/core/crypto/relay_crypto.h \
+ src/core/mainloop/connection.h \
+ src/core/mainloop/cpuworker.h \
+ src/core/mainloop/main.h \
+ src/core/mainloop/periodic.h \
+ src/core/or/addr_policy_st.h \
+ src/core/or/address_set.h \
+ src/core/or/cell_queue_st.h \
+ src/core/or/cell_st.h \
+ src/core/or/channel.h \
+ src/core/or/channelpadding.h \
+ src/core/or/channeltls.h \
+ src/core/or/circuit_st.h \
+ src/core/or/circuitbuild.h \
+ src/core/or/circuitlist.h \
+ src/core/or/circuitmux.h \
+ src/core/or/circuitmux_ewma.h \
+ src/core/or/circuitstats.h \
+ src/core/or/circuituse.h \
+ src/core/or/command.h \
+ src/core/or/connection_edge.h \
+ src/core/or/connection_or.h \
+ src/core/or/connection_st.h \
+ src/core/or/cpath_build_state_st.h \
+ src/core/or/crypt_path_reference_st.h \
+ src/core/or/crypt_path_st.h \
+ src/core/or/destroy_cell_queue_st.h \
+ src/core/or/dos.h \
+ src/core/or/edge_connection_st.h \
+ src/core/or/entry_connection_st.h \
+ src/core/or/entry_port_cfg_st.h \
+ src/core/or/extend_info_st.h \
+ src/core/or/git_revision.h \
+ src/core/or/listener_connection_st.h \
+ src/core/or/or.h \
+ src/core/or/or_circuit_st.h \
+ src/core/or/or_connection_st.h \
+ src/core/or/or_handshake_certs_st.h \
+ src/core/or/or_handshake_state_st.h \
+ src/core/or/origin_circuit_st.h \
+ src/core/or/policies.h \
+ src/core/or/port_cfg_st.h \
+ src/core/or/protover.h \
+ src/core/or/reasons.h \
+ src/core/or/relay.h \
+ src/core/or/relay_crypto_st.h \
+ src/core/or/scheduler.h \
+ src/core/or/server_port_cfg_st.h \
+ src/core/or/socks_request_st.h \
+ src/core/or/status.h \
+ src/core/or/tor_version_st.h \
+ src/core/or/var_cell_st.h \
+ src/core/proto/proto_cell.h \
+ src/core/proto/proto_control0.h \
+ src/core/proto/proto_ext_or.h \
+ src/core/proto/proto_http.h \
+ src/core/proto/proto_socks.h \
+ src/feature/api/tor_api_internal.h \
+ src/feature/client/addressmap.h \
+ src/feature/client/bridges.h \
+ src/feature/client/circpathbias.h \
+ src/feature/client/dnsserv.h \
+ src/feature/client/entrynodes.h \
+ src/feature/client/transports.h \
+ src/feature/control/control.h \
+ src/feature/control/control_connection_st.h \
+ src/feature/dirauth/dircollate.h \
+ src/feature/dirauth/dirvote.h \
+ src/feature/dirauth/keypin.h \
+ src/feature/dirauth/mode.h \
+ src/feature/dirauth/ns_detached_signatures_st.h \
+ src/feature/dirauth/shared_random.h \
+ src/feature/dirauth/shared_random_state.h \
+ src/feature/dirauth/vote_microdesc_hash_st.h \
+ src/feature/dircache/cached_dir_st.h \
+ src/feature/dircache/conscache.h \
+ src/feature/dircache/consdiffmgr.h \
+ src/feature/dircache/directory.h \
+ src/feature/dircache/dirserv.h \
+ src/feature/dirclient/dir_server_st.h \
+ src/feature/dirclient/download_status_st.h \
+ src/feature/dircommon/consdiff.h \
+ src/feature/dircommon/dir_connection_st.h \
+ src/feature/dircommon/fp_pair.h \
+ src/feature/dircommon/vote_timing_st.h \
+ src/feature/dircommon/voting_schedule.h \
+ src/feature/hibernate/hibernate.h \
+ src/feature/hs/hs_cache.h \
+ src/feature/hs/hs_cell.h \
+ src/feature/hs/hs_circuit.h \
+ src/feature/hs/hs_circuitmap.h \
+ src/feature/hs/hs_client.h \
+ src/feature/hs/hs_common.h \
+ src/feature/hs/hs_config.h \
+ src/feature/hs/hs_control.h \
+ src/feature/hs/hs_descriptor.h \
+ src/feature/hs/hs_ident.h \
+ src/feature/hs/hs_intropoint.h \
+ src/feature/hs/hs_service.h \
+ src/feature/hs/hs_stats.h \
+ src/feature/hs/hsdir_index_st.h \
+ src/feature/hs_common/replaycache.h \
+ src/feature/hs_common/shared_random_client.h \
+ src/feature/nodelist/authority_cert_st.h \
+ src/feature/nodelist/desc_store_st.h \
+ src/feature/nodelist/document_signature_st.h \
+ src/feature/nodelist/extrainfo_st.h \
+ src/feature/nodelist/microdesc.h \
+ src/feature/nodelist/microdesc_st.h \
+ src/feature/nodelist/networkstatus.h \
+ src/feature/nodelist/networkstatus_sr_info_st.h \
+ src/feature/nodelist/networkstatus_st.h \
+ src/feature/nodelist/networkstatus_voter_info_st.h \
+ src/feature/nodelist/node_st.h \
+ src/feature/nodelist/nodelist.h \
+ src/feature/nodelist/parsecommon.h \
+ src/feature/nodelist/routerinfo_st.h \
+ src/feature/nodelist/routerlist.h \
+ src/feature/nodelist/routerlist_st.h \
+ src/feature/nodelist/routerparse.h \
+ src/feature/nodelist/routerset.h \
+ src/feature/nodelist/routerstatus_st.h \
+ src/feature/nodelist/signed_descriptor_st.h \
+ src/feature/nodelist/torcert.h \
+ src/feature/nodelist/vote_routerstatus_st.h \
+ src/feature/relay/dns.h \
+ src/feature/relay/dns_structs.h \
+ src/feature/relay/ext_orport.h \
+ src/feature/relay/router.h \
+ src/feature/relay/routerkeys.h \
+ src/feature/rend/rend_authorized_client_st.h \
+ src/feature/rend/rend_encoded_v2_service_descriptor_st.h \
+ src/feature/rend/rend_intro_point_st.h \
+ src/feature/rend/rend_service_descriptor_st.h \
+ src/feature/rend/rendcache.h \
+ src/feature/rend/rendclient.h \
+ src/feature/rend/rendcommon.h \
+ src/feature/rend/rendmid.h \
+ src/feature/rend/rendservice.h \
+ src/feature/stats/geoip.h \
+ src/feature/stats/rephist.h
+
+noinst_HEADERS += \
+ src/app/config/auth_dirs.inc \
+ src/app/config/fallback_dirs.inc
+
+# This may someday want to be an installed file?
+noinst_HEADERS += src/feature/api/tor_api.h
+
+micro-revision.i: FORCE
+ $(AM_V_at)rm -f micro-revision.tmp; \
+ if test -r "$(top_srcdir)/.git" && \
+ test -x "`which git 2>&1;true`"; then \
+ HASH="`cd "$(top_srcdir)" && git rev-parse --short=16 HEAD`"; \
+ echo \"$$HASH\" > micro-revision.tmp; \
+ fi; \
+ if test ! -f micro-revision.tmp; then \
+ if test ! -f micro-revision.i; then \
+ echo '""' > micro-revision.i; \
+ fi; \
+ elif test ! -f micro-revision.i || \
+ test x"`cat micro-revision.tmp`" != x"`cat micro-revision.i`"; then \
+ mv micro-revision.tmp micro-revision.i; \
+ fi; \
+ rm -f micro-revision.tmp; \
+ true
+
+CLEANFILES+= micro-revision.i micro-revision.tmp
+
+FORCE:
diff --git a/src/or/connection.c b/src/core/mainloop/connection.c
index 7283a81043..ed789d5208 100644
--- a/src/or/connection.c
+++ b/src/core/mainloop/connection.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -55,64 +55,84 @@
**/
#define CONNECTION_PRIVATE
-#include "or.h"
-#include "bridges.h"
-#include "buffers.h"
-#include "buffers_tls.h"
+#include "core/or/or.h"
+#include "feature/client/bridges.h"
+#include "lib/container/buffers.h"
+#include "lib/tls/buffers_tls.h"
/*
* Define this so we get channel internal functions, since we're implementing
* part of a subclass (channel_tls_t).
*/
#define TOR_CHANNEL_INTERNAL_
#define CONNECTION_PRIVATE
-#include "backtrace.h"
-#include "channel.h"
-#include "channeltls.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "config.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "connection_or.h"
-#include "control.h"
-#include "crypto_util.h"
-#include "directory.h"
-#include "dirserv.h"
-#include "dns.h"
-#include "dnsserv.h"
-#include "dos.h"
-#include "entrynodes.h"
-#include "ext_orport.h"
-#include "geoip.h"
-#include "main.h"
-#include "hibernate.h"
-#include "hs_common.h"
-#include "hs_ident.h"
-#include "nodelist.h"
-#include "proto_http.h"
-#include "proto_socks.h"
-#include "policies.h"
-#include "reasons.h"
-#include "relay.h"
-#include "rendclient.h"
-#include "rendcommon.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerlist.h"
-#include "transports.h"
-#include "routerparse.h"
-#include "sandbox.h"
+#include "lib/err/backtrace.h"
+#include "core/or/channel.h"
+#include "core/or/channeltls.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "core/or/connection_or.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/dircache/directory.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/relay/dns.h"
+#include "feature/client/dnsserv.h"
+#include "core/or/dos.h"
+#include "feature/client/entrynodes.h"
+#include "feature/relay/ext_orport.h"
+#include "feature/stats/geoip.h"
+#include "core/mainloop/main.h"
+#include "feature/hibernate/hibernate.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_ident.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/proto/proto_http.h"
+#include "core/proto/proto_socks.h"
+#include "core/or/policies.h"
+#include "core/or/reasons.h"
+#include "core/or/relay.h"
+#include "feature/rend/rendclient.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/client/transports.h"
+#include "feature/nodelist/routerparse.h"
+#include "lib/sandbox/sandbox.h"
+#include "lib/net/buffers_net.h"
+#include "lib/tls/tortls.h"
+#include "lib/evloop/compat_libevent.h"
+#include "lib/compress/compress.h"
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
#ifdef HAVE_SYS_UN_H
#include <sys/socket.h>
#include <sys/un.h>
#endif
+#include "feature/dircommon/dir_connection_st.h"
+#include "feature/control/control_connection_st.h"
+#include "core/or/entry_connection_st.h"
+#include "core/or/listener_connection_st.h"
+#include "core/or/or_connection_st.h"
+#include "core/or/port_cfg_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "core/or/socks_request_st.h"
+
static connection_t *connection_listener_new(
const struct sockaddr *listensockaddr,
socklen_t listensocklen, int type,
@@ -167,6 +187,27 @@ static smartlist_t *outgoing_addrs = NULL;
/**************************************************************/
+/** Convert a connection_t* to an listener_connection_t*; assert if the cast
+ * is invalid. */
+listener_connection_t *
+TO_LISTENER_CONN(connection_t *c)
+{
+ tor_assert(c->magic == LISTENER_CONNECTION_MAGIC);
+ return DOWNCAST(listener_connection_t, c);
+}
+
+size_t
+connection_get_inbuf_len(connection_t *conn)
+{
+ return conn->inbuf ? buf_datalen(conn->inbuf) : 0;
+}
+
+size_t
+connection_get_outbuf_len(connection_t *conn)
+{
+ return conn->outbuf ? buf_datalen(conn->outbuf) : 0;
+}
+
/**
* Return the human-readable name for the connection type <b>type</b>
*/
@@ -583,9 +624,9 @@ connection_free_minimal(connection_t *conn)
/* Owww, this shouldn't happen, but... */
log_info(LD_CHANNEL,
"Freeing orconn at %p, saw channel %p with ID "
- U64_FORMAT " left un-NULLed",
+ "%"PRIu64 " left un-NULLed",
or_conn, TLS_CHAN_TO_BASE(or_conn->chan),
- U64_PRINTF_ARG(
+ (
TLS_CHAN_TO_BASE(or_conn->chan)->global_identifier));
if (!CHANNEL_FINISHED(TLS_CHAN_TO_BASE(or_conn->chan))) {
channel_close_for_error(TLS_CHAN_TO_BASE(or_conn->chan));
@@ -4111,6 +4152,13 @@ connection_write_to_buf_impl_,(const char *string, size_t len,
connection_write_to_buf_commit(conn, written);
}
+void
+connection_buf_add_compress(const char *string, size_t len,
+ dir_connection_t *conn, int done)
+{
+ connection_write_to_buf_impl_(string, len, TO_CONN(conn), done ? -1 : 1);
+}
+
/**
* Add all bytes from <b>buf</b> to <b>conn</b>'s outbuf, draining them
* from <b>buf</b>. (If the connection is marked and will soon be closed,
@@ -4815,6 +4863,20 @@ kill_conn_list_for_oos, (smartlist_t *conns))
smartlist_len(conns));
}
+/** Check if a connection is on the way out so the OOS handler doesn't try
+ * to kill more than it needs. */
+int
+connection_is_moribund(connection_t *conn)
+{
+ if (conn != NULL &&
+ (conn->conn_array_index < 0 ||
+ conn->marked_for_close)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
/** Out-of-Sockets handler; n_socks is the current number of open
* sockets, and failed is non-zero if a socket exhaustion related
* error immediately preceded this call. This is where to do
@@ -4937,16 +4999,16 @@ connection_dump_buffer_mem_stats(int severity)
}
tor_log(severity, LD_GENERAL,
- "In buffers for %d connections: "U64_FORMAT" used/"U64_FORMAT" allocated",
+ "In buffers for %d connections: %"PRIu64" used/%"PRIu64" allocated",
smartlist_len(conns),
- U64_PRINTF_ARG(total_used), U64_PRINTF_ARG(total_alloc));
+ (total_used), (total_alloc));
for (i=CONN_TYPE_MIN_; i <= CONN_TYPE_MAX_; ++i) {
if (!n_conns_by_type[i])
continue;
tor_log(severity, LD_GENERAL,
- " For %d %s connections: "U64_FORMAT" used/"U64_FORMAT" allocated",
+ " For %d %s connections: %"PRIu64" used/%"PRIu64" allocated",
n_conns_by_type[i], conn_type_to_string(i),
- U64_PRINTF_ARG(used_by_type[i]), U64_PRINTF_ARG(alloc_by_type[i]));
+ (used_by_type[i]), (alloc_by_type[i]));
}
}
@@ -5267,4 +5329,3 @@ clock_skew_warning, (const connection_t *conn, long apparent_skew, int trusted,
tor_free(warn);
tor_free(ext_source);
}
-
diff --git a/src/or/connection.h b/src/core/mainloop/connection.h
index ad3129c9d8..3419ee65e8 100644
--- a/src/or/connection.h
+++ b/src/core/mainloop/connection.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,8 +12,74 @@
#ifndef TOR_CONNECTION_H
#define TOR_CONNECTION_H
-/* XXXX For buf_datalen in inline function */
-#include "buffers.h"
+listener_connection_t *TO_LISTENER_CONN(connection_t *);
+
+struct buf_t;
+
+#define CONN_TYPE_MIN_ 3
+/** Type for sockets listening for OR connections. */
+#define CONN_TYPE_OR_LISTENER 3
+/** A bidirectional TLS connection transmitting a sequence of cells.
+ * May be from an OR to an OR, or from an OP to an OR. */
+#define CONN_TYPE_OR 4
+/** A TCP connection from an onion router to a stream's destination. */
+#define CONN_TYPE_EXIT 5
+/** Type for sockets listening for SOCKS connections. */
+#define CONN_TYPE_AP_LISTENER 6
+/** A SOCKS proxy connection from the user application to the onion
+ * proxy. */
+#define CONN_TYPE_AP 7
+/** Type for sockets listening for HTTP connections to the directory server. */
+#define CONN_TYPE_DIR_LISTENER 8
+/** Type for HTTP connections to the directory server. */
+#define CONN_TYPE_DIR 9
+/* Type 10 is unused. */
+/** Type for listening for connections from user interface process. */
+#define CONN_TYPE_CONTROL_LISTENER 11
+/** Type for connections from user interface process. */
+#define CONN_TYPE_CONTROL 12
+/** Type for sockets listening for transparent connections redirected by pf or
+ * netfilter. */
+#define CONN_TYPE_AP_TRANS_LISTENER 13
+/** Type for sockets listening for transparent connections redirected by
+ * natd. */
+#define CONN_TYPE_AP_NATD_LISTENER 14
+/** Type for sockets listening for DNS requests. */
+#define CONN_TYPE_AP_DNS_LISTENER 15
+
+/** Type for connections from the Extended ORPort. */
+#define CONN_TYPE_EXT_OR 16
+/** Type for sockets listening for Extended ORPort connections. */
+#define CONN_TYPE_EXT_OR_LISTENER 17
+/** Type for sockets listening for HTTP CONNECT tunnel connections. */
+#define CONN_TYPE_AP_HTTP_CONNECT_LISTENER 18
+
+#define CONN_TYPE_MAX_ 19
+/* !!!! If _CONN_TYPE_MAX is ever over 31, we must grow the type field in
+ * connection_t. */
+
+/* Proxy client handshake states */
+/* We use a proxy but we haven't even connected to it yet. */
+#define PROXY_INFANT 1
+/* We use an HTTP proxy and we've sent the CONNECT command. */
+#define PROXY_HTTPS_WANT_CONNECT_OK 2
+/* We use a SOCKS4 proxy and we've sent the CONNECT command. */
+#define PROXY_SOCKS4_WANT_CONNECT_OK 3
+/* We use a SOCKS5 proxy and we try to negotiate without
+ any authentication . */
+#define PROXY_SOCKS5_WANT_AUTH_METHOD_NONE 4
+/* We use a SOCKS5 proxy and we try to negotiate with
+ Username/Password authentication . */
+#define PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929 5
+/* We use a SOCKS5 proxy and we just sent our credentials. */
+#define PROXY_SOCKS5_WANT_AUTH_RFC1929_OK 6
+/* We use a SOCKS5 proxy and we just sent our CONNECT command. */
+#define PROXY_SOCKS5_WANT_CONNECT_OK 7
+/* We use a proxy and we CONNECTed successfully!. */
+#define PROXY_CONNECTED 8
+
+/** State for any listener connection. */
+#define LISTENER_STATE_READY 0
const char *conn_type_to_string(int type);
const char *conn_state_to_string(int type, int state);
@@ -150,39 +216,17 @@ MOCK_DECL(void, connection_write_to_buf_impl_,
/* DOCDOC connection_write_to_buf */
static void connection_buf_add(const char *string, size_t len,
connection_t *conn);
-/* DOCDOC connection_write_to_buf_compress */
-static void connection_buf_add_compress(const char *string, size_t len,
- dir_connection_t *conn, int done);
static inline void
connection_buf_add(const char *string, size_t len, connection_t *conn)
{
connection_write_to_buf_impl_(string, len, conn, 0);
}
-static inline void
-connection_buf_add_compress(const char *string, size_t len,
- dir_connection_t *conn, int done)
-{
- connection_write_to_buf_impl_(string, len, TO_CONN(conn), done ? -1 : 1);
-}
-void connection_buf_add_buf(connection_t *conn, buf_t *buf);
-
-/* DOCDOC connection_get_inbuf_len */
-static size_t connection_get_inbuf_len(connection_t *conn);
-/* DOCDOC connection_get_outbuf_len */
-static size_t connection_get_outbuf_len(connection_t *conn);
-
-static inline size_t
-connection_get_inbuf_len(connection_t *conn)
-{
- return conn->inbuf ? buf_datalen(conn->inbuf) : 0;
-}
-
-static inline size_t
-connection_get_outbuf_len(connection_t *conn)
-{
- return conn->outbuf ? buf_datalen(conn->outbuf) : 0;
-}
+void connection_buf_add_compress(const char *string, size_t len,
+ dir_connection_t *conn, int done);
+void connection_buf_add_buf(connection_t *conn, struct buf_t *buf);
+size_t connection_get_inbuf_len(connection_t *conn);
+size_t connection_get_outbuf_len(connection_t *conn);
connection_t *connection_get_by_global_id(uint64_t id);
connection_t *connection_get_by_type(int type);
@@ -259,22 +303,27 @@ MOCK_DECL(void, clock_skew_warning,
log_domain_mask_t domain, const char *received,
const char *source));
-/** Check if a connection is on the way out so the OOS handler doesn't try
- * to kill more than it needs. */
-static inline int
-connection_is_moribund(connection_t *conn)
-{
- if (conn != NULL &&
- (conn->conn_array_index < 0 ||
- conn->marked_for_close)) {
- return 1;
- } else {
- return 0;
- }
-}
-
+int connection_is_moribund(connection_t *conn);
void connection_check_oos(int n_socks, int failed);
+/** Execute the statement <b>stmt</b>, which may log events concerning the
+ * connection <b>conn</b>. To prevent infinite loops, disable log messages
+ * being sent to controllers if <b>conn</b> is a control connection.
+ *
+ * Stmt must not contain any return or goto statements.
+ */
+#define CONN_LOG_PROTECT(conn, stmt) \
+ STMT_BEGIN \
+ int _log_conn_is_control; \
+ tor_assert(conn); \
+ _log_conn_is_control = (conn->type == CONN_TYPE_CONTROL); \
+ if (_log_conn_is_control) \
+ disable_control_logging(); \
+ STMT_BEGIN stmt; STMT_END; \
+ if (_log_conn_is_control) \
+ enable_control_logging(); \
+ STMT_END
+
#ifdef CONNECTION_PRIVATE
STATIC void connection_free_minimal(connection_t *conn);
@@ -292,4 +341,3 @@ MOCK_DECL(STATIC smartlist_t *, pick_oos_victims, (int n));
#endif /* defined(CONNECTION_PRIVATE) */
#endif /* !defined(TOR_CONNECTION_H) */
-
diff --git a/src/or/cpuworker.c b/src/core/mainloop/cpuworker.c
index 15ef6869cf..a372db3f17 100644
--- a/src/or/cpuworker.c
+++ b/src/core/mainloop/cpuworker.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,20 +17,23 @@
* <li>and for calculating diffs and compressing them in consdiffmgr.c.
* </ul>
**/
-#include "or.h"
-#include "channel.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "connection_or.h"
-#include "config.h"
-#include "cpuworker.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "main.h"
-#include "onion.h"
-#include "rephist.h"
-#include "router.h"
-#include "workqueue.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/connection_or.h"
+#include "app/config/config.h"
+#include "core/mainloop/cpuworker.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "core/mainloop/main.h"
+#include "core/crypto/onion.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "lib/evloop/workqueue.h"
+
+#include "core/or/or_circuit_st.h"
+#include "lib/intmath/weakrng.h"
static void queue_pending_tasks(void);
@@ -280,7 +283,7 @@ get_overhead_for_onionskins(uint32_t *usec_out, double *frac_out,
onionskins_usec_internal[onionskin_type];
*usec_out = (uint32_t)(overhead / onionskins_n_processed[onionskin_type]);
- *frac_out = U64_TO_DBL(overhead) / onionskins_usec_internal[onionskin_type];
+ *frac_out = ((double)overhead) / onionskins_usec_internal[onionskin_type];
return 0;
}
@@ -594,4 +597,3 @@ cpuworker_cancel_circ_handshake(or_circuit_t *circ)
circ->workqueue_entry = NULL;
}
}
-
diff --git a/src/or/cpuworker.h b/src/core/mainloop/cpuworker.h
index d39851325f..50812b2dab 100644
--- a/src/or/cpuworker.h
+++ b/src/core/mainloop/cpuworker.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/or/main.c b/src/core/mainloop/main.c
index 9dce158b33..c5773ddfc1 100644
--- a/src/or/main.c
+++ b/src/core/mainloop/main.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -47,80 +47,98 @@
**/
#define MAIN_PRIVATE
-#include "or.h"
-#include "addressmap.h"
-#include "backtrace.h"
-#include "bridges.h"
-#include "buffers.h"
-#include "buffers_tls.h"
-#include "channel.h"
-#include "channeltls.h"
-#include "channelpadding.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "circuitmux_ewma.h"
-#include "command.h"
-#include "compress.h"
-#include "config.h"
-#include "confparse.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "connection_or.h"
-#include "consdiffmgr.h"
-#include "control.h"
-#include "cpuworker.h"
-#include "crypto_s2k.h"
-#include "crypto_rand.h"
-#include "directory.h"
-#include "dirserv.h"
-#include "dns.h"
-#include "dnsserv.h"
-#include "dos.h"
-#include "entrynodes.h"
-#include "geoip.h"
-#include "hibernate.h"
-#include "hs_cache.h"
-#include "hs_circuitmap.h"
-#include "hs_client.h"
-#include "keypin.h"
-#include "main.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "ntmain.h"
-#include "onion.h"
-#include "periodic.h"
-#include "policies.h"
-#include "protover.h"
-#include "transports.h"
-#include "relay.h"
-#include "rendclient.h"
-#include "rendcommon.h"
-#include "rendservice.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerkeys.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "scheduler.h"
-#include "statefile.h"
-#include "status.h"
-#include "tor_api.h"
-#include "tor_api_internal.h"
-#include "util_process.h"
-#include "ext_orport.h"
-#ifdef USE_DMALLOC
-#include <dmalloc.h>
-#endif
-#include "memarea.h"
-#include "sandbox.h"
+#include "core/or/or.h"
+#include "feature/client/addressmap.h"
+#include "lib/err/backtrace.h"
+#include "feature/client/bridges.h"
+#include "lib/container/buffers.h"
+#include "lib/tls/buffers_tls.h"
+#include "core/or/channel.h"
+#include "core/or/channeltls.h"
+#include "core/or/channelpadding.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "core/or/circuitmux_ewma.h"
+#include "core/or/command.h"
+#include "lib/compress/compress.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "core/or/connection_or.h"
+#include "feature/dircache/consdiffmgr.h"
+#include "feature/control/control.h"
+#include "core/mainloop/cpuworker.h"
+#include "lib/crypt_ops/crypto_s2k.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/dircache/directory.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/relay/dns.h"
+#include "feature/client/dnsserv.h"
+#include "core/or/dos.h"
+#include "feature/client/entrynodes.h"
+#include "feature/stats/geoip.h"
+#include "feature/hibernate/hibernate.h"
+#include "feature/hs/hs_cache.h"
+#include "feature/hs/hs_circuitmap.h"
+#include "feature/hs/hs_client.h"
+#include "feature/dirauth/keypin.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "app/main/ntmain.h"
+#include "core/crypto/onion.h"
+#include "core/mainloop/periodic.h"
+#include "core/or/policies.h"
+#include "core/or/protover.h"
+#include "feature/client/transports.h"
+#include "core/or/relay.h"
+#include "feature/rend/rendclient.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/rend/rendservice.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routerkeys.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "core/or/scheduler.h"
+#include "app/config/statefile.h"
+#include "core/or/status.h"
+#include "feature/api/tor_api.h"
+#include "feature/api/tor_api_internal.h"
+#include "lib/process/waitpid.h"
+#include "feature/relay/ext_orport.h"
+#include "lib/memarea/memarea.h"
+#include "lib/meminfo/meminfo.h"
+#include "lib/osinfo/uname.h"
+#include "lib/sandbox/sandbox.h"
+#include "lib/fs/lockfile.h"
+#include "lib/net/buffers_net.h"
+#include "lib/tls/tortls.h"
+#include "lib/evloop/compat_libevent.h"
+#include "lib/encoding/confline.h"
+#include "lib/evloop/timers.h"
#include <event2/event.h>
-#include "dirauth/dirvote.h"
-#include "dirauth/mode.h"
-#include "dirauth/shared_random.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/dirauth/mode.h"
+#include "feature/dirauth/shared_random.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/entry_connection_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "core/or/or_connection_st.h"
+#include "app/config/or_state_st.h"
+#include "core/or/port_cfg_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "core/or/socks_request_st.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#ifdef HAVE_SYSTEMD
# if defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__)
@@ -1262,9 +1280,9 @@ run_connection_housekeeping(int i, time_t now)
} else if (!have_any_circuits &&
now - or_conn->idle_timeout >=
chan->timestamp_last_had_circuits) {
- log_info(LD_OR,"Expiring non-used OR connection "U64_FORMAT" to fd %d "
+ log_info(LD_OR,"Expiring non-used OR connection %"PRIu64" to fd %d "
"(%s:%d) [no circuits for %d; timeout %d; %scanonical].",
- U64_PRINTF_ARG(chan->global_identifier),
+ (chan->global_identifier),
(int)conn->s, conn->address, conn->port,
(int)(now - chan->timestamp_last_had_circuits),
or_conn->idle_timeout,
@@ -2687,11 +2705,6 @@ do_hup(void)
{
const or_options_t *options = get_options();
-#ifdef USE_DMALLOC
- dmalloc_log_stats();
- dmalloc_log_changed(0, 1, 0, 0);
-#endif
-
log_notice(LD_GENERAL,"Received reload signal (hup). Reloading config and "
"resetting internal state.");
if (accounting_is_enabled(options))
@@ -3195,8 +3208,8 @@ static void
dumpmemusage(int severity)
{
connection_dump_buffer_mem_stats(severity);
- tor_log(severity, LD_GENERAL, "In rephist: "U64_FORMAT" used by %d Tors.",
- U64_PRINTF_ARG(rephist_total_alloc), rephist_total_num);
+ tor_log(severity, LD_GENERAL, "In rephist: %"PRIu64" used by %d Tors.",
+ (rephist_total_alloc), rephist_total_num);
dump_routerlist_mem_usage(severity);
dump_cell_pool_usage(severity);
dump_dns_mem_usage(severity);
@@ -3259,28 +3272,28 @@ dumpstats(int severity)
channel_listener_dumpstats(severity);
tor_log(severity, LD_NET,
- "Cells processed: "U64_FORMAT" padding\n"
- " "U64_FORMAT" create\n"
- " "U64_FORMAT" created\n"
- " "U64_FORMAT" relay\n"
- " ("U64_FORMAT" relayed)\n"
- " ("U64_FORMAT" delivered)\n"
- " "U64_FORMAT" destroy",
- U64_PRINTF_ARG(stats_n_padding_cells_processed),
- U64_PRINTF_ARG(stats_n_create_cells_processed),
- U64_PRINTF_ARG(stats_n_created_cells_processed),
- U64_PRINTF_ARG(stats_n_relay_cells_processed),
- U64_PRINTF_ARG(stats_n_relay_cells_relayed),
- U64_PRINTF_ARG(stats_n_relay_cells_delivered),
- U64_PRINTF_ARG(stats_n_destroy_cells_processed));
+ "Cells processed: %"PRIu64" padding\n"
+ " %"PRIu64" create\n"
+ " %"PRIu64" created\n"
+ " %"PRIu64" relay\n"
+ " (%"PRIu64" relayed)\n"
+ " (%"PRIu64" delivered)\n"
+ " %"PRIu64" destroy",
+ (stats_n_padding_cells_processed),
+ (stats_n_create_cells_processed),
+ (stats_n_created_cells_processed),
+ (stats_n_relay_cells_processed),
+ (stats_n_relay_cells_relayed),
+ (stats_n_relay_cells_delivered),
+ (stats_n_destroy_cells_processed));
if (stats_n_data_cells_packaged)
tor_log(severity,LD_NET,"Average packaged cell fullness: %2.3f%%",
- 100*(U64_TO_DBL(stats_n_data_bytes_packaged) /
- U64_TO_DBL(stats_n_data_cells_packaged*RELAY_PAYLOAD_SIZE)) );
+ 100*(((double)stats_n_data_bytes_packaged) /
+ ((double)stats_n_data_cells_packaged*RELAY_PAYLOAD_SIZE)) );
if (stats_n_data_cells_received)
tor_log(severity,LD_NET,"Average delivered cell fullness: %2.3f%%",
- 100*(U64_TO_DBL(stats_n_data_bytes_received) /
- U64_TO_DBL(stats_n_data_cells_received*RELAY_PAYLOAD_SIZE)) );
+ 100*(((double)stats_n_data_bytes_received) /
+ ((double)stats_n_data_cells_received*RELAY_PAYLOAD_SIZE)) );
cpuworker_log_onionskin_overhead(severity, ONION_HANDSHAKE_TYPE_TAP, "TAP");
cpuworker_log_onionskin_overhead(severity, ONION_HANDSHAKE_TYPE_NTOR,"ntor");
@@ -3292,13 +3305,13 @@ dumpstats(int severity)
if (elapsed) {
tor_log(severity, LD_NET,
- "Average bandwidth: "U64_FORMAT"/%d = %d bytes/sec reading",
- U64_PRINTF_ARG(stats_n_bytes_read),
+ "Average bandwidth: %"PRIu64"/%d = %d bytes/sec reading",
+ (stats_n_bytes_read),
(int)elapsed,
(int) (stats_n_bytes_read/elapsed));
tor_log(severity, LD_NET,
- "Average bandwidth: "U64_FORMAT"/%d = %d bytes/sec writing",
- U64_PRINTF_ARG(stats_n_bytes_written),
+ "Average bandwidth: %"PRIu64"/%d = %d bytes/sec writing",
+ (stats_n_bytes_written),
(int)elapsed,
(int) (stats_n_bytes_written/elapsed));
}
@@ -3631,7 +3644,7 @@ release_lockfile(void)
* only the parts of memory that we won't touch. If !<b>postfork</b>,
* Tor is shutting down and we should free everything.
*
- * Helps us find the real leaks with dmalloc and the like. Also valgrind
+ * Helps us find the real leaks with sanitizers and the like. Also valgrind
* should then report 0 reachable in its leak report (in an ideal world --
* in practice libevent, SSL, libc etc never quite free everything). */
void
@@ -3664,7 +3677,7 @@ tor_free_all(int postfork)
routerparse_free_all();
ext_orport_free_all();
control_free_all();
- sandbox_free_getaddrinfo_cache();
+ tor_free_getaddrinfo_cache();
protover_free_all();
bridges_free_all();
consdiffmgr_free_all();
@@ -3787,18 +3800,11 @@ tor_cleanup(void)
timers_shutdown();
-#ifdef USE_DMALLOC
- dmalloc_log_stats();
-#endif
tor_free_all(0); /* We could move tor_free_all back into the ifdef below
later, if it makes shutdown unacceptably slow. But for
now, leave it here: it's helped us catch bugs in the
past. */
crypto_global_cleanup();
-#ifdef USE_DMALLOC
- dmalloc_log_unfreed();
- dmalloc_shutdown();
-#endif
}
/** Read/create keys as needed, and echo our fingerprint to stdout. */
@@ -3893,7 +3899,7 @@ init_addrinfo(void)
// host name to sandbox
gethostname(hname, sizeof(hname));
- sandbox_add_addrinfo(hname);
+ tor_add_addrinfo(hname);
}
static sandbox_cfg_t*
@@ -4221,7 +4227,13 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
}
#endif /* defined(_WIN32) */
- configure_backtrace_handler(get_version());
+ {
+ int bt_err = configure_backtrace_handler(get_version());
+ if (bt_err < 0) {
+ log_warn(LD_BUG, "Unable to install backtrace handler: %s",
+ strerror(-bt_err));
+ }
+ }
init_protocol_warning_severity_level();
update_approx_time(time(NULL));
@@ -4229,14 +4241,6 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
tor_compress_init();
init_logging(0);
monotime_init();
-#ifdef USE_DMALLOC
- {
- /* Instruct OpenSSL to use our internal wrappers for malloc,
- realloc and free. */
- int r = crypto_use_tor_alloc_functions();
- tor_assert(r == 0);
- }
-#endif /* defined(USE_DMALLOC) */
#ifdef NT_SERVICE
{
int done = 0;
@@ -4305,4 +4309,3 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
tor_cleanup();
return result;
}
-
diff --git a/src/or/main.h b/src/core/mainloop/main.h
index 9dbbc6e5ee..2b44596706 100644
--- a/src/or/main.h
+++ b/src/core/mainloop/main.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -96,10 +96,12 @@ uint64_t get_main_loop_idle_count(void);
void periodic_events_on_new_options(const or_options_t *options);
void reschedule_per_second_timer(void);
+struct token_bucket_rw_t;
+
extern time_t time_of_process_start;
extern int quiet_level;
-extern token_bucket_rw_t global_bucket;
-extern token_bucket_rw_t global_relayed_bucket;
+extern struct token_bucket_rw_t global_bucket;
+extern struct token_bucket_rw_t global_relayed_bucket;
#ifdef MAIN_PRIVATE
STATIC void init_connection_lists(void);
@@ -112,10 +114,9 @@ STATIC int get_my_roles(const or_options_t *options);
extern smartlist_t *connection_array;
/* We need the periodic_event_item_t definition. */
-#include "periodic.h"
+#include "core/mainloop/periodic.h"
extern periodic_event_item_t periodic_events[];
#endif
#endif /* defined(MAIN_PRIVATE) */
#endif /* !defined(TOR_MAIN_H) */
-
diff --git a/src/or/periodic.c b/src/core/mainloop/periodic.c
index 92fa677f8f..c17c0c56d2 100644
--- a/src/or/periodic.c
+++ b/src/core/mainloop/periodic.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Tor Project, Inc. */
+/* Copyright (c) 2015-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -11,11 +11,12 @@
* that they fire. See periodic_events[] in main.c for examples.
*/
-#include "or.h"
-#include "compat_libevent.h"
-#include "config.h"
-#include "main.h"
-#include "periodic.h"
+#include "core/or/or.h"
+#include "lib/evloop/compat_libevent.h"
+#include "app/config/config.h"
+#include "core/mainloop/main.h"
+#include "core/mainloop/periodic.h"
+#include "lib/evloop/compat_libevent.h"
/** We disable any interval greater than this number of seconds, on the
* grounds that it is probably an absolute time mistakenly passed in as a
@@ -169,4 +170,3 @@ periodic_event_disable(periodic_event_item_t *event)
mainloop_event_cancel(event->ev);
event->enabled = 0;
}
-
diff --git a/src/or/periodic.h b/src/core/mainloop/periodic.h
index e8208b2475..4c8c3c96cc 100644
--- a/src/or/periodic.h
+++ b/src/core/mainloop/periodic.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Tor Project, Inc. */
+/* Copyright (c) 2015-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_PERIODIC_H
diff --git a/src/core/or/addr_policy_st.h b/src/core/or/addr_policy_st.h
new file mode 100644
index 0000000000..be3e9d8f01
--- /dev/null
+++ b/src/core/or/addr_policy_st.h
@@ -0,0 +1,46 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_ADDR_POLICY_ST_H
+#define TOR_ADDR_POLICY_ST_H
+
+#include "lib/cc/torint.h"
+#include "lib/net/address.h"
+
+/** What action type does an address policy indicate: accept or reject? */
+typedef enum {
+ ADDR_POLICY_ACCEPT=1,
+ ADDR_POLICY_REJECT=2,
+} addr_policy_action_t;
+#define addr_policy_action_bitfield_t ENUM_BF(addr_policy_action_t)
+
+/** A reference-counted address policy rule. */
+typedef struct addr_policy_t {
+ int refcnt; /**< Reference count */
+ /** What to do when the policy matches.*/
+ addr_policy_action_bitfield_t policy_type:2;
+ unsigned int is_private:1; /**< True iff this is the pseudo-address,
+ * "private". */
+ unsigned int is_canonical:1; /**< True iff this policy is the canonical
+ * copy (stored in a hash table to avoid
+ * duplication of common policies) */
+ maskbits_t maskbits; /**< Accept/reject all addresses <b>a</b> such that the
+ * first <b>maskbits</b> bits of <b>a</b> match
+ * <b>addr</b>. */
+ /** Base address to accept or reject.
+ *
+ * Note that wildcards are treated
+ * differntly depending on address family. An AF_UNSPEC address means
+ * "All addresses, IPv4 or IPv6." An AF_INET address with maskbits==0 means
+ * "All IPv4 addresses" and an AF_INET6 address with maskbits == 0 means
+ * "All IPv6 addresses".
+ **/
+ tor_addr_t addr;
+ uint16_t prt_min; /**< Lowest port number to accept/reject. */
+ uint16_t prt_max; /**< Highest port number to accept/reject. */
+} addr_policy_t;
+
+#endif
diff --git a/src/core/or/address_set.c b/src/core/or/address_set.c
new file mode 100644
index 0000000000..014e650d2d
--- /dev/null
+++ b/src/core/or/address_set.c
@@ -0,0 +1,71 @@
+/* Copyright (c) 2018-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file address_set.c
+ * \brief Implementation for a set of addresses.
+ *
+ * This module was first written on a semi-emergency basis to improve the
+ * robustness of the anti-DoS module. As such, it's written in a pretty
+ * conservative way, and should be susceptible to improvement later on.
+ **/
+
+#include "orconfig.h"
+#include "core/or/address_set.h"
+#include "lib/net/address.h"
+#include "lib/container/bloomfilt.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "siphash.h"
+
+/* Wrap our hash function to have the signature that the bloom filter
+ * needs. */
+static uint64_t
+bloomfilt_addr_hash(const struct sipkey *key,
+ const void *item)
+{
+ return tor_addr_keyed_hash(key, item);
+}
+
+/**
+ * Allocate and return an address_set, suitable for holding up to
+ * <b>max_address_guess</b> distinct values.
+ */
+address_set_t *
+address_set_new(int max_addresses_guess)
+{
+ uint8_t k[BLOOMFILT_KEY_LEN];
+ crypto_rand((void*)k, sizeof(k));
+ return bloomfilt_new(max_addresses_guess, bloomfilt_addr_hash, k);
+}
+
+/**
+ * Add <b>addr</b> to <b>set</b>.
+ *
+ * All future queries for <b>addr</b> in set will return true. Removing
+ * items is not possible.
+ */
+void
+address_set_add(address_set_t *set, const struct tor_addr_t *addr)
+{
+ bloomfilt_add(set, addr);
+}
+
+/** As address_set_add(), but take an ipv4 address in host order. */
+void
+address_set_add_ipv4h(address_set_t *set, uint32_t addr)
+{
+ tor_addr_t a;
+ tor_addr_from_ipv4h(&a, addr);
+ address_set_add(set, &a);
+}
+
+/**
+ * Return true if <b>addr</b> is a member of <b>set</b>. (And probably,
+ * return false if <b>addr</b> is not a member of set.)
+ */
+int
+address_set_probably_contains(const address_set_t *set,
+ const struct tor_addr_t *addr)
+{
+ return bloomfilt_probably_contains(set, addr);
+}
diff --git a/src/common/address_set.h b/src/core/or/address_set.h
index 28d29f3fdf..2efa1cb03b 100644
--- a/src/common/address_set.h
+++ b/src/core/or/address_set.h
@@ -1,35 +1,31 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file address_set.h
* \brief Types to handle sets of addresses.
- *
- * This module was first written on a semi-emergency basis to improve the
- * robustness of the anti-DoS module. As such, it's written in a pretty
- * conservative way, and should be susceptible to improvement later on.
**/
#ifndef TOR_ADDRESS_SET_H
#define TOR_ADDRESS_SET_H
#include "orconfig.h"
-#include "torint.h"
+#include "lib/cc/torint.h"
+#include "lib/container/bloomfilt.h"
/**
* An address_set_t represents a set of tor_addr_t values. The implementation
* is probabilistic: false negatives cannot occur but false positives are
* possible.
*/
-typedef struct address_set_t address_set_t;
+typedef struct bloomfilt_t address_set_t;
struct tor_addr_t;
address_set_t *address_set_new(int max_addresses_guess);
-void address_set_free(address_set_t *set);
+#define address_set_free(set) bloomfilt_free(set)
void address_set_add(address_set_t *set, const struct tor_addr_t *addr);
void address_set_add_ipv4h(address_set_t *set, uint32_t addr);
-int address_set_probably_contains(address_set_t *set,
+int address_set_probably_contains(const address_set_t *set,
const struct tor_addr_t *addr);
#endif
-
diff --git a/src/core/or/cell_queue_st.h b/src/core/or/cell_queue_st.h
new file mode 100644
index 0000000000..40110019bc
--- /dev/null
+++ b/src/core/or/cell_queue_st.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef PACKED_CELL_ST_H
+#define PACKED_CELL_ST_H
+
+#include "tor_queue.h"
+
+/** A cell as packed for writing to the network. */
+struct packed_cell_t {
+ /** Next cell queued on this circuit. */
+ TOR_SIMPLEQ_ENTRY(packed_cell_t) next;
+ char body[CELL_MAX_NETWORK_SIZE]; /**< Cell as packed for network. */
+ uint32_t inserted_timestamp; /**< Time (in timestamp units) when this cell
+ * was inserted */
+};
+
+/** A queue of cells on a circuit, waiting to be added to the
+ * or_connection_t's outbuf. */
+struct cell_queue_t {
+ /** Linked list of packed_cell_t*/
+ TOR_SIMPLEQ_HEAD(cell_simpleq, packed_cell_t) head;
+ int n; /**< The number of cells in the queue. */
+};
+
+#endif
diff --git a/src/core/or/cell_st.h b/src/core/or/cell_st.h
new file mode 100644
index 0000000000..6728e783b9
--- /dev/null
+++ b/src/core/or/cell_st.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef CELL_ST_H
+#define CELL_ST_H
+
+/** Parsed onion routing cell. All communication between nodes
+ * is via cells. */
+struct cell_t {
+ circid_t circ_id; /**< Circuit which received the cell. */
+ uint8_t command; /**< Type of the cell: one of CELL_PADDING, CELL_CREATE,
+ * CELL_DESTROY, etc */
+ uint8_t payload[CELL_PAYLOAD_SIZE]; /**< Cell body. */
+};
+
+#endif
+
diff --git a/src/or/channel.c b/src/core/or/channel.c
index c30e508018..476f31d5b4 100644
--- a/src/or/channel.c
+++ b/src/core/or/channel.c
@@ -1,5 +1,5 @@
-/* * Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -57,28 +57,31 @@
/* This one's for stuff only channel.c and the test suite should see */
#define CHANNEL_PRIVATE_
-#include "or.h"
-#include "channel.h"
-#include "channeltls.h"
-#include "channelpadding.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuitstats.h"
-#include "config.h"
-#include "connection_or.h" /* For var_cell_free() */
-#include "circuitmux.h"
-#include "entrynodes.h"
-#include "geoip.h"
-#include "main.h"
-#include "nodelist.h"
-#include "relay.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerlist.h"
-#include "scheduler.h"
-#include "compat_time.h"
-#include "networkstatus.h"
-#include "rendservice.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "core/or/channeltls.h"
+#include "core/or/channelpadding.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuitstats.h"
+#include "app/config/config.h"
+#include "core/or/connection_or.h" /* For var_cell_free() */
+#include "core/or/circuitmux.h"
+#include "feature/client/entrynodes.h"
+#include "feature/stats/geoip.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/relay.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "core/or/scheduler.h"
+#include "lib/time/compat_time.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/rend/rendservice.h"
+#include "lib/evloop/timers.h"
+
+#include "core/or/cell_queue_st.h"
/* Global lists of channels */
@@ -388,9 +391,9 @@ channel_register(channel_t *chan)
if (chan->registered) return;
log_debug(LD_CHANNEL,
- "Registering channel %p (ID " U64_FORMAT ") "
+ "Registering channel %p (ID %"PRIu64 ") "
"in state %s (%d) with digest %s",
- chan, U64_PRINTF_ARG(chan->global_identifier),
+ chan, (chan->global_identifier),
channel_state_to_string(chan->state), chan->state,
hex_str(chan->identity_digest, DIGEST_LEN));
@@ -418,9 +421,9 @@ channel_register(channel_t *chan)
channel_add_to_digest_map(chan);
} else {
log_info(LD_CHANNEL,
- "Channel %p (global ID " U64_FORMAT ") "
+ "Channel %p (global ID %"PRIu64 ") "
"in state %s (%d) registered with no identity digest",
- chan, U64_PRINTF_ARG(chan->global_identifier),
+ chan, (chan->global_identifier),
channel_state_to_string(chan->state), chan->state);
}
}
@@ -484,9 +487,9 @@ channel_listener_register(channel_listener_t *chan_l)
if (chan_l->registered) return;
log_debug(LD_CHANNEL,
- "Registering channel listener %p (ID " U64_FORMAT ") "
+ "Registering channel listener %p (ID %"PRIu64 ") "
"in state %s (%d)",
- chan_l, U64_PRINTF_ARG(chan_l->global_identifier),
+ chan_l, (chan_l->global_identifier),
channel_listener_state_to_string(chan_l->state),
chan_l->state);
@@ -576,9 +579,9 @@ channel_add_to_digest_map(channel_t *chan)
TOR_LIST_INSERT_HEAD(&ent->channel_list, chan, next_with_same_id);
log_debug(LD_CHANNEL,
- "Added channel %p (global ID " U64_FORMAT ") "
+ "Added channel %p (global ID %"PRIu64 ") "
"to identity map in state %s (%d) with digest %s",
- chan, U64_PRINTF_ARG(chan->global_identifier),
+ chan, (chan->global_identifier),
channel_state_to_string(chan->state), chan->state,
hex_str(chan->identity_digest, DIGEST_LEN));
}
@@ -615,18 +618,18 @@ channel_remove_from_digest_map(channel_t *chan)
}
log_debug(LD_CHANNEL,
- "Removed channel %p (global ID " U64_FORMAT ") from "
+ "Removed channel %p (global ID %"PRIu64 ") from "
"identity map in state %s (%d) with digest %s",
- chan, U64_PRINTF_ARG(chan->global_identifier),
+ chan, (chan->global_identifier),
channel_state_to_string(chan->state), chan->state,
hex_str(chan->identity_digest, DIGEST_LEN));
} else {
/* Shouldn't happen */
log_warn(LD_BUG,
- "Trying to remove channel %p (global ID " U64_FORMAT ") with "
+ "Trying to remove channel %p (global ID %"PRIu64 ") with "
"digest %s from identity map, but couldn't find any with "
"that digest",
- chan, U64_PRINTF_ARG(chan->global_identifier),
+ chan, (chan->global_identifier),
hex_str(chan->identity_digest, DIGEST_LEN));
}
}
@@ -880,8 +883,8 @@ channel_free_(channel_t *chan)
tor_assert(!(chan->registered));
log_debug(LD_CHANNEL,
- "Freeing channel " U64_FORMAT " at %p",
- U64_PRINTF_ARG(chan->global_identifier), chan);
+ "Freeing channel %"PRIu64 " at %p",
+ (chan->global_identifier), chan);
/* Get this one out of the scheduler */
scheduler_release_channel(chan);
@@ -926,8 +929,8 @@ channel_listener_free_(channel_listener_t *chan_l)
if (!chan_l) return;
log_debug(LD_CHANNEL,
- "Freeing channel_listener_t " U64_FORMAT " at %p",
- U64_PRINTF_ARG(chan_l->global_identifier),
+ "Freeing channel_listener_t %"PRIu64 " at %p",
+ (chan_l->global_identifier),
chan_l);
/* It must be closed or errored */
@@ -953,8 +956,8 @@ channel_force_xfree(channel_t *chan)
tor_assert(chan);
log_debug(LD_CHANNEL,
- "Force-freeing channel " U64_FORMAT " at %p",
- U64_PRINTF_ARG(chan->global_identifier), chan);
+ "Force-freeing channel %"PRIu64 " at %p",
+ (chan->global_identifier), chan);
/* Get this one out of the scheduler */
scheduler_release_channel(chan);
@@ -997,8 +1000,8 @@ channel_listener_force_xfree(channel_listener_t *chan_l)
tor_assert(chan_l);
log_debug(LD_CHANNEL,
- "Force-freeing channel_listener_t " U64_FORMAT " at %p",
- U64_PRINTF_ARG(chan_l->global_identifier),
+ "Force-freeing channel_listener_t %"PRIu64 " at %p",
+ (chan_l->global_identifier),
chan_l);
/* Call a free method if there is one */
@@ -1037,8 +1040,8 @@ channel_listener_set_listener_fn(channel_listener_t *chan_l,
log_debug(LD_CHANNEL,
"Setting listener callback for channel listener %p "
- "(global ID " U64_FORMAT ") to %p",
- chan_l, U64_PRINTF_ARG(chan_l->global_identifier),
+ "(global ID %"PRIu64 ") to %p",
+ chan_l, (chan_l->global_identifier),
listener);
chan_l->listener = listener;
@@ -1137,9 +1140,9 @@ channel_mark_for_close(channel_t *chan)
return;
log_debug(LD_CHANNEL,
- "Closing channel %p (global ID " U64_FORMAT ") "
+ "Closing channel %p (global ID %"PRIu64 ") "
"by request",
- chan, U64_PRINTF_ARG(chan->global_identifier));
+ chan, (chan->global_identifier));
/* Note closing by request from above */
chan->reason_for_closing = CHANNEL_CLOSE_REQUESTED;
@@ -1177,9 +1180,9 @@ channel_listener_mark_for_close(channel_listener_t *chan_l)
chan_l->state == CHANNEL_LISTENER_STATE_ERROR) return;
log_debug(LD_CHANNEL,
- "Closing channel listener %p (global ID " U64_FORMAT ") "
+ "Closing channel listener %p (global ID %"PRIu64 ") "
"by request",
- chan_l, U64_PRINTF_ARG(chan_l->global_identifier));
+ chan_l, (chan_l->global_identifier));
/* Note closing by request from above */
chan_l->reason_for_closing = CHANNEL_LISTENER_CLOSE_REQUESTED;
@@ -1215,9 +1218,9 @@ channel_close_from_lower_layer(channel_t *chan)
return;
log_debug(LD_CHANNEL,
- "Closing channel %p (global ID " U64_FORMAT ") "
+ "Closing channel %p (global ID %"PRIu64 ") "
"due to lower-layer event",
- chan, U64_PRINTF_ARG(chan->global_identifier));
+ chan, (chan->global_identifier));
/* Note closing by event from below */
chan->reason_for_closing = CHANNEL_CLOSE_FROM_BELOW;
@@ -1300,8 +1303,8 @@ channel_clear_identity_digest(channel_t *chan)
log_debug(LD_CHANNEL,
"Clearing remote endpoint digest on channel %p with "
- "global ID " U64_FORMAT,
- chan, U64_PRINTF_ARG(chan->global_identifier));
+ "global ID %"PRIu64,
+ chan, (chan->global_identifier));
state_not_in_map = CHANNEL_CONDEMNED(chan);
@@ -1331,8 +1334,8 @@ channel_set_identity_digest(channel_t *chan,
log_debug(LD_CHANNEL,
"Setting remote endpoint digest on channel %p with "
- "global ID " U64_FORMAT " to digest %s",
- chan, U64_PRINTF_ARG(chan->global_identifier),
+ "global ID %"PRIu64 " to digest %s",
+ chan, (chan->global_identifier),
identity_digest ?
hex_str(identity_digest, DIGEST_LEN) : "(null)");
@@ -1388,8 +1391,8 @@ channel_clear_remote_end(channel_t *chan)
log_debug(LD_CHANNEL,
"Clearing remote endpoint identity on channel %p with "
- "global ID " U64_FORMAT,
- chan, U64_PRINTF_ARG(chan->global_identifier));
+ "global ID %"PRIu64,
+ chan, (chan->global_identifier));
state_not_in_map = CHANNEL_CONDEMNED(chan);
@@ -1472,13 +1475,13 @@ channel_write_packed_cell(channel_t *chan, packed_cell_t *cell)
if (CHANNEL_IS_CLOSING(chan)) {
log_debug(LD_CHANNEL, "Discarding %p on closing channel %p with "
- "global ID "U64_FORMAT, cell, chan,
- U64_PRINTF_ARG(chan->global_identifier));
+ "global ID %"PRIu64, cell, chan,
+ (chan->global_identifier));
goto end;
}
log_debug(LD_CHANNEL,
"Writing %p to channel %p with global ID "
- U64_FORMAT, cell, chan, U64_PRINTF_ARG(chan->global_identifier));
+ "%"PRIu64, cell, chan, (chan->global_identifier));
ret = write_packed_cell(chan, cell);
@@ -1515,9 +1518,9 @@ channel_change_state_(channel_t *chan, channel_state_t to_state)
if (from_state == to_state) {
log_debug(LD_CHANNEL,
"Got no-op transition from \"%s\" to itself on channel %p"
- "(global ID " U64_FORMAT ")",
+ "(global ID %"PRIu64 ")",
channel_state_to_string(to_state),
- chan, U64_PRINTF_ARG(chan->global_identifier));
+ chan, (chan->global_identifier));
return;
}
@@ -1529,10 +1532,10 @@ channel_change_state_(channel_t *chan, channel_state_t to_state)
}
log_debug(LD_CHANNEL,
- "Changing state of channel %p (global ID " U64_FORMAT
+ "Changing state of channel %p (global ID %"PRIu64
") from \"%s\" to \"%s\"",
chan,
- U64_PRINTF_ARG(chan->global_identifier),
+ (chan->global_identifier),
channel_state_to_string(chan->state),
channel_state_to_string(to_state));
@@ -1635,9 +1638,9 @@ channel_listener_change_state(channel_listener_t *chan_l,
if (from_state == to_state) {
log_debug(LD_CHANNEL,
"Got no-op transition from \"%s\" to itself on channel "
- "listener %p (global ID " U64_FORMAT ")",
+ "listener %p (global ID %"PRIu64 ")",
channel_listener_state_to_string(to_state),
- chan_l, U64_PRINTF_ARG(chan_l->global_identifier));
+ chan_l, (chan_l->global_identifier));
return;
}
@@ -1649,9 +1652,9 @@ channel_listener_change_state(channel_listener_t *chan_l,
}
log_debug(LD_CHANNEL,
- "Changing state of channel listener %p (global ID " U64_FORMAT
+ "Changing state of channel listener %p (global ID %"PRIu64
"from \"%s\" to \"%s\"",
- chan_l, U64_PRINTF_ARG(chan_l->global_identifier),
+ chan_l, (chan_l->global_identifier),
channel_listener_state_to_string(chan_l->state),
channel_listener_state_to_string(to_state));
@@ -1800,8 +1803,8 @@ channel_listener_process_incoming(channel_listener_t *listener)
log_debug(LD_CHANNEL,
"Processing queue of incoming connections for channel "
- "listener %p (global ID " U64_FORMAT ")",
- listener, U64_PRINTF_ARG(listener->global_identifier));
+ "listener %p (global ID %"PRIu64 ")",
+ listener, (listener->global_identifier));
if (!(listener->incoming_list)) return;
@@ -1810,12 +1813,12 @@ channel_listener_process_incoming(channel_listener_t *listener)
tor_assert(chan);
log_debug(LD_CHANNEL,
- "Handling incoming channel %p (" U64_FORMAT ") "
- "for listener %p (" U64_FORMAT ")",
+ "Handling incoming channel %p (%"PRIu64 ") "
+ "for listener %p (%"PRIu64 ")",
chan,
- U64_PRINTF_ARG(chan->global_identifier),
+ (chan->global_identifier),
listener,
- U64_PRINTF_ARG(listener->global_identifier));
+ (listener->global_identifier));
/* Make sure this is set correctly */
channel_mark_incoming(chan);
listener->listener(listener, chan);
@@ -1921,10 +1924,10 @@ channel_listener_queue_incoming(channel_listener_t *listener,
tor_assert(incoming);
log_debug(LD_CHANNEL,
- "Queueing incoming channel %p (global ID " U64_FORMAT ") on "
- "channel listener %p (global ID " U64_FORMAT ")",
- incoming, U64_PRINTF_ARG(incoming->global_identifier),
- listener, U64_PRINTF_ARG(listener->global_identifier));
+ "Queueing incoming channel %p (global ID %"PRIu64 ") on "
+ "channel listener %p (global ID %"PRIu64 ")",
+ incoming, (incoming->global_identifier),
+ listener, (listener->global_identifier));
/* Do we need to queue it, or can we just call the listener right away? */
if (!(listener->listener)) need_to_queue = 1;
@@ -1981,8 +1984,8 @@ channel_process_cell(channel_t *chan, cell_t *cell)
log_debug(LD_CHANNEL,
"Processing incoming cell_t %p for channel %p (global ID "
- U64_FORMAT ")", cell, chan,
- U64_PRINTF_ARG(chan->global_identifier));
+ "%"PRIu64 ")", cell, chan,
+ (chan->global_identifier));
chan->cell_handler(chan, cell);
}
@@ -2022,8 +2025,8 @@ channel_send_destroy(circid_t circ_id, channel_t *chan, int reason)
tor_assert(chan);
if (circ_id == 0) {
log_warn(LD_BUG, "Attempted to send a destroy cell for circID 0 "
- "on a channel " U64_FORMAT " at %p in state %s (%d)",
- U64_PRINTF_ARG(chan->global_identifier),
+ "on a channel %"PRIu64 " at %p in state %s (%d)",
+ (chan->global_identifier),
chan, channel_state_to_string(chan->state),
chan->state);
return 0;
@@ -2035,14 +2038,14 @@ channel_send_destroy(circid_t circ_id, channel_t *chan, int reason)
circuitmux_append_destroy_cell(chan, chan->cmux, circ_id, reason);
log_debug(LD_OR,
"Sending destroy (circID %u) on channel %p "
- "(global ID " U64_FORMAT ")",
+ "(global ID %"PRIu64 ")",
(unsigned)circ_id, chan,
- U64_PRINTF_ARG(chan->global_identifier));
+ (chan->global_identifier));
} else {
log_warn(LD_BUG,
"Someone called channel_send_destroy() for circID %u "
- "on a channel " U64_FORMAT " at %p in state %s (%d)",
- (unsigned)circ_id, U64_PRINTF_ARG(chan->global_identifier),
+ "on a channel %"PRIu64 " at %p in state %s (%d)",
+ (unsigned)circ_id, (chan->global_identifier),
chan, channel_state_to_string(chan->state),
chan->state);
}
@@ -2176,9 +2179,9 @@ channel_free_list(smartlist_t *channels, int mark_for_close)
/* Deregister and free it */
tor_assert(curr);
log_debug(LD_CHANNEL,
- "Cleaning up channel %p (global ID " U64_FORMAT ") "
+ "Cleaning up channel %p (global ID %"PRIu64 ") "
"in state %s (%d)",
- curr, U64_PRINTF_ARG(curr->global_identifier),
+ curr, (curr->global_identifier),
channel_state_to_string(curr->state), curr->state);
/* Detach circuits early so they can find the channel */
if (curr->cmux) {
@@ -2207,9 +2210,9 @@ channel_listener_free_list(smartlist_t *listeners, int mark_for_close)
/* Deregister and free it */
tor_assert(curr);
log_debug(LD_CHANNEL,
- "Cleaning up channel listener %p (global ID " U64_FORMAT ") "
+ "Cleaning up channel listener %p (global ID %"PRIu64 ") "
"in state %s (%d)",
- curr, U64_PRINTF_ARG(curr->global_identifier),
+ curr, (curr->global_identifier),
channel_listener_state_to_string(curr->state), curr->state);
channel_listener_unregister(curr);
if (mark_for_close) {
@@ -2532,33 +2535,33 @@ channel_dump_statistics, (channel_t *chan, int severity))
age = (double)(now - chan->timestamp_created);
tor_log(severity, LD_GENERAL,
- "Channel " U64_FORMAT " (at %p) with transport %s is in state "
+ "Channel %"PRIu64 " (at %p) with transport %s is in state "
"%s (%d)",
- U64_PRINTF_ARG(chan->global_identifier), chan,
+ (chan->global_identifier), chan,
channel_describe_transport(chan),
channel_state_to_string(chan->state), chan->state);
tor_log(severity, LD_GENERAL,
- " * Channel " U64_FORMAT " was created at " U64_FORMAT
- " (" U64_FORMAT " seconds ago) "
- "and last active at " U64_FORMAT " (" U64_FORMAT " seconds ago)",
- U64_PRINTF_ARG(chan->global_identifier),
- U64_PRINTF_ARG(chan->timestamp_created),
- U64_PRINTF_ARG(now - chan->timestamp_created),
- U64_PRINTF_ARG(chan->timestamp_active),
- U64_PRINTF_ARG(now - chan->timestamp_active));
+ " * Channel %"PRIu64 " was created at %"PRIu64
+ " (%"PRIu64 " seconds ago) "
+ "and last active at %"PRIu64 " (%"PRIu64 " seconds ago)",
+ (chan->global_identifier),
+ (uint64_t)(chan->timestamp_created),
+ (uint64_t)(now - chan->timestamp_created),
+ (uint64_t)(chan->timestamp_active),
+ (uint64_t)(now - chan->timestamp_active));
/* Handle digest. */
if (!tor_digest_is_zero(chan->identity_digest)) {
tor_log(severity, LD_GENERAL,
- " * Channel " U64_FORMAT " says it is connected "
+ " * Channel %"PRIu64 " says it is connected "
"to an OR with digest %s",
- U64_PRINTF_ARG(chan->global_identifier),
+ (chan->global_identifier),
hex_str(chan->identity_digest, DIGEST_LEN));
} else {
tor_log(severity, LD_GENERAL,
- " * Channel " U64_FORMAT " does not know the digest"
+ " * Channel %"PRIu64 " does not know the digest"
" of the OR it is connected to",
- U64_PRINTF_ARG(chan->global_identifier));
+ (chan->global_identifier));
}
/* Handle remote address and descriptions */
@@ -2567,10 +2570,10 @@ channel_dump_statistics, (channel_t *chan, int severity))
char *actual = tor_strdup(channel_get_actual_remote_descr(chan));
remote_addr_str = tor_addr_to_str_dup(&remote_addr);
tor_log(severity, LD_GENERAL,
- " * Channel " U64_FORMAT " says its remote address"
+ " * Channel %"PRIu64 " says its remote address"
" is %s, and gives a canonical description of \"%s\" and an "
"actual description of \"%s\"",
- U64_PRINTF_ARG(chan->global_identifier),
+ (chan->global_identifier),
safe_str(remote_addr_str),
safe_str(channel_get_canonical_remote_descr(chan)),
safe_str(actual));
@@ -2579,10 +2582,10 @@ channel_dump_statistics, (channel_t *chan, int severity))
} else {
char *actual = tor_strdup(channel_get_actual_remote_descr(chan));
tor_log(severity, LD_GENERAL,
- " * Channel " U64_FORMAT " does not know its remote "
+ " * Channel %"PRIu64 " does not know its remote "
"address, but gives a canonical description of \"%s\" and an "
"actual description of \"%s\"",
- U64_PRINTF_ARG(chan->global_identifier),
+ (chan->global_identifier),
channel_get_canonical_remote_descr(chan),
actual);
tor_free(actual);
@@ -2590,9 +2593,9 @@ channel_dump_statistics, (channel_t *chan, int severity))
/* Handle marks */
tor_log(severity, LD_GENERAL,
- " * Channel " U64_FORMAT " has these marks: %s %s %s "
+ " * Channel %"PRIu64 " has these marks: %s %s %s "
"%s %s %s",
- U64_PRINTF_ARG(chan->global_identifier),
+ (chan->global_identifier),
channel_is_bad_for_new_circs(chan) ?
"bad_for_new_circs" : "!bad_for_new_circs",
channel_is_canonical(chan) ?
@@ -2609,9 +2612,9 @@ channel_dump_statistics, (channel_t *chan, int severity))
/* Describe circuits */
tor_log(severity, LD_GENERAL,
- " * Channel " U64_FORMAT " has %d active circuits out of"
+ " * Channel %"PRIu64 " has %d active circuits out of"
" %d in total",
- U64_PRINTF_ARG(chan->global_identifier),
+ (chan->global_identifier),
(chan->cmux != NULL) ?
circuitmux_num_active_circuits(chan->cmux) : 0,
(chan->cmux != NULL) ?
@@ -2619,78 +2622,78 @@ channel_dump_statistics, (channel_t *chan, int severity))
/* Describe timestamps */
tor_log(severity, LD_GENERAL,
- " * Channel " U64_FORMAT " was last used by a "
- "client at " U64_FORMAT " (" U64_FORMAT " seconds ago)",
- U64_PRINTF_ARG(chan->global_identifier),
- U64_PRINTF_ARG(chan->timestamp_client),
- U64_PRINTF_ARG(now - chan->timestamp_client));
+ " * Channel %"PRIu64 " was last used by a "
+ "client at %"PRIu64 " (%"PRIu64 " seconds ago)",
+ (chan->global_identifier),
+ (uint64_t)(chan->timestamp_client),
+ (uint64_t)(now - chan->timestamp_client));
tor_log(severity, LD_GENERAL,
- " * Channel " U64_FORMAT " last received a cell "
- "at " U64_FORMAT " (" U64_FORMAT " seconds ago)",
- U64_PRINTF_ARG(chan->global_identifier),
- U64_PRINTF_ARG(chan->timestamp_recv),
- U64_PRINTF_ARG(now - chan->timestamp_recv));
+ " * Channel %"PRIu64 " last received a cell "
+ "at %"PRIu64 " (%"PRIu64 " seconds ago)",
+ (chan->global_identifier),
+ (uint64_t)(chan->timestamp_recv),
+ (uint64_t)(now - chan->timestamp_recv));
tor_log(severity, LD_GENERAL,
- " * Channel " U64_FORMAT " last transmitted a cell "
- "at " U64_FORMAT " (" U64_FORMAT " seconds ago)",
- U64_PRINTF_ARG(chan->global_identifier),
- U64_PRINTF_ARG(chan->timestamp_xmit),
- U64_PRINTF_ARG(now - chan->timestamp_xmit));
+ " * Channel %"PRIu64 " last transmitted a cell "
+ "at %"PRIu64 " (%"PRIu64 " seconds ago)",
+ (chan->global_identifier),
+ (uint64_t)(chan->timestamp_xmit),
+ (uint64_t)(now - chan->timestamp_xmit));
/* Describe counters and rates */
tor_log(severity, LD_GENERAL,
- " * Channel " U64_FORMAT " has received "
- U64_FORMAT " bytes in " U64_FORMAT " cells and transmitted "
- U64_FORMAT " bytes in " U64_FORMAT " cells",
- U64_PRINTF_ARG(chan->global_identifier),
- U64_PRINTF_ARG(chan->n_bytes_recved),
- U64_PRINTF_ARG(chan->n_cells_recved),
- U64_PRINTF_ARG(chan->n_bytes_xmitted),
- U64_PRINTF_ARG(chan->n_cells_xmitted));
+ " * Channel %"PRIu64 " has received "
+ "%"PRIu64 " bytes in %"PRIu64 " cells and transmitted "
+ "%"PRIu64 " bytes in %"PRIu64 " cells",
+ (chan->global_identifier),
+ (chan->n_bytes_recved),
+ (chan->n_cells_recved),
+ (chan->n_bytes_xmitted),
+ (chan->n_cells_xmitted));
if (now > chan->timestamp_created &&
chan->timestamp_created > 0) {
if (chan->n_bytes_recved > 0) {
avg = (double)(chan->n_bytes_recved) / age;
tor_log(severity, LD_GENERAL,
- " * Channel " U64_FORMAT " has averaged %f "
+ " * Channel %"PRIu64 " has averaged %f "
"bytes received per second",
- U64_PRINTF_ARG(chan->global_identifier), avg);
+ (chan->global_identifier), avg);
}
if (chan->n_cells_recved > 0) {
avg = (double)(chan->n_cells_recved) / age;
if (avg >= 1.0) {
tor_log(severity, LD_GENERAL,
- " * Channel " U64_FORMAT " has averaged %f "
+ " * Channel %"PRIu64 " has averaged %f "
"cells received per second",
- U64_PRINTF_ARG(chan->global_identifier), avg);
+ (chan->global_identifier), avg);
} else if (avg >= 0.0) {
interval = 1.0 / avg;
tor_log(severity, LD_GENERAL,
- " * Channel " U64_FORMAT " has averaged %f "
+ " * Channel %"PRIu64 " has averaged %f "
"seconds between received cells",
- U64_PRINTF_ARG(chan->global_identifier), interval);
+ (chan->global_identifier), interval);
}
}
if (chan->n_bytes_xmitted > 0) {
avg = (double)(chan->n_bytes_xmitted) / age;
tor_log(severity, LD_GENERAL,
- " * Channel " U64_FORMAT " has averaged %f "
+ " * Channel %"PRIu64 " has averaged %f "
"bytes transmitted per second",
- U64_PRINTF_ARG(chan->global_identifier), avg);
+ (chan->global_identifier), avg);
}
if (chan->n_cells_xmitted > 0) {
avg = (double)(chan->n_cells_xmitted) / age;
if (avg >= 1.0) {
tor_log(severity, LD_GENERAL,
- " * Channel " U64_FORMAT " has averaged %f "
+ " * Channel %"PRIu64 " has averaged %f "
"cells transmitted per second",
- U64_PRINTF_ARG(chan->global_identifier), avg);
+ (chan->global_identifier), avg);
} else if (avg >= 0.0) {
interval = 1.0 / avg;
tor_log(severity, LD_GENERAL,
- " * Channel " U64_FORMAT " has averaged %f "
+ " * Channel %"PRIu64 " has averaged %f "
"seconds between transmitted cells",
- U64_PRINTF_ARG(chan->global_identifier), interval);
+ (chan->global_identifier), interval);
}
}
}
@@ -2715,29 +2718,29 @@ channel_listener_dump_statistics(channel_listener_t *chan_l, int severity)
age = (double)(now - chan_l->timestamp_created);
tor_log(severity, LD_GENERAL,
- "Channel listener " U64_FORMAT " (at %p) with transport %s is in "
+ "Channel listener %"PRIu64 " (at %p) with transport %s is in "
"state %s (%d)",
- U64_PRINTF_ARG(chan_l->global_identifier), chan_l,
+ (chan_l->global_identifier), chan_l,
channel_listener_describe_transport(chan_l),
channel_listener_state_to_string(chan_l->state), chan_l->state);
tor_log(severity, LD_GENERAL,
- " * Channel listener " U64_FORMAT " was created at " U64_FORMAT
- " (" U64_FORMAT " seconds ago) "
- "and last active at " U64_FORMAT " (" U64_FORMAT " seconds ago)",
- U64_PRINTF_ARG(chan_l->global_identifier),
- U64_PRINTF_ARG(chan_l->timestamp_created),
- U64_PRINTF_ARG(now - chan_l->timestamp_created),
- U64_PRINTF_ARG(chan_l->timestamp_active),
- U64_PRINTF_ARG(now - chan_l->timestamp_active));
+ " * Channel listener %"PRIu64 " was created at %"PRIu64
+ " (%"PRIu64 " seconds ago) "
+ "and last active at %"PRIu64 " (%"PRIu64 " seconds ago)",
+ (chan_l->global_identifier),
+ (uint64_t)(chan_l->timestamp_created),
+ (uint64_t)(now - chan_l->timestamp_created),
+ (uint64_t)(chan_l->timestamp_active),
+ (uint64_t)(now - chan_l->timestamp_active));
tor_log(severity, LD_GENERAL,
- " * Channel listener " U64_FORMAT " last accepted an incoming "
- "channel at " U64_FORMAT " (" U64_FORMAT " seconds ago) "
- "and has accepted " U64_FORMAT " channels in total",
- U64_PRINTF_ARG(chan_l->global_identifier),
- U64_PRINTF_ARG(chan_l->timestamp_accepted),
- U64_PRINTF_ARG(now - chan_l->timestamp_accepted),
- U64_PRINTF_ARG(chan_l->n_accepted));
+ " * Channel listener %"PRIu64 " last accepted an incoming "
+ "channel at %"PRIu64 " (%"PRIu64 " seconds ago) "
+ "and has accepted %"PRIu64 " channels in total",
+ (chan_l->global_identifier),
+ (uint64_t)(chan_l->timestamp_accepted),
+ (uint64_t)(now - chan_l->timestamp_accepted),
+ (uint64_t)(chan_l->n_accepted));
/*
* If it's sensible to do so, get the rate of incoming channels on this
@@ -2749,15 +2752,15 @@ channel_listener_dump_statistics(channel_listener_t *chan_l, int severity)
avg = (double)(chan_l->n_accepted) / age;
if (avg >= 1.0) {
tor_log(severity, LD_GENERAL,
- " * Channel listener " U64_FORMAT " has averaged %f incoming "
+ " * Channel listener %"PRIu64 " has averaged %f incoming "
"channels per second",
- U64_PRINTF_ARG(chan_l->global_identifier), avg);
+ (chan_l->global_identifier), avg);
} else if (avg >= 0.0) {
interval = 1.0 / avg;
tor_log(severity, LD_GENERAL,
- " * Channel listener " U64_FORMAT " has averaged %f seconds "
+ " * Channel listener %"PRIu64 " has averaged %f seconds "
"between incoming channels",
- U64_PRINTF_ARG(chan_l->global_identifier), interval);
+ (chan_l->global_identifier), interval);
}
}
@@ -3475,4 +3478,3 @@ channel_update_bad_for_new_circs(const char *digest, int force)
channel_rsa_id_group_set_badness(&(*iter)->channel_list, force);
}
}
-
diff --git a/src/or/channel.h b/src/core/or/channel.h
index 6cf8cd7f72..b3d97a9add 100644
--- a/src/or/channel.h
+++ b/src/core/or/channel.h
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,10 +9,15 @@
#ifndef TOR_CHANNEL_H
#define TOR_CHANNEL_H
-#include "or.h"
-#include "circuitmux.h"
-#include "timers.h"
-#include "handles.h"
+#include "core/or/or.h"
+#include "core/or/circuitmux.h"
+#include "lib/container/handles.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+
+#include "tor_queue.h"
+
+#define tor_timer_t timeout
+struct tor_timer_t;
/* Channel handler function pointer typedefs */
typedef void (*channel_listener_fn_ptr)(channel_listener_t *, channel_t *);
@@ -30,6 +35,141 @@ typedef enum {
CHANNEL_USED_FOR_USER_TRAFFIC,
} channel_usage_info_t;
+/** Possible rules for generating circuit IDs on an OR connection. */
+typedef enum {
+ CIRC_ID_TYPE_LOWER=0, /**< Pick from 0..1<<15-1. */
+ CIRC_ID_TYPE_HIGHER=1, /**< Pick from 1<<15..1<<16-1. */
+ /** The other side of a connection is an OP: never create circuits to it,
+ * and let it use any circuit ID it wants. */
+ CIRC_ID_TYPE_NEITHER=2
+} circ_id_type_t;
+#define circ_id_type_bitfield_t ENUM_BF(circ_id_type_t)
+
+/* channel states for channel_t */
+
+typedef enum {
+ /*
+ * Closed state - channel is inactive
+ *
+ * Permitted transitions from:
+ * - CHANNEL_STATE_CLOSING
+ * Permitted transitions to:
+ * - CHANNEL_STATE_OPENING
+ */
+ CHANNEL_STATE_CLOSED = 0,
+ /*
+ * Opening state - channel is trying to connect
+ *
+ * Permitted transitions from:
+ * - CHANNEL_STATE_CLOSED
+ * Permitted transitions to:
+ * - CHANNEL_STATE_CLOSING
+ * - CHANNEL_STATE_ERROR
+ * - CHANNEL_STATE_OPEN
+ */
+ CHANNEL_STATE_OPENING,
+ /*
+ * Open state - channel is active and ready for use
+ *
+ * Permitted transitions from:
+ * - CHANNEL_STATE_MAINT
+ * - CHANNEL_STATE_OPENING
+ * Permitted transitions to:
+ * - CHANNEL_STATE_CLOSING
+ * - CHANNEL_STATE_ERROR
+ * - CHANNEL_STATE_MAINT
+ */
+ CHANNEL_STATE_OPEN,
+ /*
+ * Maintenance state - channel is temporarily offline for subclass specific
+ * maintenance activities such as TLS renegotiation.
+ *
+ * Permitted transitions from:
+ * - CHANNEL_STATE_OPEN
+ * Permitted transitions to:
+ * - CHANNEL_STATE_CLOSING
+ * - CHANNEL_STATE_ERROR
+ * - CHANNEL_STATE_OPEN
+ */
+ CHANNEL_STATE_MAINT,
+ /*
+ * Closing state - channel is shutting down
+ *
+ * Permitted transitions from:
+ * - CHANNEL_STATE_MAINT
+ * - CHANNEL_STATE_OPEN
+ * Permitted transitions to:
+ * - CHANNEL_STATE_CLOSED,
+ * - CHANNEL_STATE_ERROR
+ */
+ CHANNEL_STATE_CLOSING,
+ /*
+ * Error state - channel has experienced a permanent error
+ *
+ * Permitted transitions from:
+ * - CHANNEL_STATE_CLOSING
+ * - CHANNEL_STATE_MAINT
+ * - CHANNEL_STATE_OPENING
+ * - CHANNEL_STATE_OPEN
+ * Permitted transitions to:
+ * - None
+ */
+ CHANNEL_STATE_ERROR,
+ /*
+ * Placeholder for maximum state value
+ */
+ CHANNEL_STATE_LAST
+} channel_state_t;
+
+/* channel listener states for channel_listener_t */
+
+typedef enum {
+ /*
+ * Closed state - channel listener is inactive
+ *
+ * Permitted transitions from:
+ * - CHANNEL_LISTENER_STATE_CLOSING
+ * Permitted transitions to:
+ * - CHANNEL_LISTENER_STATE_LISTENING
+ */
+ CHANNEL_LISTENER_STATE_CLOSED = 0,
+ /*
+ * Listening state - channel listener is listening for incoming
+ * connections
+ *
+ * Permitted transitions from:
+ * - CHANNEL_LISTENER_STATE_CLOSED
+ * Permitted transitions to:
+ * - CHANNEL_LISTENER_STATE_CLOSING
+ * - CHANNEL_LISTENER_STATE_ERROR
+ */
+ CHANNEL_LISTENER_STATE_LISTENING,
+ /*
+ * Closing state - channel listener is shutting down
+ *
+ * Permitted transitions from:
+ * - CHANNEL_LISTENER_STATE_LISTENING
+ * Permitted transitions to:
+ * - CHANNEL_LISTENER_STATE_CLOSED,
+ * - CHANNEL_LISTENER_STATE_ERROR
+ */
+ CHANNEL_LISTENER_STATE_CLOSING,
+ /*
+ * Error state - channel listener has experienced a permanent error
+ *
+ * Permitted transitions from:
+ * - CHANNEL_STATE_CLOSING
+ * - CHANNEL_STATE_LISTENING
+ * Permitted transitions to:
+ * - None
+ */
+ CHANNEL_LISTENER_STATE_ERROR,
+ /*
+ * Placeholder for maximum state value
+ */
+ CHANNEL_LISTENER_STATE_LAST
+} channel_listener_state_t;
+
/**
* Channel struct; see the channel_t typedef in or.h. A channel is an
* abstract interface for the OR-to-OR connection, similar to connection_or_t,
@@ -92,7 +232,7 @@ struct channel_s {
monotime_coarse_t next_padding_time;
/** The callback pointer for the padding callbacks */
- tor_timer_t *padding_timer;
+ struct tor_timer_t *padding_timer;
/** The handle to this channel (to free on canceled timers) */
struct channel_handle_t *timer_handle;
@@ -251,7 +391,7 @@ struct channel_s {
* necessarily its true identity. Don't believe this identity unless
* authentication has happened.
*/
- ed25519_public_key_t ed25519_identity;
+ struct ed25519_public_key_t ed25519_identity;
/**
* Linked list of channels with the same RSA identity digest, for use with
@@ -470,8 +610,8 @@ void channel_mark_incoming(channel_t *chan);
void channel_mark_outgoing(channel_t *chan);
void channel_mark_remote(channel_t *chan);
void channel_set_identity_digest(channel_t *chan,
- const char *identity_digest,
- const ed25519_public_key_t *ed_identity);
+ const char *identity_digest,
+ const struct ed25519_public_key_t *ed_identity);
void channel_listener_change_state(channel_listener_t *chan_l,
channel_listener_state_t to_state);
@@ -521,10 +661,10 @@ int channel_send_destroy(circid_t circ_id, channel_t *chan,
channel_t * channel_connect(const tor_addr_t *addr, uint16_t port,
const char *rsa_id_digest,
- const ed25519_public_key_t *ed_id);
+ const struct ed25519_public_key_t *ed_id);
channel_t * channel_get_for_extend(const char *rsa_id_digest,
- const ed25519_public_key_t *ed_id,
+ const struct ed25519_public_key_t *ed_id,
const tor_addr_t *target_addr,
const char **msg_out,
int *launch_out);
@@ -537,7 +677,7 @@ int channel_is_better(channel_t *a, channel_t *b);
channel_t * channel_find_by_global_id(uint64_t global_identifier);
channel_t * channel_find_by_remote_identity(const char *rsa_id_digest,
- const ed25519_public_key_t *ed_id);
+ const struct ed25519_public_key_t *ed_id);
/** For things returned by channel_find_by_remote_digest(), walk the list.
* The RSA key will match for all returned elements; the Ed25519 key might not.
@@ -635,6 +775,6 @@ int packed_cell_is_destroy(channel_t *chan,
HANDLE_DECL(channel, channel_s,)
#define channel_handle_free(h) \
FREE_AND_NULL(channel_handle_t, channel_handle_free_, (h))
+#undef tor_timer_t
#endif /* !defined(TOR_CHANNEL_H) */
-
diff --git a/src/or/channelpadding.c b/src/core/or/channelpadding.c
index a8b9a2b47b..b8cfd33d50 100644
--- a/src/or/channelpadding.c
+++ b/src/core/or/channelpadding.c
@@ -1,27 +1,31 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2015, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* TOR_CHANNEL_INTERNAL_ define needed for an O(1) implementation of
* channelpadding_channel_to_channelinfo() */
#define TOR_CHANNEL_INTERNAL_
-#include "or.h"
-#include "channel.h"
-#include "channelpadding.h"
-#include "channeltls.h"
-#include "config.h"
-#include "networkstatus.h"
-#include "connection.h"
-#include "connection_or.h"
-#include "crypto_rand.h"
-#include "main.h"
-#include "rephist.h"
-#include "router.h"
-#include "compat_time.h"
-#include "rendservice.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "core/or/channelpadding.h"
+#include "core/or/channeltls.h"
+#include "app/config/config.h"
+#include "feature/nodelist/networkstatus.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_or.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "core/mainloop/main.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "lib/time/compat_time.h"
+#include "feature/rend/rendservice.h"
+#include "lib/evloop/timers.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/or_connection_st.h"
STATIC int32_t channelpadding_get_netflow_inactive_timeout_ms(
const channel_t *);
@@ -279,10 +283,10 @@ channelpadding_update_padding_for_channel(channel_t *chan,
pad_vars->ito_high_ms);
log_fn(LOG_INFO,LD_OR,
- "Negotiated padding=%d, lo=%d, hi=%d on "U64_FORMAT,
+ "Negotiated padding=%d, lo=%d, hi=%d on %"PRIu64,
chan->padding_enabled, chan->padding_timeout_low_ms,
chan->padding_timeout_high_ms,
- U64_PRINTF_ARG(chan->global_identifier));
+ (chan->global_identifier));
return 1;
}
@@ -390,13 +394,13 @@ channelpadding_send_padding_cell_for_callback(channel_t *chan)
monotime_coarse_get(&now);
log_fn(LOG_INFO,LD_OR,
- "Sending netflow keepalive on "U64_FORMAT" to %s (%s) after "
- I64_FORMAT" ms. Delta "I64_FORMAT"ms",
- U64_PRINTF_ARG(chan->global_identifier),
+ "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(hex_str(chan->identity_digest, DIGEST_LEN)),
- I64_PRINTF_ARG(monotime_coarse_diff_msec(&chan->timestamp_xfer,&now)),
- I64_PRINTF_ARG(
+ (monotime_coarse_diff_msec(&chan->timestamp_xfer,&now)),
+ (
monotime_coarse_diff_msec(&chan->next_padding_time,&now)));
}
@@ -536,9 +540,9 @@ channelpadding_compute_time_until_pad_for_netflow(channel_t *chan)
if (ms_till_pad > DFLT_NETFLOW_INACTIVE_KEEPALIVE_MAX) {
tor_fragile_assert();
log_warn(LD_BUG,
- "Channel padding timeout scheduled "I64_FORMAT"ms in the future. "
+ "Channel padding timeout scheduled %"PRId64"ms in the future. "
"Did the monotonic clock just jump?",
- I64_PRINTF_ARG(ms_till_pad));
+ (ms_till_pad));
return 0; /* Clock jumped: Send padding now */
}
@@ -562,8 +566,8 @@ channelpadding_compute_time_until_pad_for_netflow(channel_t *chan)
int severity = (ms_till_pad < -NETFLOW_MISSED_WINDOW)
? LOG_NOTICE : LOG_INFO;
log_fn(severity, LD_OR,
- "Channel padding timeout scheduled "I64_FORMAT"ms in the past. ",
- I64_PRINTF_ARG(-ms_till_pad));
+ "Channel padding timeout scheduled %"PRId64"ms in the past. ",
+ (-ms_till_pad));
return 0; /* Clock jumped: Send padding now */
}
@@ -694,8 +698,8 @@ channelpadding_reduce_padding_on_channel(channel_t *chan)
chan->padding_timeout_high_ms = consensus_nf_ito_high_reduced;
log_fn(LOG_INFO,LD_OR,
- "Reduced padding on channel "U64_FORMAT": lo=%d, hi=%d",
- U64_PRINTF_ARG(chan->global_identifier),
+ "Reduced padding on channel %"PRIu64": lo=%d, hi=%d",
+ (chan->global_identifier),
chan->padding_timeout_low_ms, chan->padding_timeout_high_ms);
}
@@ -794,4 +798,3 @@ channelpadding_decide_to_pad_channel(channel_t *chan)
return CHANNELPADDING_PADLATER;
}
}
-
diff --git a/src/or/channelpadding.h b/src/core/or/channelpadding.h
index 58bf741d5c..7eddbdbe2d 100644
--- a/src/or/channelpadding.h
+++ b/src/core/or/channelpadding.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2015, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -11,7 +11,7 @@
#ifndef TOR_CHANNELPADDING_H
#define TOR_CHANNELPADDING_H
-#include "channelpadding_negotiation.h"
+#include "trunnel/channelpadding_negotiation.h"
#define CHANNELPADDING_TOR2WEB_PARAM "nf_pad_tor2web"
#define CHANNELPADDING_TOR2WEB_DEFAULT 1
diff --git a/src/or/channeltls.c b/src/core/or/channeltls.c
index 54d94f6109..87f5a02b75 100644
--- a/src/or/channeltls.c
+++ b/src/core/or/channeltls.c
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -38,27 +38,38 @@
#define CHANNELTLS_PRIVATE
-#include "or.h"
-#include "channel.h"
-#include "channeltls.h"
-#include "circuitmux.h"
-#include "circuitmux_ewma.h"
-#include "command.h"
-#include "config.h"
-#include "connection.h"
-#include "connection_or.h"
-#include "control.h"
-#include "entrynodes.h"
-#include "link_handshake.h"
-#include "relay.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerlist.h"
-#include "scheduler.h"
-#include "torcert.h"
-#include "networkstatus.h"
-#include "channelpadding_negotiation.h"
-#include "channelpadding.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "core/or/channeltls.h"
+#include "core/or/circuitmux.h"
+#include "core/or/circuitmux_ewma.h"
+#include "core/or/command.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_or.h"
+#include "feature/control/control.h"
+#include "feature/client/entrynodes.h"
+#include "trunnel/link_handshake.h"
+#include "core/or/relay.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "core/or/scheduler.h"
+#include "feature/nodelist/torcert.h"
+#include "feature/nodelist/networkstatus.h"
+#include "trunnel/channelpadding_negotiation.h"
+#include "core/or/channelpadding.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 "lib/tls/tortls.h"
/** How many CELL_PADDING cells have we received, ever? */
uint64_t stats_n_padding_cells_processed = 0;
@@ -183,19 +194,19 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
log_debug(LD_CHANNEL,
"In channel_tls_connect() for channel %p "
- "(global id " U64_FORMAT ")",
+ "(global id %"PRIu64 ")",
tlschan,
- U64_PRINTF_ARG(chan->global_identifier));
+ (chan->global_identifier));
if (is_local_addr(addr)) {
log_debug(LD_CHANNEL,
- "Marking new outgoing channel " U64_FORMAT " at %p as local",
- U64_PRINTF_ARG(chan->global_identifier), chan);
+ "Marking new outgoing channel %"PRIu64 " at %p as local",
+ (chan->global_identifier), chan);
channel_mark_local(chan);
} else {
log_debug(LD_CHANNEL,
- "Marking new outgoing channel " U64_FORMAT " at %p as remote",
- U64_PRINTF_ARG(chan->global_identifier), chan);
+ "Marking new outgoing channel %"PRIu64 " at %p as remote",
+ (chan->global_identifier), chan);
channel_mark_remote(chan);
}
@@ -211,8 +222,8 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
}
log_debug(LD_CHANNEL,
- "Got orconn %p for channel with global id " U64_FORMAT,
- tlschan->conn, U64_PRINTF_ARG(chan->global_identifier));
+ "Got orconn %p for channel with global id %"PRIu64,
+ tlschan->conn, (chan->global_identifier));
goto done;
@@ -262,8 +273,8 @@ channel_tls_start_listener(void)
channel_tls_listener = listener;
log_debug(LD_CHANNEL,
- "Starting TLS channel listener %p with global id " U64_FORMAT,
- listener, U64_PRINTF_ARG(listener->global_identifier));
+ "Starting TLS channel listener %p with global id %"PRIu64,
+ listener, (listener->global_identifier));
channel_listener_register(listener);
} else listener = channel_tls_listener;
@@ -292,9 +303,9 @@ channel_tls_free_all(void)
*/
old_listener = channel_tls_listener;
log_debug(LD_CHANNEL,
- "Closing channel_tls_listener with ID " U64_FORMAT
+ "Closing channel_tls_listener with ID %"PRIu64
" at %p.",
- U64_PRINTF_ARG(old_listener->global_identifier),
+ (old_listener->global_identifier),
old_listener);
channel_listener_unregister(old_listener);
channel_listener_mark_for_close(old_listener);
@@ -326,13 +337,13 @@ channel_tls_handle_incoming(or_connection_t *orconn)
if (is_local_addr(&(TO_CONN(orconn)->addr))) {
log_debug(LD_CHANNEL,
- "Marking new incoming channel " U64_FORMAT " at %p as local",
- U64_PRINTF_ARG(chan->global_identifier), chan);
+ "Marking new incoming channel %"PRIu64 " at %p as local",
+ (chan->global_identifier), chan);
channel_mark_local(chan);
} else {
log_debug(LD_CHANNEL,
- "Marking new incoming channel " U64_FORMAT " at %p as remote",
- U64_PRINTF_ARG(chan->global_identifier), chan);
+ "Marking new incoming channel %"PRIu64 " at %p as remote",
+ (chan->global_identifier), chan);
channel_mark_remote(chan);
}
@@ -422,8 +433,8 @@ channel_tls_describe_transport_method(channel_t *chan)
if (buf) tor_free(buf);
tor_asprintf(&buf,
- "TLS channel (connection " U64_FORMAT ")",
- U64_PRINTF_ARG(id));
+ "TLS channel (connection %"PRIu64 ")",
+ (id));
rv = buf;
} else {
@@ -484,8 +495,8 @@ channel_tls_get_overhead_estimate_method(channel_t *chan)
}
log_debug(LD_CHANNEL,
- "Estimated overhead ratio for TLS chan " U64_FORMAT " is %f",
- U64_PRINTF_ARG(chan->global_identifier), overhead);
+ "Estimated overhead ratio for TLS chan %"PRIu64 " is %f",
+ (chan->global_identifier), overhead);
return overhead;
}
@@ -616,8 +627,8 @@ channel_tls_has_queued_writes_method(channel_t *chan)
if (!(tlschan->conn)) {
log_info(LD_CHANNEL,
"something called has_queued_writes on a tlschan "
- "(%p with ID " U64_FORMAT " but no conn",
- chan, U64_PRINTF_ARG(chan->global_identifier));
+ "(%p with ID %"PRIu64 " but no conn",
+ chan, (chan->global_identifier));
}
outbuf_len = (tlschan->conn != NULL) ?
@@ -684,8 +695,8 @@ channel_tls_matches_extend_info_method(channel_t *chan,
if (!(tlschan->conn)) {
log_info(LD_CHANNEL,
"something called matches_extend_info on a tlschan "
- "(%p with ID " U64_FORMAT " but no conn",
- chan, U64_PRINTF_ARG(chan->global_identifier));
+ "(%p with ID %"PRIu64 " but no conn",
+ chan, (chan->global_identifier));
return 0;
}
@@ -714,8 +725,8 @@ channel_tls_matches_target_method(channel_t *chan,
if (!(tlschan->conn)) {
log_info(LD_CHANNEL,
"something called matches_target on a tlschan "
- "(%p with ID " U64_FORMAT " but no conn",
- chan, U64_PRINTF_ARG(chan->global_identifier));
+ "(%p with ID %"PRIu64 " but no conn",
+ chan, (chan->global_identifier));
return 0;
}
@@ -797,8 +808,8 @@ channel_tls_write_cell_method(channel_t *chan, cell_t *cell)
} else {
log_info(LD_CHANNEL,
"something called write_cell on a tlschan "
- "(%p with ID " U64_FORMAT " but no conn",
- chan, U64_PRINTF_ARG(chan->global_identifier));
+ "(%p with ID %"PRIu64 " but no conn",
+ chan, (chan->global_identifier));
}
return written;
@@ -830,8 +841,8 @@ channel_tls_write_packed_cell_method(channel_t *chan,
} else {
log_info(LD_CHANNEL,
"something called write_packed_cell on a tlschan "
- "(%p with ID " U64_FORMAT " but no conn",
- chan, U64_PRINTF_ARG(chan->global_identifier));
+ "(%p with ID %"PRIu64 " but no conn",
+ chan, (chan->global_identifier));
return -1;
}
@@ -859,8 +870,8 @@ channel_tls_write_var_cell_method(channel_t *chan, var_cell_t *var_cell)
} else {
log_info(LD_CHANNEL,
"something called write_var_cell on a tlschan "
- "(%p with ID " U64_FORMAT " but no conn",
- chan, U64_PRINTF_ARG(chan->global_identifier));
+ "(%p with ID %"PRIu64 " but no conn",
+ chan, (chan->global_identifier));
}
return written;
@@ -1332,15 +1343,15 @@ channel_tls_update_marks(or_connection_t *conn)
if (is_local_addr(&(TO_CONN(conn)->addr))) {
if (!channel_is_local(chan)) {
log_debug(LD_CHANNEL,
- "Marking channel " U64_FORMAT " at %p as local",
- U64_PRINTF_ARG(chan->global_identifier), chan);
+ "Marking channel %"PRIu64 " at %p as local",
+ (chan->global_identifier), chan);
channel_mark_local(chan);
}
} else {
if (channel_is_local(chan)) {
log_debug(LD_CHANNEL,
- "Marking channel " U64_FORMAT " at %p as remote",
- U64_PRINTF_ARG(chan->global_identifier), chan);
+ "Marking channel %"PRIu64 " at %p as remote",
+ (chan->global_identifier), chan);
channel_mark_remote(chan);
}
}
@@ -2445,4 +2456,3 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan)
#undef ERR
}
-
diff --git a/src/or/channeltls.h b/src/core/or/channeltls.h
index d9c4239c3a..4a10d51d9f 100644
--- a/src/or/channeltls.h
+++ b/src/core/or/channeltls.h
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,8 +9,11 @@
#ifndef TOR_CHANNELTLS_H
#define TOR_CHANNELTLS_H
-#include "or.h"
-#include "channel.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
+
+struct ed25519_public_key_t;
+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)))
@@ -30,7 +33,7 @@ struct channel_tls_s {
channel_t * channel_tls_connect(const tor_addr_t *addr, uint16_t port,
const char *id_digest,
- const ed25519_public_key_t *ed_id);
+ const struct ed25519_public_key_t *ed_id);
channel_listener_t * channel_tls_get_listener(void);
channel_listener_t * channel_tls_start_listener(void);
channel_t * channel_tls_handle_incoming(or_connection_t *orconn);
@@ -72,4 +75,3 @@ STATIC void channel_tls_process_authenticate_cell(var_cell_t *cell,
#endif /* defined(CHANNELTLS_PRIVATE) */
#endif /* !defined(TOR_CHANNELTLS_H) */
-
diff --git a/src/core/or/circuit_st.h b/src/core/or/circuit_st.h
new file mode 100644
index 0000000000..2e33b37b01
--- /dev/null
+++ b/src/core/or/circuit_st.h
@@ -0,0 +1,182 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef CIRCUIT_ST_H
+#define CIRCUIT_ST_H
+
+#include "core/or/or.h"
+
+#include "core/or/cell_queue_st.h"
+
+struct hs_token_t;
+
+/** "magic" value for an origin_circuit_t */
+#define ORIGIN_CIRCUIT_MAGIC 0x35315243u
+/** "magic" value for an or_circuit_t */
+#define OR_CIRCUIT_MAGIC 0x98ABC04Fu
+/** "magic" value for a circuit that would have been freed by circuit_free,
+ * but which we're keeping around until a cpuworker reply arrives. See
+ * circuit_free() for more documentation. */
+#define DEAD_CIRCUIT_MAGIC 0xdeadc14c
+
+/**
+ * A circuit is a path over the onion routing
+ * network. Applications can connect to one end of the circuit, and can
+ * create exit connections at the other end of the circuit. AP and exit
+ * connections have only one circuit associated with them (and thus these
+ * connection types are closed when the circuit is closed), whereas
+ * OR connections multiplex many circuits at once, and stay standing even
+ * when there are no circuits running over them.
+ *
+ * A circuit_t structure can fill one of two roles. First, a or_circuit_t
+ * links two connections together: either an edge connection and an OR
+ * connection, or two OR connections. (When joined to an OR connection, a
+ * circuit_t affects only cells sent to a particular circID on that
+ * connection. When joined to an edge connection, a circuit_t affects all
+ * data.)
+
+ * Second, an origin_circuit_t holds the cipher keys and state for sending data
+ * along a given circuit. At the OP, it has a sequence of ciphers, each
+ * of which is shared with a single OR along the circuit. Separate
+ * ciphers are used for data going "forward" (away from the OP) and
+ * "backward" (towards the OP). At the OR, a circuit has only two stream
+ * ciphers: one for data going forward, and one for data going backward.
+ */
+struct circuit_t {
+ uint32_t magic; /**< For memory and type debugging: must equal
+ * ORIGIN_CIRCUIT_MAGIC or OR_CIRCUIT_MAGIC. */
+
+ /** The channel that is next in this circuit. */
+ channel_t *n_chan;
+
+ /**
+ * The circuit_id used in the next (forward) hop of this circuit;
+ * this is unique to n_chan, but this ordered pair is globally
+ * unique:
+ *
+ * (n_chan->global_identifier, n_circ_id)
+ */
+ circid_t n_circ_id;
+
+ /**
+ * Circuit mux associated with n_chan to which this circuit is attached;
+ * NULL if we have no n_chan.
+ */
+ circuitmux_t *n_mux;
+
+ /** Queue of cells waiting to be transmitted on n_chan */
+ cell_queue_t n_chan_cells;
+
+ /**
+ * The hop to which we want to extend this circuit. Should be NULL if
+ * the circuit has attached to a channel.
+ */
+ extend_info_t *n_hop;
+
+ /** True iff we are waiting for n_chan_cells to become less full before
+ * allowing p_streams to add any more cells. (Origin circuit only.) */
+ unsigned int streams_blocked_on_n_chan : 1;
+ /** True iff we are waiting for p_chan_cells to become less full before
+ * allowing n_streams to add any more cells. (OR circuit only.) */
+ unsigned int streams_blocked_on_p_chan : 1;
+
+ /** True iff we have queued a delete backwards on this circuit, but not put
+ * it on the output buffer. */
+ unsigned int p_delete_pending : 1;
+ /** True iff we have queued a delete forwards on this circuit, but not put
+ * it on the output buffer. */
+ unsigned int n_delete_pending : 1;
+
+ /** True iff this circuit has received a DESTROY cell in either direction */
+ unsigned int received_destroy : 1;
+
+ uint8_t state; /**< Current status of this circuit. */
+ uint8_t purpose; /**< Why are we creating this circuit? */
+
+ /** How many relay data cells can we package (read from edge streams)
+ * on this circuit before we receive a circuit-level sendme cell asking
+ * for more? */
+ int package_window;
+ /** How many relay data cells will we deliver (write to edge streams)
+ * on this circuit? When deliver_window gets low, we send some
+ * circuit-level sendme cells to indicate that we're willing to accept
+ * more. */
+ int deliver_window;
+
+ /** Temporary field used during circuits_handle_oom. */
+ uint32_t age_tmp;
+
+ /** For storage while n_chan is pending (state CIRCUIT_STATE_CHAN_WAIT). */
+ struct create_cell_t *n_chan_create_cell;
+
+ /** When did circuit construction actually begin (ie send the
+ * CREATE cell or begin cannibalization).
+ *
+ * Note: This timer will get reset if we decide to cannibalize
+ * a circuit. It may also get reset during certain phases of hidden
+ * service circuit use.
+ *
+ * We keep this timestamp with a higher resolution than most so that the
+ * circuit-build-time tracking code can get millisecond resolution.
+ */
+ struct timeval timestamp_began;
+
+ /** This timestamp marks when the init_circuit_base constructor ran. */
+ struct timeval timestamp_created;
+
+ /** When the circuit was first used, or 0 if the circuit is clean.
+ *
+ * XXXX Note that some code will artificially adjust this value backward
+ * in time in order to indicate that a circuit shouldn't be used for new
+ * streams, but that it can stay alive as long as it has streams on it.
+ * That's a kludge we should fix.
+ *
+ * XXX The CBT code uses this field to record when HS-related
+ * circuits entered certain states. This usage probably won't
+ * interfere with this field's primary purpose, but we should
+ * document it more thoroughly to make sure of that.
+ *
+ * XXX The SocksPort option KeepaliveIsolateSOCKSAuth will artificially
+ * adjust this value forward each time a suitable stream is attached to an
+ * already constructed circuit, potentially keeping the circuit alive
+ * indefinitely.
+ */
+ time_t timestamp_dirty;
+
+ uint16_t marked_for_close; /**< Should we close this circuit at the end of
+ * the main loop? (If true, holds the line number
+ * where this circuit was marked.) */
+ const char *marked_for_close_file; /**< For debugging: in which file was this
+ * circuit marked for close? */
+ /** For what reason (See END_CIRC_REASON...) is this circuit being closed?
+ * This field is set in circuit_mark_for_close and used later in
+ * circuit_about_to_free. */
+ int marked_for_close_reason;
+ /** As marked_for_close_reason, but reflects the underlying reason for
+ * closing this circuit.
+ */
+ int marked_for_close_orig_reason;
+
+ /** Unique ID for measuring tunneled network status requests. */
+ uint64_t dirreq_id;
+
+ /** Index in smartlist of all circuits (global_circuitlist). */
+ int global_circuitlist_idx;
+
+ /** Various statistics about cells being added to or removed from this
+ * circuit's queues; used only if CELL_STATS events are enabled and
+ * cleared after being sent to control port. */
+ smartlist_t *testing_cell_stats;
+
+ /** If set, points to an HS token that this circuit might be carrying.
+ * Used by the HS circuitmap. */
+ struct hs_token_t *hs_token;
+ /** Hashtable node: used to look up the circuit by its HS token using the HS
+ circuitmap. */
+ HT_ENTRY(circuit_t) hs_circuitmap_node;
+};
+
+#endif
diff --git a/src/or/circuitbuild.c b/src/core/or/circuitbuild.c
index 3d1c9c1abf..e22ddabde3 100644
--- a/src/or/circuitbuild.c
+++ b/src/core/or/circuitbuild.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -27,43 +27,54 @@
#define CIRCUITBUILD_PRIVATE
-#include "or.h"
-#include "bridges.h"
-#include "channel.h"
-#include "circpathbias.h"
+#include "core/or/or.h"
+#include "feature/client/bridges.h"
+#include "core/or/channel.h"
+#include "feature/client/circpathbias.h"
#define CIRCUITBUILD_PRIVATE
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuitstats.h"
-#include "circuituse.h"
-#include "command.h"
-#include "config.h"
-#include "confparse.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "connection_or.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "directory.h"
-#include "entrynodes.h"
-#include "hs_ntor.h"
-#include "main.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "onion.h"
-#include "onion_tap.h"
-#include "onion_fast.h"
-#include "policies.h"
-#include "relay.h"
-#include "relay_crypto.h"
-#include "rendcommon.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "routerset.h"
-#include "transports.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuitstats.h"
+#include "core/or/circuituse.h"
+#include "core/or/command.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "core/or/connection_or.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/dircache/directory.h"
+#include "feature/client/entrynodes.h"
+#include "core/crypto/hs_ntor.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/crypto/onion.h"
+#include "core/crypto/onion_tap.h"
+#include "core/crypto/onion_fast.h"
+#include "core/or/policies.h"
+#include "core/or/relay.h"
+#include "core/crypto/relay_crypto.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/routerset.h"
+#include "feature/client/transports.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/cpath_build_state_st.h"
+#include "core/or/entry_connection_st.h"
+#include "core/or/extend_info_st.h"
+#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 channel_t * channel_connect_for_circuit(const tor_addr_t *addr,
uint16_t port,
@@ -191,11 +202,11 @@ get_unique_circ_id_by_chan(channel_t *chan)
chan->cmux);
log_warn(LD_CIRC, " Circuitmux on this channel has %u circuits, "
- "of which %u are active. It says it has "I64_FORMAT
+ "of which %u are active. It says it has %"PRId64
" destroy cells queued.",
circuitmux_num_circuits(chan->cmux),
circuitmux_num_active_circuits(chan->cmux),
- I64_PRINTF_ARG(queued_destroys));
+ (queued_destroys));
/* Change this into "if (1)" in order to get more information about
* possible failure modes here. You'll need to know how to use gdb with
@@ -1139,20 +1150,20 @@ circuit_note_clock_jumped(int64_t seconds_elapsed, bool was_idle)
{
int severity = server_mode(get_options()) ? LOG_WARN : LOG_NOTICE;
if (was_idle) {
- tor_log(severity, LD_GENERAL, "Tor has been idle for "I64_FORMAT
+ tor_log(severity, LD_GENERAL, "Tor has been idle for %"PRId64
" seconds; assuming established circuits no longer work.",
- I64_PRINTF_ARG(seconds_elapsed));
+ (seconds_elapsed));
} else {
tor_log(severity, LD_GENERAL,
- "Your system clock just jumped "I64_FORMAT" seconds %s; "
+ "Your system clock just jumped %"PRId64" seconds %s; "
"assuming established circuits no longer work.",
- I64_PRINTF_ARG(
+ (
seconds_elapsed >=0 ? seconds_elapsed : -seconds_elapsed),
seconds_elapsed >=0 ? "forward" : "backward");
}
- control_event_general_status(LOG_WARN, "CLOCK_JUMPED TIME="I64_FORMAT
+ control_event_general_status(LOG_WARN, "CLOCK_JUMPED TIME=%"PRId64
" IDLE=%d",
- I64_PRINTF_ARG(seconds_elapsed), was_idle?1:0);
+ (seconds_elapsed), was_idle?1:0);
/* so we log when it works again */
note_that_we_maybe_cant_complete_circuits();
control_event_client_status(severity, "CIRCUIT_NOT_ESTABLISHED REASON=%s",
diff --git a/src/or/circuitbuild.h b/src/core/or/circuitbuild.h
index 0184898e29..9f5d99c2a5 100644
--- a/src/or/circuitbuild.h
+++ b/src/core/or/circuitbuild.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,6 +12,9 @@
#ifndef TOR_CIRCUITBUILD_H
#define TOR_CIRCUITBUILD_H
+struct ed25519_public_key_t;
+struct curve25519_public_key_t;
+
int route_len_for_purpose(uint8_t purpose, extend_info_t *exit_ei);
char *circuit_list_path(origin_circuit_t *circ, int verbose);
char *circuit_list_path_for_controller(origin_circuit_t *circ);
@@ -52,9 +55,9 @@ int circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info);
void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop);
extend_info_t *extend_info_new(const char *nickname,
const char *rsa_id_digest,
- const ed25519_public_key_t *ed_id,
+ const struct ed25519_public_key_t *ed_id,
crypto_pk_t *onion_key,
- const curve25519_public_key_t *ntor_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);
@@ -91,8 +94,10 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit_ei,
int is_hs_v3_rp_circuit);
#if defined(ENABLE_TOR2WEB_MODE) || defined(TOR_UNIT_TESTS)
-STATIC const node_t *pick_tor2web_rendezvous_node(router_crn_flags_t flags,
- const or_options_t *options);
+enum router_crn_flags_t;
+STATIC const node_t *pick_tor2web_rendezvous_node(
+ enum router_crn_flags_t flags,
+ const or_options_t *options);
unsigned int cpath_get_n_hops(crypt_path_t **head_ptr);
#endif /* defined(ENABLE_TOR2WEB_MODE) || defined(TOR_UNIT_TESTS) */
@@ -100,4 +105,3 @@ unsigned int cpath_get_n_hops(crypt_path_t **head_ptr);
#endif /* defined(CIRCUITBUILD_PRIVATE) */
#endif /* !defined(TOR_CIRCUITBUILD_H) */
-
diff --git a/src/or/circuitlist.c b/src/core/or/circuitlist.c
index 45fff7cc17..f39e05ecd1 100644
--- a/src/or/circuitlist.c
+++ b/src/core/or/circuitlist.c
@@ -1,7 +1,7 @@
/* Copyright 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -51,46 +51,58 @@
* logic, which was originally circuit-focused.
**/
#define CIRCUITLIST_PRIVATE
-#include "torint.h" /* TOR_PRIuSZ */
-
-#include "or.h"
-#include "channel.h"
-#include "circpathbias.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "circuitstats.h"
-#include "connection.h"
-#include "config.h"
-#include "connection_edge.h"
-#include "connection_or.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "entrynodes.h"
-#include "main.h"
-#include "hs_circuit.h"
-#include "hs_circuitmap.h"
-#include "hs_ident.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "onion.h"
-#include "onion_fast.h"
-#include "policies.h"
-#include "relay.h"
-#include "relay_crypto.h"
-#include "rendclient.h"
-#include "rendcommon.h"
-#include "rephist.h"
-#include "routerlist.h"
-#include "routerset.h"
-#include "channelpadding.h"
-#include "compress_lzma.h"
-#include "compress_zlib.h"
-#include "compress_zstd.h"
+#include "lib/cc/torint.h" /* TOR_PRIuSZ */
+
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "feature/client/circpathbias.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "core/or/circuitstats.h"
+#include "core/mainloop/connection.h"
+#include "app/config/config.h"
+#include "core/or/connection_edge.h"
+#include "core/or/connection_or.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "feature/dircache/directory.h"
+#include "feature/client/entrynodes.h"
+#include "core/mainloop/main.h"
+#include "feature/hs/hs_circuit.h"
+#include "feature/hs/hs_circuitmap.h"
+#include "feature/hs/hs_ident.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/crypto/onion.h"
+#include "core/crypto/onion_fast.h"
+#include "core/or/policies.h"
+#include "core/or/relay.h"
+#include "core/crypto/relay_crypto.h"
+#include "feature/rend/rendclient.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/stats/rephist.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerset.h"
+#include "core/or/channelpadding.h"
+#include "lib/compress/compress.h"
+#include "lib/compress/compress_lzma.h"
+#include "lib/compress/compress_zlib.h"
+#include "lib/compress/compress_zstd.h"
+#include "lib/container/buffers.h"
#include "ht.h"
+#include "core/or/cpath_build_state_st.h"
+#include "core/or/crypt_path_reference_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "core/or/edge_connection_st.h"
+#include "core/or/extend_info_st.h"
+#include "core/or/or_circuit_st.h"
+#include "core/or/origin_circuit_st.h"
+
/********* START VARIABLES **********/
/** A global list of all circuits at this hop. */
@@ -126,6 +138,31 @@ static int any_opened_circs_cached_val = 0;
/********* END VARIABLES ************/
+or_circuit_t *
+TO_OR_CIRCUIT(circuit_t *x)
+{
+ tor_assert(x->magic == OR_CIRCUIT_MAGIC);
+ return DOWNCAST(or_circuit_t, x);
+}
+const or_circuit_t *
+CONST_TO_OR_CIRCUIT(const circuit_t *x)
+{
+ tor_assert(x->magic == OR_CIRCUIT_MAGIC);
+ return DOWNCAST(or_circuit_t, x);
+}
+origin_circuit_t *
+TO_ORIGIN_CIRCUIT(circuit_t *x)
+{
+ tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC);
+ return DOWNCAST(origin_circuit_t, x);
+}
+const origin_circuit_t *
+CONST_TO_ORIGIN_CIRCUIT(const circuit_t *x)
+{
+ tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC);
+ return DOWNCAST(origin_circuit_t, x);
+}
+
/** A map from channel and circuit ID to circuit. (Lookup performance is
* very important here, since we need to do it every time a cell arrives.) */
typedef struct chan_circid_circuit_map_t {
@@ -966,9 +1003,9 @@ origin_circuit_new(void)
}
log_info(LD_CIRC,
- "Circuit " U64_FORMAT " chose an idle timeout of %d based on "
+ "Circuit %"PRIu32" chose an idle timeout of %d based on "
"%d seconds of predictive building remaining.",
- U64_PRINTF_ARG(circ->global_identifier),
+ (circ->global_identifier),
circ->circuit_idle_timeout,
prediction_time_remaining);
}
@@ -1355,9 +1392,9 @@ circuit_get_by_circid_channel_impl(circid_t circ_id, channel_t *chan,
if (found && found->circuit) {
log_debug(LD_CIRC,
"circuit_get_by_circid_channel_impl() returning circuit %p for"
- " circ_id %u, channel ID " U64_FORMAT " (%p)",
+ " circ_id %u, channel ID %"PRIu64 " (%p)",
found->circuit, (unsigned)circ_id,
- U64_PRINTF_ARG(chan->global_identifier), chan);
+ (chan->global_identifier), chan);
if (found_entry_out)
*found_entry_out = 1;
return found->circuit;
@@ -1365,10 +1402,10 @@ circuit_get_by_circid_channel_impl(circid_t circ_id, channel_t *chan,
log_debug(LD_CIRC,
"circuit_get_by_circid_channel_impl() found %s for"
- " circ_id %u, channel ID " U64_FORMAT " (%p)",
+ " circ_id %u, channel ID %"PRIu64 " (%p)",
found ? "placeholder" : "nothing",
(unsigned)circ_id,
- U64_PRINTF_ARG(chan->global_identifier), chan);
+ (chan->global_identifier), chan);
if (found_entry_out)
*found_entry_out = found ? 1 : 0;
@@ -2567,10 +2604,10 @@ circuits_handle_oom(size_t current_allocation)
done_recovering_mem:
- log_notice(LD_GENERAL, "Removed "U64_FORMAT" bytes by killing %d circuits; "
+ log_notice(LD_GENERAL, "Removed %"TOR_PRIuSZ" bytes by killing %d circuits; "
"%d circuits remain alive. Also killed %d non-linked directory "
"connections.",
- U64_PRINTF_ARG(mem_recovered),
+ mem_recovered,
n_circuits_killed,
smartlist_len(circlist) - n_circuits_killed,
n_dirconns_killed);
@@ -2703,4 +2740,3 @@ assert_circuit_ok,(const circuit_t *c))
tor_assert(!or_circ || !or_circ->rend_splice);
}
}
-
diff --git a/src/core/or/circuitlist.h b/src/core/or/circuitlist.h
new file mode 100644
index 0000000000..b069604a1e
--- /dev/null
+++ b/src/core/or/circuitlist.h
@@ -0,0 +1,247 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file circuitlist.h
+ * \brief Header file for circuitlist.c.
+ **/
+
+#ifndef TOR_CIRCUITLIST_H
+#define TOR_CIRCUITLIST_H
+
+#include "lib/testsupport/testsupport.h"
+#include "feature/hs/hs_ident.h"
+
+/** Circuit state: I'm the origin, still haven't done all my handshakes. */
+#define CIRCUIT_STATE_BUILDING 0
+/** Circuit state: Waiting to process the onionskin. */
+#define CIRCUIT_STATE_ONIONSKIN_PENDING 1
+/** Circuit state: I'd like to deliver a create, but my n_chan is still
+ * connecting. */
+#define CIRCUIT_STATE_CHAN_WAIT 2
+/** Circuit state: the circuit is open but we don't want to actually use it
+ * until we find out if a better guard will be available.
+ */
+#define CIRCUIT_STATE_GUARD_WAIT 3
+/** Circuit state: onionskin(s) processed, ready to send/receive cells. */
+#define CIRCUIT_STATE_OPEN 4
+
+#define CIRCUIT_PURPOSE_MIN_ 1
+
+/* these circuits were initiated elsewhere */
+#define CIRCUIT_PURPOSE_OR_MIN_ 1
+/** OR-side circuit purpose: normal circuit, at OR. */
+#define CIRCUIT_PURPOSE_OR 1
+/** OR-side circuit purpose: At OR, from the service, waiting for intro from
+ * clients. */
+#define CIRCUIT_PURPOSE_INTRO_POINT 2
+/** OR-side circuit purpose: At OR, from the client, waiting for the service.
+ */
+#define CIRCUIT_PURPOSE_REND_POINT_WAITING 3
+/** OR-side circuit purpose: At OR, both circuits have this purpose. */
+#define CIRCUIT_PURPOSE_REND_ESTABLISHED 4
+#define CIRCUIT_PURPOSE_OR_MAX_ 4
+
+/* these circuits originate at this node */
+
+/* here's how circ client-side purposes work:
+ * normal circuits are C_GENERAL.
+ * circuits that are c_introducing are either on their way to
+ * becoming open, or they are open and waiting for a
+ * suitable rendcirc before they send the intro.
+ * circuits that are c_introduce_ack_wait have sent the intro,
+ * but haven't gotten a response yet.
+ * circuits that are c_establish_rend are either on their way
+ * to becoming open, or they are open and have sent the
+ * establish_rendezvous cell but haven't received an ack.
+ * circuits that are c_rend_ready are open and have received a
+ * rend ack, but haven't heard from the service yet. if they have a
+ * buildstate->pending_final_cpath then they're expecting a
+ * cell from the service, else they're not.
+ * circuits that are c_rend_ready_intro_acked are open, and
+ * some intro circ has sent its intro and received an ack.
+ * circuits that are c_rend_joined are open, have heard from
+ * the service, and are talking to it.
+ */
+/** Client-side circuit purpose: Normal circuit, with cpath. */
+#define CIRCUIT_PURPOSE_C_GENERAL 5
+#define CIRCUIT_PURPOSE_C_HS_MIN_ 6
+/** Client-side circuit purpose: at the client, connecting to intro point. */
+#define CIRCUIT_PURPOSE_C_INTRODUCING 6
+/** Client-side circuit purpose: at the client, sent INTRODUCE1 to intro point,
+ * waiting for ACK/NAK. */
+#define CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT 7
+/** Client-side circuit purpose: at the client, introduced and acked, closing.
+ */
+#define CIRCUIT_PURPOSE_C_INTRODUCE_ACKED 8
+/** Client-side circuit purpose: at the client, waiting for ack. */
+#define CIRCUIT_PURPOSE_C_ESTABLISH_REND 9
+/** Client-side circuit purpose: at the client, waiting for the service. */
+#define CIRCUIT_PURPOSE_C_REND_READY 10
+/** Client-side circuit purpose: at the client, waiting for the service,
+ * INTRODUCE has been acknowledged. */
+#define CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED 11
+/** Client-side circuit purpose: at the client, rendezvous established. */
+#define CIRCUIT_PURPOSE_C_REND_JOINED 12
+/** This circuit is used for getting hsdirs */
+#define CIRCUIT_PURPOSE_C_HSDIR_GET 13
+#define CIRCUIT_PURPOSE_C_HS_MAX_ 13
+/** This circuit is used for build time measurement only */
+#define CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT 14
+#define CIRCUIT_PURPOSE_C_MAX_ 14
+
+#define CIRCUIT_PURPOSE_S_HS_MIN_ 15
+/** Hidden-service-side circuit purpose: at the service, waiting for
+ * introductions. */
+#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO 15
+/** Hidden-service-side circuit purpose: at the service, successfully
+ * established intro. */
+#define CIRCUIT_PURPOSE_S_INTRO 16
+/** Hidden-service-side circuit purpose: at the service, connecting to rend
+ * point. */
+#define CIRCUIT_PURPOSE_S_CONNECT_REND 17
+/** Hidden-service-side circuit purpose: at the service, rendezvous
+ * established. */
+#define CIRCUIT_PURPOSE_S_REND_JOINED 18
+/** This circuit is used for uploading hsdirs */
+#define CIRCUIT_PURPOSE_S_HSDIR_POST 19
+#define CIRCUIT_PURPOSE_S_HS_MAX_ 19
+
+/** A testing circuit; not meant to be used for actual traffic. */
+#define CIRCUIT_PURPOSE_TESTING 20
+/** A controller made this circuit and Tor should not use it. */
+#define CIRCUIT_PURPOSE_CONTROLLER 21
+/** This circuit is used for path bias probing only */
+#define CIRCUIT_PURPOSE_PATH_BIAS_TESTING 22
+
+/** This circuit is used for vanguards/restricted paths.
+ *
+ * This type of circuit is *only* created preemptively and never
+ * on-demand. When an HS operation needs to take place (e.g. connect to an
+ * intro point), these circuits are then cannibalized and repurposed to the
+ * actual needed HS purpose. */
+#define CIRCUIT_PURPOSE_HS_VANGUARDS 23
+
+#define CIRCUIT_PURPOSE_MAX_ 23
+/** A catch-all for unrecognized purposes. Currently we don't expect
+ * to make or see any circuits with this purpose. */
+#define CIRCUIT_PURPOSE_UNKNOWN 255
+
+/** True iff the circuit purpose <b>p</b> is for a circuit that
+ * originated at this node. */
+#define CIRCUIT_PURPOSE_IS_ORIGIN(p) ((p)>CIRCUIT_PURPOSE_OR_MAX_)
+/** True iff the circuit purpose <b>p</b> is for a circuit that originated
+ * here to serve as a client. (Hidden services don't count here.) */
+#define CIRCUIT_PURPOSE_IS_CLIENT(p) \
+ ((p)> CIRCUIT_PURPOSE_OR_MAX_ && \
+ (p)<=CIRCUIT_PURPOSE_C_MAX_)
+/** True iff the circuit_t <b>c</b> is actually an origin_circuit_t. */
+#define CIRCUIT_IS_ORIGIN(c) (CIRCUIT_PURPOSE_IS_ORIGIN((c)->purpose))
+/** True iff the circuit purpose <b>p</b> is for an established rendezvous
+ * circuit. */
+#define CIRCUIT_PURPOSE_IS_ESTABLISHED_REND(p) \
+ ((p) == CIRCUIT_PURPOSE_C_REND_JOINED || \
+ (p) == CIRCUIT_PURPOSE_S_REND_JOINED)
+/** True iff the circuit_t c is actually an or_circuit_t */
+#define CIRCUIT_IS_ORCIRC(c) (((circuit_t *)(c))->magic == OR_CIRCUIT_MAGIC)
+
+/** True iff this circuit purpose should count towards the global
+ * pending rate limit (set by MaxClientCircuitsPending). We count all
+ * general purpose circuits, as well as the first step of client onion
+ * service connections (HSDir gets). */
+#define CIRCUIT_PURPOSE_COUNTS_TOWARDS_MAXPENDING(p) \
+ ((p) == CIRCUIT_PURPOSE_C_GENERAL || \
+ (p) == CIRCUIT_PURPOSE_C_HSDIR_GET)
+
+/** Convert a circuit_t* to a pointer to the enclosing or_circuit_t. Assert
+ * if the cast is impossible. */
+or_circuit_t *TO_OR_CIRCUIT(circuit_t *);
+const or_circuit_t *CONST_TO_OR_CIRCUIT(const circuit_t *);
+/** Convert a circuit_t* to a pointer to the enclosing origin_circuit_t.
+ * Assert if the cast is impossible. */
+origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *);
+const origin_circuit_t *CONST_TO_ORIGIN_CIRCUIT(const circuit_t *);
+
+MOCK_DECL(smartlist_t *, circuit_get_global_list, (void));
+smartlist_t *circuit_get_global_origin_circuit_list(void);
+int circuit_any_opened_circuits(void);
+int circuit_any_opened_circuits_cached(void);
+void circuit_cache_opened_circuit_state(int circuits_are_opened);
+
+const char *circuit_state_to_string(int state);
+const char *circuit_purpose_to_controller_string(uint8_t purpose);
+const char *circuit_purpose_to_controller_hs_state_string(uint8_t purpose);
+const char *circuit_purpose_to_string(uint8_t purpose);
+void circuit_dump_by_conn(connection_t *conn, int severity);
+void circuit_set_p_circid_chan(or_circuit_t *circ, circid_t id,
+ channel_t *chan);
+void circuit_set_n_circid_chan(circuit_t *circ, circid_t id,
+ channel_t *chan);
+void channel_mark_circid_unusable(channel_t *chan, circid_t id);
+void channel_mark_circid_usable(channel_t *chan, circid_t id);
+time_t circuit_id_when_marked_unusable_on_channel(circid_t circ_id,
+ channel_t *chan);
+void circuit_set_state(circuit_t *circ, uint8_t state);
+void circuit_close_all_marked(void);
+int32_t circuit_initial_package_window(void);
+origin_circuit_t *origin_circuit_new(void);
+or_circuit_t *or_circuit_new(circid_t p_circ_id, channel_t *p_chan);
+circuit_t *circuit_get_by_circid_channel(circid_t circ_id,
+ channel_t *chan);
+circuit_t *
+circuit_get_by_circid_channel_even_if_marked(circid_t circ_id,
+ channel_t *chan);
+int circuit_id_in_use_on_channel(circid_t circ_id, channel_t *chan);
+circuit_t *circuit_get_by_edge_conn(edge_connection_t *conn);
+void circuit_unlink_all_from_channel(channel_t *chan, int reason);
+origin_circuit_t *circuit_get_by_global_id(uint32_t id);
+origin_circuit_t *circuit_get_ready_rend_circ_by_rend_data(
+ const rend_data_t *rend_data);
+origin_circuit_t *circuit_get_next_by_pk_and_purpose(origin_circuit_t *start,
+ const uint8_t *digest, uint8_t purpose);
+origin_circuit_t *circuit_get_next_service_intro_circ(origin_circuit_t *start);
+origin_circuit_t *circuit_get_next_service_rp_circ(origin_circuit_t *start);
+origin_circuit_t *circuit_get_next_service_hsdir_circ(origin_circuit_t *start);
+origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose,
+ extend_info_t *info, int flags);
+void circuit_mark_all_unused_circs(void);
+void circuit_mark_all_dirty_circs_as_unusable(void);
+MOCK_DECL(void, circuit_mark_for_close_, (circuit_t *circ, int reason,
+ int line, const char *file));
+int circuit_get_cpath_len(origin_circuit_t *circ);
+int circuit_get_cpath_opened_len(const origin_circuit_t *);
+void circuit_clear_cpath(origin_circuit_t *circ);
+crypt_path_t *circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum);
+void circuit_get_all_pending_on_channel(smartlist_t *out,
+ channel_t *chan);
+int circuit_count_pending_on_channel(channel_t *chan);
+
+#define circuit_mark_for_close(c, reason) \
+ circuit_mark_for_close_((c), (reason), __LINE__, SHORT_FILE__)
+
+void assert_cpath_layer_ok(const crypt_path_t *cp);
+MOCK_DECL(void, assert_circuit_ok,(const circuit_t *c));
+void circuit_free_all(void);
+void circuits_handle_oom(size_t current_allocation);
+
+void circuit_clear_testing_cell_stats(circuit_t *circ);
+
+void channel_note_destroy_pending(channel_t *chan, circid_t id);
+MOCK_DECL(void, channel_note_destroy_not_pending,
+ (channel_t *chan, circid_t id));
+
+smartlist_t *circuit_find_circuits_to_upgrade_from_guard_wait(void);
+
+#ifdef CIRCUITLIST_PRIVATE
+STATIC void circuit_free_(circuit_t *circ);
+#define circuit_free(circ) FREE_AND_NULL(circuit_t, circuit_free_, (circ))
+STATIC size_t n_cells_in_circ_queues(const circuit_t *c);
+STATIC uint32_t circuit_max_queued_data_age(const circuit_t *c, uint32_t now);
+STATIC uint32_t circuit_max_queued_cell_age(const circuit_t *c, uint32_t now);
+STATIC uint32_t circuit_max_queued_item_age(const circuit_t *c, uint32_t now);
+#endif /* defined(CIRCUITLIST_PRIVATE) */
+
+#endif /* !defined(TOR_CIRCUITLIST_H) */
diff --git a/src/or/circuitmux.c b/src/core/or/circuitmux.c
index f9f5faa057..f55386df23 100644
--- a/src/or/circuitmux.c
+++ b/src/core/or/circuitmux.c
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -69,11 +69,15 @@
* made to attach all existing circuits to the new policy.
**/
-#include "or.h"
-#include "channel.h"
-#include "circuitlist.h"
-#include "circuitmux.h"
-#include "relay.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuitmux.h"
+#include "core/or/relay.h"
+
+#include "core/or/cell_queue_st.h"
+#include "core/or/destroy_cell_queue_st.h"
+#include "core/or/or_circuit_st.h"
/*
* Private typedefs for circuitmux.c
@@ -316,10 +320,10 @@ circuitmux_detach_all_circuits(circuitmux_t *cmux, smartlist_t *detached_out)
} else {
/* Complain and move on */
log_warn(LD_CIRC,
- "Circuit %u/channel " U64_FORMAT " had direction == "
+ "Circuit %u/channel %"PRIu64 " had direction == "
"CELL_DIRECTION_IN, but isn't an or_circuit_t",
(unsigned)to_remove->circ_id,
- U64_PRINTF_ARG(to_remove->chan_id));
+ (to_remove->chan_id));
}
/* Free policy-specific data if we have it */
@@ -340,15 +344,15 @@ circuitmux_detach_all_circuits(circuitmux_t *cmux, smartlist_t *detached_out)
} else {
/* Complain and move on */
log_warn(LD_CIRC,
- "Couldn't find circuit %u (for channel " U64_FORMAT ")",
+ "Couldn't find circuit %u (for channel %"PRIu64 ")",
(unsigned)to_remove->circ_id,
- U64_PRINTF_ARG(to_remove->chan_id));
+ (to_remove->chan_id));
}
} else {
/* Complain and move on */
log_warn(LD_CIRC,
- "Couldn't find channel " U64_FORMAT " (for circuit id %u)",
- U64_PRINTF_ARG(to_remove->chan_id),
+ "Couldn't find channel %"PRIu64 " (for circuit id %u)",
+ (to_remove->chan_id),
(unsigned)to_remove->circ_id);
}
@@ -424,17 +428,17 @@ circuitmux_free_(circuitmux_t *cmux)
global_destroy_ctr -= cmux->destroy_cell_queue.n;
log_debug(LD_CIRC,
"Freeing cmux at %p with %u queued destroys; the last cmux "
- "destroy balance was "I64_FORMAT", global is "I64_FORMAT,
+ "destroy balance was %"PRId64", global is %"PRId64,
cmux, cmux->destroy_cell_queue.n,
- I64_PRINTF_ARG(cmux->destroy_ctr),
- I64_PRINTF_ARG(global_destroy_ctr));
+ (cmux->destroy_ctr),
+ (global_destroy_ctr));
} else {
log_debug(LD_CIRC,
"Freeing cmux at %p with no queued destroys, the cmux destroy "
- "balance was "I64_FORMAT", global is "I64_FORMAT,
+ "balance was %"PRId64", global is %"PRId64,
cmux,
- I64_PRINTF_ARG(cmux->destroy_ctr),
- I64_PRINTF_ARG(global_destroy_ctr));
+ (cmux->destroy_ctr),
+ (global_destroy_ctr));
}
destroy_cell_queue_clear(&cmux->destroy_cell_queue);
@@ -831,9 +835,9 @@ circuitmux_attach_circuit,(circuitmux_t *cmux, circuit_t *circ,
* directions match and update the cell count and active circuit count.
*/
log_info(LD_CIRC,
- "Circuit %u on channel " U64_FORMAT " was already attached to "
+ "Circuit %u on channel %"PRIu64 " was already attached to "
"cmux %p (trying to attach to %p)",
- (unsigned)circ_id, U64_PRINTF_ARG(channel_id),
+ (unsigned)circ_id, (channel_id),
((direction == CELL_DIRECTION_OUT) ?
circ->n_mux : TO_OR_CIRCUIT(circ)->p_mux),
cmux);
@@ -865,8 +869,8 @@ circuitmux_attach_circuit,(circuitmux_t *cmux, circuit_t *circ,
* counts.
*/
log_debug(LD_CIRC,
- "Attaching circuit %u on channel " U64_FORMAT " to cmux %p",
- (unsigned)circ_id, U64_PRINTF_ARG(channel_id), cmux);
+ "Attaching circuit %u on channel %"PRIu64 " to cmux %p",
+ (unsigned)circ_id, (channel_id), cmux);
/*
* Assert that the circuit doesn't already have a mux for this
@@ -1237,11 +1241,11 @@ circuitmux_notify_xmit_destroy(circuitmux_t *cmux)
--(cmux->destroy_ctr);
--(global_destroy_ctr);
log_debug(LD_CIRC,
- "Cmux at %p sent a destroy, cmux counter is now "I64_FORMAT", "
- "global counter is now "I64_FORMAT,
+ "Cmux at %p sent a destroy, cmux counter is now %"PRId64", "
+ "global counter is now %"PRId64,
cmux,
- I64_PRINTF_ARG(cmux->destroy_ctr),
- I64_PRINTF_ARG(global_destroy_ctr));
+ (cmux->destroy_ctr),
+ (global_destroy_ctr));
}
/*DOCDOC */
@@ -1258,10 +1262,10 @@ circuitmux_append_destroy_cell(channel_t *chan,
++global_destroy_ctr;
log_debug(LD_CIRC,
"Cmux at %p queued a destroy for circ %u, cmux counter is now "
- I64_FORMAT", global counter is now "I64_FORMAT,
+ "%"PRId64", global counter is now %"PRId64,
cmux, circ_id,
- I64_PRINTF_ARG(cmux->destroy_ctr),
- I64_PRINTF_ARG(global_destroy_ctr));
+ (cmux->destroy_ctr),
+ (global_destroy_ctr));
/* XXXX Duplicate code from append_cell_to_circuit_queue */
if (!channel_has_queued_writes(chan)) {
@@ -1299,12 +1303,12 @@ circuitmux_count_queued_destroy_cells(const channel_t *chan,
n_destroy_cells != manual_total ||
n_destroy_cells != manual_total_in_map) {
log_warn(LD_BUG, " Discrepancy in counts for queued destroy cells on "
- "circuitmux. n="I64_FORMAT". queue_size="I64_FORMAT". "
- "manual_total="I64_FORMAT". manual_total_in_map="I64_FORMAT".",
- I64_PRINTF_ARG(n_destroy_cells),
- I64_PRINTF_ARG(destroy_queue_size),
- I64_PRINTF_ARG(manual_total),
- I64_PRINTF_ARG(manual_total_in_map));
+ "circuitmux. n=%"PRId64". queue_size=%"PRId64". "
+ "manual_total=%"PRId64". manual_total_in_map=%"PRId64".",
+ (n_destroy_cells),
+ (destroy_queue_size),
+ (manual_total),
+ (manual_total_in_map));
}
return n_destroy_cells;
diff --git a/src/or/circuitmux.h b/src/core/or/circuitmux.h
index 336e128c76..31bf81463b 100644
--- a/src/or/circuitmux.h
+++ b/src/core/or/circuitmux.h
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,8 +9,8 @@
#ifndef TOR_CIRCUITMUX_H
#define TOR_CIRCUITMUX_H
-#include "or.h"
-#include "testsupport.h"
+#include "core/or/or.h"
+#include "lib/testsupport/testsupport.h"
typedef struct circuitmux_policy_s circuitmux_policy_t;
typedef struct circuitmux_policy_data_s circuitmux_policy_data_t;
diff --git a/src/or/circuitmux_ewma.c b/src/core/or/circuitmux_ewma.c
index e5d5a14581..deca81f0ac 100644
--- a/src/or/circuitmux_ewma.c
+++ b/src/core/or/circuitmux_ewma.c
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -34,11 +34,12 @@
#include <math.h>
-#include "or.h"
-#include "circuitmux.h"
-#include "circuitmux_ewma.h"
-#include "crypto_rand.h"
-#include "networkstatus.h"
+#include "core/or/or.h"
+#include "core/or/circuitmux.h"
+#include "core/or/circuitmux_ewma.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/nodelist/networkstatus.h"
+#include "app/config/or_options_st.h"
/*** EWMA parameter #defines ***/
@@ -826,4 +827,3 @@ circuitmux_ewma_free_all(void)
{
ewma_ticks_initialized = 0;
}
-
diff --git a/src/or/circuitmux_ewma.h b/src/core/or/circuitmux_ewma.h
index f0c4c36095..8e87830a80 100644
--- a/src/or/circuitmux_ewma.h
+++ b/src/core/or/circuitmux_ewma.h
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,8 +9,8 @@
#ifndef TOR_CIRCUITMUX_EWMA_H
#define TOR_CIRCUITMUX_EWMA_H
-#include "or.h"
-#include "circuitmux.h"
+#include "core/or/or.h"
+#include "core/or/circuitmux.h"
/* The public EWMA policy callbacks object. */
extern circuitmux_policy_t ewma_policy;
diff --git a/src/or/circuitstats.c b/src/core/or/circuitstats.c
index 94f75c590f..63cd21540d 100644
--- a/src/or/circuitstats.c
+++ b/src/core/or/circuitstats.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -25,21 +25,28 @@
#define CIRCUITSTATS_PRIVATE
-#include "or.h"
-#include "circuitbuild.h"
-#include "circuitstats.h"
-#include "config.h"
-#include "confparse.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "main.h"
-#include "networkstatus.h"
-#include "rendclient.h"
-#include "rendservice.h"
-#include "router.h"
-#include "statefile.h"
-#include "circuitlist.h"
-#include "circuituse.h"
+#include "core/or/or.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitstats.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/rend/rendclient.h"
+#include "feature/rend/rendservice.h"
+#include "feature/relay/router.h"
+#include "app/config/statefile.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "lib/math/fp.h"
+#include "lib/time/tvdiff.h"
+#include "lib/encoding/confline.h"
+
+#include "core/or/crypt_path_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "app/config/or_state_st.h"
#undef log
#include <math.h>
@@ -706,8 +713,8 @@ circuit_build_times_handle_completed_hop(origin_circuit_t *circ)
* Switch their purpose and wait. */
if (circ->base_.purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) {
log_info(LD_CIRC,
- "Deciding to timeout circuit "U64_FORMAT"\n",
- U64_PRINTF_ARG(circ->global_identifier));
+ "Deciding to timeout circuit %"PRIu32"\n",
+ (circ->global_identifier));
circuit_build_times_mark_circ_as_measurement_only(circ);
}
}
@@ -1943,4 +1950,3 @@ cbt_control_event_buildtimeout_set(const circuit_build_times_t *cbt,
tor_free(args);
}
-
diff --git a/src/or/circuitstats.h b/src/core/or/circuitstats.h
index 86116cb7f8..174730d035 100644
--- a/src/or/circuitstats.h
+++ b/src/core/or/circuitstats.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -21,6 +21,9 @@ int circuit_build_times_disabled(const or_options_t *options);
int circuit_build_times_disabled_(const or_options_t *options,
int ignore_consensus);
+/** A build_time_t is milliseconds */
+typedef uint32_t build_time_t;
+
int circuit_build_times_enough_to_compute(const circuit_build_times_t *cbt);
void circuit_build_times_update_state(const circuit_build_times_t *cbt,
or_state_t *state);
@@ -47,6 +50,89 @@ 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);
+/** Total size of the circuit timeout history to accumulate.
+ * 1000 is approx 2.5 days worth of continual-use circuits. */
+#define CBT_NCIRCUITS_TO_OBSERVE 1000
+
+/** Width of the histogram bins in milliseconds */
+#define CBT_BIN_WIDTH ((build_time_t)50)
+
+/** Number of modes to use in the weighted-avg computation of Xm */
+#define CBT_DEFAULT_NUM_XM_MODES 3
+#define CBT_MIN_NUM_XM_MODES 1
+#define CBT_MAX_NUM_XM_MODES 20
+
+/**
+ * CBT_BUILD_ABANDONED is our flag value to represent a force-closed
+ * circuit (Aka a 'right-censored' pareto value).
+ */
+#define CBT_BUILD_ABANDONED ((build_time_t)(INT32_MAX-1))
+#define CBT_BUILD_TIME_MAX ((build_time_t)(INT32_MAX))
+
+/** Save state every 10 circuits */
+#define CBT_SAVE_STATE_EVERY 10
+
+/* Circuit build times consensus parameters */
+
+/**
+ * How long to wait before actually closing circuits that take too long to
+ * build in terms of CDF quantile.
+ */
+#define CBT_DEFAULT_CLOSE_QUANTILE 95
+#define CBT_MIN_CLOSE_QUANTILE CBT_MIN_QUANTILE_CUTOFF
+#define CBT_MAX_CLOSE_QUANTILE CBT_MAX_QUANTILE_CUTOFF
+
+/**
+ * How many circuits count as recent when considering if the
+ * connection has gone gimpy or changed.
+ */
+#define CBT_DEFAULT_RECENT_CIRCUITS 20
+#define CBT_MIN_RECENT_CIRCUITS 3
+#define CBT_MAX_RECENT_CIRCUITS 1000
+
+/**
+ * Maximum count of timeouts that finish the first hop in the past
+ * RECENT_CIRCUITS before calculating a new timeout.
+ *
+ * This tells us whether to abandon timeout history and set
+ * the timeout back to whatever circuit_build_times_get_initial_timeout()
+ * gives us.
+ */
+#define CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT (CBT_DEFAULT_RECENT_CIRCUITS*9/10)
+#define CBT_MIN_MAX_RECENT_TIMEOUT_COUNT 3
+#define CBT_MAX_MAX_RECENT_TIMEOUT_COUNT 10000
+
+/** Minimum circuits before estimating a timeout */
+#define CBT_DEFAULT_MIN_CIRCUITS_TO_OBSERVE 100
+#define CBT_MIN_MIN_CIRCUITS_TO_OBSERVE 1
+#define CBT_MAX_MIN_CIRCUITS_TO_OBSERVE 10000
+
+/** Cutoff percentile on the CDF for our timeout estimation. */
+#define CBT_DEFAULT_QUANTILE_CUTOFF 80
+#define CBT_MIN_QUANTILE_CUTOFF 10
+#define CBT_MAX_QUANTILE_CUTOFF 99
+double circuit_build_times_quantile_cutoff(void);
+
+/** How often in seconds should we build a test circuit */
+#define CBT_DEFAULT_TEST_FREQUENCY 10
+#define CBT_MIN_TEST_FREQUENCY 1
+#define CBT_MAX_TEST_FREQUENCY INT32_MAX
+
+/** Lowest allowable value for CircuitBuildTimeout in milliseconds */
+#define CBT_DEFAULT_TIMEOUT_MIN_VALUE (1500)
+#define CBT_MIN_TIMEOUT_MIN_VALUE 500
+#define CBT_MAX_TIMEOUT_MIN_VALUE INT32_MAX
+
+/** Initial circuit build timeout in milliseconds */
+#define CBT_DEFAULT_TIMEOUT_INITIAL_VALUE (60*1000)
+#define CBT_MIN_TIMEOUT_INITIAL_VALUE CBT_MIN_TIMEOUT_MIN_VALUE
+#define CBT_MAX_TIMEOUT_INITIAL_VALUE INT32_MAX
+int32_t circuit_build_times_initial_timeout(void);
+
+#if CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT < CBT_MIN_MAX_RECENT_TIMEOUT_COUNT
+#error "RECENT_CIRCUITS is set too low."
+#endif
+
#ifdef CIRCUITSTATS_PRIVATE
STATIC double circuit_build_times_calculate_timeout(circuit_build_times_t *cbt,
double quantile);
@@ -73,6 +159,21 @@ 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 */
+ time_t network_last_live;
+ /** If the network is not live, how many timeouts has this caused? */
+ int nonlive_timeouts;
+ /** Circular array of circuits that have made it to the first hop. Slot is
+ * 1 if circuit timed out, 0 if circuit succeeded */
+ int8_t *timeouts_after_firsthop;
+ /** Number of elements allocated for the above array */
+ int num_recent_circs;
+ /** Index into circular array. */
+ int after_firsthop_idx;
+} network_liveness_t;
+
/** Structure for circuit build times history */
struct circuit_build_times_s {
/** The circular array of recorded build times in milliseconds */
@@ -110,4 +211,3 @@ struct circuit_build_times_s {
#endif /* defined(CIRCUITSTATS_PRIVATE) */
#endif /* !defined(TOR_CIRCUITSTATS_H) */
-
diff --git a/src/or/circuituse.c b/src/core/or/circuituse.c
index 8e007ce920..a3b9eb1713 100644
--- a/src/or/circuituse.c
+++ b/src/core/or/circuituse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -27,34 +27,45 @@
* logic in circuitstats.c.
**/
-#include "or.h"
-#include "addressmap.h"
-#include "bridges.h"
-#include "channel.h"
-#include "circpathbias.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuitstats.h"
-#include "circuituse.h"
-#include "config.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "control.h"
-#include "entrynodes.h"
-#include "hs_common.h"
-#include "hs_client.h"
-#include "hs_circuit.h"
-#include "hs_ident.h"
-#include "hs_stats.h"
-#include "nodelist.h"
-#include "networkstatus.h"
-#include "policies.h"
-#include "rendclient.h"
-#include "rendcommon.h"
-#include "rendservice.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerlist.h"
+#include "core/or/or.h"
+#include "feature/client/addressmap.h"
+#include "feature/client/bridges.h"
+#include "core/or/channel.h"
+#include "feature/client/circpathbias.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuitstats.h"
+#include "core/or/circuituse.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "feature/control/control.h"
+#include "feature/dircache/directory.h"
+#include "feature/client/entrynodes.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_client.h"
+#include "feature/hs/hs_circuit.h"
+#include "feature/hs/hs_ident.h"
+#include "feature/hs/hs_stats.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/networkstatus.h"
+#include "core/or/policies.h"
+#include "feature/rend/rendclient.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/rend/rendservice.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "lib/math/fp.h"
+#include "lib/time/tvdiff.h"
+
+#include "core/or/cpath_build_state_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "core/or/entry_connection_st.h"
+#include "core/or/extend_info_st.h"
+#include "core/or/or_circuit_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "core/or/socks_request_st.h"
static void circuit_expire_old_circuits_clientside(void);
static void circuit_increment_failure_count(void);
@@ -708,9 +719,8 @@ circuit_expire_building(void)
circuit_build_times_enough_to_compute(get_circuit_build_times())) {
log_info(LD_CIRC,
- "Deciding to count the timeout for circuit "U64_FORMAT"\n",
- U64_PRINTF_ARG(
- TO_ORIGIN_CIRCUIT(victim)->global_identifier));
+ "Deciding to count the timeout for circuit %"PRIu32"\n",
+ TO_ORIGIN_CIRCUIT(victim)->global_identifier);
/* Circuits are allowed to last longer for measurement.
* Switch their purpose and wait. */
@@ -1499,10 +1509,10 @@ circuit_expire_old_circuits_clientside(void)
circ->purpose <= CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) ||
circ->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND) {
log_info(LD_CIRC,
- "Closing circuit "U64_FORMAT
+ "Closing circuit %"PRIu32
" that has been unused for %ld msec.",
- U64_PRINTF_ARG(TO_ORIGIN_CIRCUIT(circ)->global_identifier),
- tv_mdiff(&circ->timestamp_began, &now));
+ TO_ORIGIN_CIRCUIT(circ)->global_identifier,
+ tv_mdiff(&circ->timestamp_began, &now));
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
@@ -3143,4 +3153,3 @@ circuit_read_valid_data(origin_circuit_t *circ, uint16_t relay_body_len)
tor_add_u32_nowrap(circ->n_overhead_read_circ_bw,
RELAY_PAYLOAD_SIZE-relay_body_len);
}
-
diff --git a/src/or/circuituse.h b/src/core/or/circuituse.h
index 6458bd6908..b65e85d170 100644
--- a/src/or/circuituse.h
+++ b/src/core/or/circuituse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/or/command.c b/src/core/or/command.c
index 39950f41bf..461e49b629 100644
--- a/src/or/command.c
+++ b/src/core/or/command.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -36,25 +36,30 @@
* callbacks registered in command_setup_channel(),
* called when channels are created in circuitbuild.c
*/
-#include "or.h"
-#include "channel.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "command.h"
-#include "connection.h"
-#include "connection_or.h"
-#include "config.h"
-#include "control.h"
-#include "cpuworker.h"
-#include "crypto_util.h"
-#include "dos.h"
-#include "hibernate.h"
-#include "nodelist.h"
-#include "onion.h"
-#include "rephist.h"
-#include "relay.h"
-#include "router.h"
-#include "routerlist.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/command.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_or.h"
+#include "app/config/config.h"
+#include "feature/control/control.h"
+#include "core/mainloop/cpuworker.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "core/or/dos.h"
+#include "feature/hibernate/hibernate.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/crypto/onion.h"
+#include "feature/stats/rephist.h"
+#include "core/or/relay.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/or_circuit_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "core/or/var_cell_st.h"
/** How many CELL_CREATE cells have we received, ever? */
uint64_t stats_n_create_cells_processed = 0;
@@ -244,10 +249,10 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
tor_assert(chan);
log_debug(LD_OR,
- "Got a CREATE cell for circ_id %u on channel " U64_FORMAT
+ "Got a CREATE cell for circ_id %u on channel %"PRIu64
" (%p)",
(unsigned)cell->circ_id,
- U64_PRINTF_ARG(chan->global_identifier), chan);
+ (chan->global_identifier), chan);
/* First thing we do, even though the cell might be invalid, is inform the
* DoS mitigation subsystem layer of this event. Validation is done by this
diff --git a/src/or/command.h b/src/core/or/command.h
index c0d1996cbb..83ffd8dccd 100644
--- a/src/or/command.h
+++ b/src/core/or/command.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,7 @@
#ifndef TOR_COMMAND_H
#define TOR_COMMAND_H
-#include "channel.h"
+#include "core/or/channel.h"
void command_process_cell(channel_t *chan, cell_t *cell);
void command_process_var_cell(channel_t *chan, var_cell_t *cell);
diff --git a/src/or/connection_edge.c b/src/core/or/connection_edge.c
index 046369af60..8e8a5e21ca 100644
--- a/src/or/connection_edge.c
+++ b/src/core/or/connection_edge.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -55,47 +55,58 @@
**/
#define CONNECTION_EDGE_PRIVATE
-#include "or.h"
-
-#include "backtrace.h"
-
-#include "addressmap.h"
-#include "buffers.h"
-#include "channel.h"
-#include "circpathbias.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "config.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "connection_or.h"
-#include "control.h"
-#include "crypto_util.h"
-#include "dns.h"
-#include "dnsserv.h"
-#include "directory.h"
-#include "dirserv.h"
-#include "hibernate.h"
-#include "hs_common.h"
-#include "hs_cache.h"
-#include "hs_client.h"
-#include "hs_circuit.h"
-#include "main.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "policies.h"
-#include "proto_http.h"
-#include "proto_socks.h"
-#include "reasons.h"
-#include "relay.h"
-#include "rendclient.h"
-#include "rendcommon.h"
-#include "rendservice.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerlist.h"
-#include "routerset.h"
-#include "circuitbuild.h"
+#include "core/or/or.h"
+
+#include "lib/err/backtrace.h"
+
+#include "feature/client/addressmap.h"
+#include "lib/container/buffers.h"
+#include "core/or/channel.h"
+#include "feature/client/circpathbias.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "core/or/connection_or.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/relay/dns.h"
+#include "feature/client/dnsserv.h"
+#include "feature/dircache/directory.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/hibernate/hibernate.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_cache.h"
+#include "feature/hs/hs_client.h"
+#include "feature/hs/hs_circuit.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "core/proto/proto_http.h"
+#include "core/proto/proto_socks.h"
+#include "core/or/reasons.h"
+#include "core/or/relay.h"
+#include "feature/rend/rendclient.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/rend/rendservice.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerset.h"
+#include "core/or/circuitbuild.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/cpath_build_state_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "core/or/entry_connection_st.h"
+#include "core/or/extend_info_st.h"
+#include "feature/nodelist/node_st.h"
+#include "core/or/or_circuit_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "core/or/socks_request_st.h"
+#include "lib/evloop/compat_libevent.h"
#ifdef HAVE_LINUX_TYPES_H
#include <linux/types.h>
@@ -137,6 +148,30 @@ 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. */
+edge_connection_t *
+TO_EDGE_CONN(connection_t *c)
+{
+ tor_assert(c->magic == EDGE_CONNECTION_MAGIC ||
+ c->magic == ENTRY_CONNECTION_MAGIC);
+ return DOWNCAST(edge_connection_t, c);
+}
+
+entry_connection_t *
+TO_ENTRY_CONN(connection_t *c)
+{
+ tor_assert(c->magic == ENTRY_CONNECTION_MAGIC);
+ return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, edge_.base_);
+}
+
+entry_connection_t *
+EDGE_TO_ENTRY_CONN(edge_connection_t *c)
+{
+ tor_assert(c->base_.magic == ENTRY_CONNECTION_MAGIC);
+ return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, edge_);
+}
+
/** 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.
@@ -3165,9 +3200,9 @@ connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply,
!CIRCUIT_IS_ORIGIN(conn->edge_.on_circuit)) {
if (endreason != END_STREAM_REASON_RESOLVEFAILED) {
log_info(LD_BUG,
- "No origin circuit for successful SOCKS stream "U64_FORMAT
+ "No origin circuit for successful SOCKS stream %"PRIu64
". Reason: %d",
- U64_PRINTF_ARG(ENTRY_TO_CONN(conn)->global_identifier),
+ (ENTRY_TO_CONN(conn)->global_identifier),
endreason);
}
/*
@@ -4187,4 +4222,3 @@ connection_edge_free_all(void)
pending_entry_connections = NULL;
mainloop_event_free(attach_pending_entry_connections_ev);
}
-
diff --git a/src/or/connection_edge.h b/src/core/or/connection_edge.h
index c6583d3845..24968b2778 100644
--- a/src/or/connection_edge.h
+++ b/src/core/or/connection_edge.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,9 +12,61 @@
#ifndef TOR_CONNECTION_EDGE_H
#define TOR_CONNECTION_EDGE_H
-#include "testsupport.h"
-
-#define connection_mark_unattached_ap(conn, endreason) \
+#include "lib/testsupport/testsupport.h"
+
+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 *);
+
+#define EXIT_CONN_STATE_MIN_ 1
+/** State for an exit connection: waiting for response from DNS farm. */
+#define EXIT_CONN_STATE_RESOLVING 1
+/** State for an exit connection: waiting for connect() to finish. */
+#define EXIT_CONN_STATE_CONNECTING 2
+/** State for an exit connection: open and ready to transmit data. */
+#define EXIT_CONN_STATE_OPEN 3
+/** State for an exit connection: waiting to be removed. */
+#define EXIT_CONN_STATE_RESOLVEFAILED 4
+#define EXIT_CONN_STATE_MAX_ 4
+
+/* The AP state values must be disjoint from the EXIT state values. */
+#define AP_CONN_STATE_MIN_ 5
+/** State for a SOCKS connection: waiting for SOCKS request. */
+#define AP_CONN_STATE_SOCKS_WAIT 5
+/** State for a SOCKS connection: got a y.onion URL; waiting to receive
+ * rendezvous descriptor. */
+#define AP_CONN_STATE_RENDDESC_WAIT 6
+/** The controller will attach this connection to a circuit; it isn't our
+ * job to do so. */
+#define AP_CONN_STATE_CONTROLLER_WAIT 7
+/** State for a SOCKS connection: waiting for a completed circuit. */
+#define AP_CONN_STATE_CIRCUIT_WAIT 8
+/** State for a SOCKS connection: sent BEGIN, waiting for CONNECTED. */
+#define AP_CONN_STATE_CONNECT_WAIT 9
+/** State for a SOCKS connection: sent RESOLVE, waiting for RESOLVED. */
+#define AP_CONN_STATE_RESOLVE_WAIT 10
+/** State for a SOCKS connection: ready to send and receive. */
+#define AP_CONN_STATE_OPEN 11
+/** State for a transparent natd connection: waiting for original
+ * destination. */
+#define AP_CONN_STATE_NATD_WAIT 12
+/** State for an HTTP tunnel: waiting for an HTTP CONNECT command. */
+#define AP_CONN_STATE_HTTP_CONNECT_WAIT 13
+#define AP_CONN_STATE_MAX_ 13
+
+#define EXIT_PURPOSE_MIN_ 1
+/** This exit stream wants to do an ordinary connect. */
+#define EXIT_PURPOSE_CONNECT 1
+/** This exit stream wants to do a resolve (either normal or reverse). */
+#define EXIT_PURPOSE_RESOLVE 2
+#define EXIT_PURPOSE_MAX_ 2
+
+/** True iff the AP_CONN_STATE_* value <b>s</b> means that the corresponding
+ * edge connection is not attached to any circuit. */
+#define AP_CONN_STATE_IS_UNATTACHED(s) \
+ ((s) <= AP_CONN_STATE_CIRCUIT_WAIT || (s) == AP_CONN_STATE_NATD_WAIT)
+
+#define connection_mark_unattached_ap(conn, endreason) \
connection_mark_unattached_ap_((conn), (endreason), __LINE__, SHORT_FILE__)
MOCK_DECL(void,connection_mark_unattached_ap_,
@@ -194,4 +246,3 @@ STATIC int connection_ap_process_http_connect(entry_connection_t *conn);
#endif /* defined(CONNECTION_EDGE_PRIVATE) */
#endif /* !defined(TOR_CONNECTION_EDGE_H) */
-
diff --git a/src/or/connection_or.c b/src/core/or/connection_or.c
index 7898fbd42e..159ee96266 100644
--- a/src/or/connection_or.c
+++ b/src/core/or/connection_or.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -20,46 +20,58 @@
*
* This module also implements the client side of the v3 Tor link handshake,
**/
-#include "or.h"
-#include "bridges.h"
-#include "buffers.h"
+#include "core/or/or.h"
+#include "feature/client/bridges.h"
+#include "lib/container/buffers.h"
/*
* Define this so we get channel internal functions, since we're implementing
* part of a subclass (channel_tls_t).
*/
#define TOR_CHANNEL_INTERNAL_
#define CONNECTION_OR_PRIVATE
-#include "channel.h"
-#include "channeltls.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuitstats.h"
-#include "command.h"
-#include "config.h"
-#include "connection.h"
-#include "connection_or.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "dirserv.h"
-#include "entrynodes.h"
-#include "geoip.h"
-#include "main.h"
-#include "link_handshake.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "proto_cell.h"
-#include "reasons.h"
-#include "relay.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerkeys.h"
-#include "routerlist.h"
-#include "ext_orport.h"
-#include "scheduler.h"
-#include "torcert.h"
-#include "channelpadding.h"
+#include "core/or/channel.h"
+#include "core/or/channeltls.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuitstats.h"
+#include "core/or/command.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_or.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/client/entrynodes.h"
+#include "feature/stats/geoip.h"
+#include "core/mainloop/main.h"
+#include "trunnel/link_handshake.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/proto/proto_cell.h"
+#include "core/or/reasons.h"
+#include "core/or/relay.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routerkeys.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/relay/ext_orport.h"
+#include "core/or/scheduler.h"
+#include "feature/nodelist/torcert.h"
+#include "core/or/channelpadding.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/cell_queue_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 "app/config/or_state_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "core/or/var_cell_st.h"
+#include "lib/crypt_ops/crypto_format.h"
+
+#include "lib/tls/tortls.h"
static int connection_tls_finish_handshake(or_connection_t *conn);
static int connection_or_launch_v3_or_handshake(or_connection_t *conn);
@@ -86,6 +98,15 @@ 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. */
+or_connection_t *
+TO_OR_CONN(connection_t *c)
+{
+ tor_assert(c->magic == OR_CONNECTION_MAGIC);
+ return DOWNCAST(or_connection_t, c);
+}
+
/** Global map between Extended ORPort identifiers and OR
* connections. */
static digestmap_t *orconn_ext_or_id_map = NULL;
@@ -834,9 +855,9 @@ connection_or_set_canonical(or_connection_t *or_conn,
TLS_CHAN_TO_BASE(or_conn->chan), is_canonical);
log_info(LD_CIRC,
- "Channel " U64_FORMAT " chose an idle timeout of %d.",
+ "Channel %"PRIu64 " chose an idle timeout of %d.",
or_conn->chan ?
- U64_PRINTF_ARG(TLS_CHAN_TO_BASE(or_conn->chan)->global_identifier):0,
+ (TLS_CHAN_TO_BASE(or_conn->chan)->global_identifier):0,
or_conn->idle_timeout);
}
@@ -2973,4 +2994,3 @@ connection_or_send_authenticate_cell,(or_connection_t *conn, int authtype))
return 0;
}
-
diff --git a/src/or/connection_or.h b/src/core/or/connection_or.h
index 158eb1fdad..2d95fdea18 100644
--- a/src/or/connection_or.h
+++ b/src/core/or/connection_or.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,6 +12,38 @@
#ifndef TOR_CONNECTION_OR_H
#define TOR_CONNECTION_OR_H
+struct ed25519_public_key_t;
+struct ed25519_keypair_t;
+
+or_connection_t *TO_OR_CONN(connection_t *);
+
+#define OR_CONN_STATE_MIN_ 1
+/** State for a connection to an OR: waiting for connect() to finish. */
+#define OR_CONN_STATE_CONNECTING 1
+/** State for a connection to an OR: waiting for proxy handshake to complete */
+#define OR_CONN_STATE_PROXY_HANDSHAKING 2
+/** State for an OR connection client: SSL is handshaking, not done
+ * yet. */
+#define OR_CONN_STATE_TLS_HANDSHAKING 3
+/** State for a connection to an OR: We're doing a second SSL handshake for
+ * renegotiation purposes. (V2 handshake only.) */
+#define OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING 4
+/** State for a connection at an OR: We're waiting for the client to
+ * renegotiate (to indicate a v2 handshake) or send a versions cell (to
+ * indicate a v3 handshake) */
+#define OR_CONN_STATE_TLS_SERVER_RENEGOTIATING 5
+/** State for an OR connection: We're done with our SSL handshake, we've done
+ * renegotiation, but we haven't yet negotiated link protocol versions and
+ * sent a netinfo cell. */
+#define OR_CONN_STATE_OR_HANDSHAKING_V2 6
+/** State for an OR connection: We're done with our SSL handshake, but we
+ * haven't yet negotiated link protocol versions, done a V3 handshake, and
+ * sent a netinfo cell. */
+#define OR_CONN_STATE_OR_HANDSHAKING_V3 7
+/** State for an OR connection: Ready to send/receive cells. */
+#define OR_CONN_STATE_OPEN 8
+#define OR_CONN_STATE_MAX_ 8
+
void connection_or_clear_identity(or_connection_t *conn);
void connection_or_clear_identity_map(void);
void clear_broken_connection_map(int disable);
@@ -40,7 +72,7 @@ MOCK_DECL(or_connection_t *,
connection_or_connect,
(const tor_addr_t *addr, uint16_t port,
const char *id_digest,
- const ed25519_public_key_t *ed_id,
+ const struct ed25519_public_key_t *ed_id,
channel_tls_t *chan));
void connection_or_close_normally(or_connection_t *orconn, int flush);
@@ -58,14 +90,14 @@ void connection_or_set_canonical(or_connection_t *or_conn,
int connection_init_or_handshake_state(or_connection_t *conn,
int started_here);
void connection_or_init_conn_from_address(or_connection_t *conn,
- const tor_addr_t *addr,
- uint16_t port,
- const char *rsa_id_digest,
- const ed25519_public_key_t *ed_id,
- int started_here);
+ const tor_addr_t *addr,
+ uint16_t port,
+ const char *rsa_id_digest,
+ const struct ed25519_public_key_t *ed_id,
+ int started_here);
int connection_or_client_learned_peer_id(or_connection_t *conn,
const uint8_t *rsa_peer_id,
- const ed25519_public_key_t *ed_peer_id);
+ const struct ed25519_public_key_t *ed_peer_id);
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);
@@ -92,11 +124,12 @@ int connection_or_send_auth_challenge_cell(or_connection_t *conn);
int authchallenge_type_is_supported(uint16_t challenge_type);
int authchallenge_type_is_better(uint16_t challenge_type_a,
uint16_t challenge_type_b);
-var_cell_t *connection_or_compute_authenticate_cell_body(or_connection_t *conn,
- const int authtype,
- crypto_pk_t *signing_key,
- const ed25519_keypair_t *ed_signing_key,
- int server);
+var_cell_t *connection_or_compute_authenticate_cell_body(
+ or_connection_t *conn,
+ const int authtype,
+ crypto_pk_t *signing_key,
+ const struct ed25519_keypair_t *ed_signing_key,
+ int server);
MOCK_DECL(int,connection_or_send_authenticate_cell,
(or_connection_t *conn, int type));
@@ -130,4 +163,3 @@ extern int certs_cell_ed25519_disabled_for_testing;
#endif
#endif /* !defined(TOR_CONNECTION_OR_H) */
-
diff --git a/src/core/or/connection_st.h b/src/core/or/connection_st.h
new file mode 100644
index 0000000000..6c22478689
--- /dev/null
+++ b/src/core/or/connection_st.h
@@ -0,0 +1,149 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef CONNECTION_ST_H
+#define CONNECTION_ST_H
+
+struct buf_t;
+
+/* Values for connection_t.magic: used to make sure that downcasts (casts from
+* connection_t to foo_connection_t) are safe. */
+#define BASE_CONNECTION_MAGIC 0x7C3C304Eu
+#define OR_CONNECTION_MAGIC 0x7D31FF03u
+#define EDGE_CONNECTION_MAGIC 0xF0374013u
+#define ENTRY_CONNECTION_MAGIC 0xbb4a5703
+#define DIR_CONNECTION_MAGIC 0x9988ffeeu
+#define CONTROL_CONNECTION_MAGIC 0x8abc765du
+#define LISTENER_CONNECTION_MAGIC 0x1a1ac741u
+
+/** Description of a connection to another host or process, and associated
+ * data.
+ *
+ * A connection is named based on what it's connected to -- an "OR
+ * connection" has a Tor node on the other end, an "exit
+ * connection" has a website or other server on the other end, and an
+ * "AP connection" has an application proxy (and thus a user) on the
+ * other end.
+ *
+ * Every connection has a type and a state. Connections never change
+ * their type, but can go through many state changes in their lifetime.
+ *
+ * Every connection has two associated input and output buffers.
+ * Listeners don't use them. For non-listener connections, incoming
+ * data is appended to conn->inbuf, and outgoing data is taken from
+ * conn->outbuf. Connections differ primarily in the functions called
+ * to fill and drain these buffers.
+ */
+struct connection_t {
+ uint32_t magic; /**< For memory debugging: must equal one of
+ * *_CONNECTION_MAGIC. */
+
+ uint8_t state; /**< Current state of this connection. */
+ unsigned int type:5; /**< What kind of connection is this? */
+ unsigned int purpose:5; /**< Only used for DIR and EXIT types currently. */
+
+ /* The next fields are all one-bit booleans. Some are only applicable to
+ * connection subtypes, but we hold them here anyway, to save space.
+ */
+ unsigned int read_blocked_on_bw:1; /**< Boolean: should we start reading
+ * again once the bandwidth throttler allows it? */
+ unsigned int write_blocked_on_bw:1; /**< Boolean: should we start writing
+ * again once the bandwidth throttler allows
+ * writes? */
+ unsigned int hold_open_until_flushed:1; /**< Despite this connection's being
+ * marked for close, do we flush it
+ * before closing it? */
+ unsigned int inbuf_reached_eof:1; /**< Boolean: did read() return 0 on this
+ * conn? */
+ /** Set to 1 when we're inside connection_flushed_some to keep us from
+ * calling connection_handle_write() recursively. */
+ unsigned int in_flushed_some:1;
+ /** True if connection_handle_write is currently running on this connection.
+ */
+ unsigned int in_connection_handle_write:1;
+
+ /* For linked connections:
+ */
+ unsigned int linked:1; /**< True if there is, or has been, a linked_conn. */
+ /** True iff we'd like to be notified about read events from the
+ * linked conn. */
+ unsigned int reading_from_linked_conn:1;
+ /** True iff we're willing to write to the linked conn. */
+ unsigned int writing_to_linked_conn:1;
+ /** True iff we're currently able to read on the linked conn, and our
+ * read_event should be made active with libevent. */
+ unsigned int active_on_link:1;
+ /** True iff we've called connection_close_immediate() on this linked
+ * connection. */
+ unsigned int linked_conn_is_closed:1;
+
+ /** CONNECT/SOCKS proxy client handshake state (for outgoing connections). */
+ unsigned int proxy_state:4;
+
+ /** Our socket; set to TOR_INVALID_SOCKET if this connection is closed,
+ * or has no socket. */
+ tor_socket_t s;
+ int conn_array_index; /**< Index into the global connection array. */
+
+ struct event *read_event; /**< Libevent event structure. */
+ struct event *write_event; /**< Libevent event structure. */
+ 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
+ * said we could write? */
+
+ time_t timestamp_created; /**< When was this connection_t created? */
+
+ 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.
+ */
+ 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. */
+ uint16_t marked_for_close; /**< Should we close this conn on the next
+ * iteration of the main loop? (If true, holds
+ * the line number where this connection was
+ * marked.) */
+ 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. */
+ /** Another connection that's connected to this one in lieu of a socket. */
+ struct connection_t *linked_conn;
+
+ /** Unique identifier for this connection on this Tor instance. */
+ uint64_t global_identifier;
+
+ /** Bytes read since last call to control_event_conn_bandwidth_used().
+ * Only used if we're configured to emit CONN_BW events. */
+ uint32_t n_read_conn_bw;
+
+ /** Bytes written since last call to control_event_conn_bandwidth_used().
+ * Only used if we're configured to emit CONN_BW events. */
+ uint32_t n_written_conn_bw;
+};
+
+/** True iff <b>x</b> is an edge connection. */
+#define CONN_IS_EDGE(x) \
+ ((x)->type == CONN_TYPE_EXIT || (x)->type == CONN_TYPE_AP)
+
+/** True iff the purpose of <b>conn</b> means that it's a server-side
+ * directory connection. */
+#define DIR_CONN_IS_SERVER(conn) ((conn)->purpose == DIR_PURPOSE_SERVER)
+
+#endif
diff --git a/src/core/or/cpath_build_state_st.h b/src/core/or/cpath_build_state_st.h
new file mode 100644
index 0000000000..1db7251132
--- /dev/null
+++ b/src/core/or/cpath_build_state_st.h
@@ -0,0 +1,38 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef CIRCUIT_BUILD_STATE_ST_ST_H
+#define CIRCUIT_BUILD_STATE_ST_ST_H
+
+/** Information used to build a circuit. */
+struct cpath_build_state_t {
+ /** Intended length of the final circuit. */
+ int desired_path_len;
+ /** How to extend to the planned exit node. */
+ extend_info_t *chosen_exit;
+ /** Whether every node in the circ must have adequate uptime. */
+ unsigned int need_uptime : 1;
+ /** Whether every node in the circ must have adequate capacity. */
+ unsigned int need_capacity : 1;
+ /** Whether the last hop was picked with exiting in mind. */
+ unsigned int is_internal : 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. */
+ unsigned int onehop_tunnel : 1;
+ /** The crypt_path_t to append after rendezvous: used for rendezvous. */
+ crypt_path_t *pending_final_cpath;
+ /** A ref-counted reference to the crypt_path_t to append after
+ * rendezvous; used on the service side. */
+ crypt_path_reference_t *service_pending_final_cpath_ref;
+ /** How many times has building a circuit for this task failed? */
+ int failure_count;
+ /** At what time should we give up on this task? */
+ time_t expiry_time;
+};
+
+#endif
+
diff --git a/src/core/or/crypt_path_reference_st.h b/src/core/or/crypt_path_reference_st.h
new file mode 100644
index 0000000000..bb0e519233
--- /dev/null
+++ b/src/core/or/crypt_path_reference_st.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef CRYPT_PATH_REFERENCE_ST_H
+#define CRYPT_PATH_REFERENCE_ST_H
+
+/** A reference-counted pointer to a crypt_path_t, used only to share
+ * the final rendezvous cpath to be used on a service-side rendezvous
+ * circuit among multiple circuits built in parallel to the same
+ * destination rendezvous point. */
+struct crypt_path_reference_t {
+ /** The reference count. */
+ unsigned int refcount;
+ /** The pointer. Set to NULL when the crypt_path_t is put into use
+ * on an opened rendezvous circuit. */
+ crypt_path_t *cpath;
+};
+
+#endif
+
diff --git a/src/core/or/crypt_path_st.h b/src/core/or/crypt_path_st.h
new file mode 100644
index 0000000000..1380913360
--- /dev/null
+++ b/src/core/or/crypt_path_st.h
@@ -0,0 +1,70 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef CRYPT_PATH_ST_H
+#define CRYPT_PATH_ST_H
+
+#include "core/or/relay_crypto_st.h"
+struct crypto_dh_t;
+
+#define CRYPT_PATH_MAGIC 0x70127012u
+
+struct fast_handshake_state_t;
+struct ntor_handshake_state_t;
+struct crypto_dh_t;
+struct onion_handshake_state_t {
+ uint16_t tag;
+ union {
+ struct fast_handshake_state_t *fast;
+ struct crypto_dh_t *tap;
+ struct ntor_handshake_state_t *ntor;
+ } u;
+};
+
+/** Holds accounting information for a single step in the layered encryption
+ * performed by a circuit. Used only at the client edge of a circuit. */
+struct crypt_path_t {
+ uint32_t magic;
+
+ /** Cryptographic state used for encrypting and authenticating relay
+ * cells to and from this hop. */
+ relay_crypto_t crypto;
+
+ /** Current state of the handshake as performed with the OR at this
+ * step. */
+ onion_handshake_state_t handshake_state;
+ /** Diffie-hellman handshake state for performing an introduction
+ * operations */
+ struct crypto_dh_t *rend_dh_handshake_state;
+
+ /** Negotiated key material shared with the OR at this step. */
+ char rend_circ_nonce[DIGEST_LEN];/* KH in tor-spec.txt */
+
+ /** Information to extend to the OR at this step. */
+ extend_info_t *extend_info;
+
+ /** Is the circuit built to this step? Must be one of:
+ * - CPATH_STATE_CLOSED (The circuit has not been extended to this step)
+ * - CPATH_STATE_AWAITING_KEYS (We have sent an EXTEND/CREATE to this step
+ * and not received an EXTENDED/CREATED)
+ * - CPATH_STATE_OPEN (The circuit has been extended to this step) */
+ uint8_t state;
+#define CPATH_STATE_CLOSED 0
+#define CPATH_STATE_AWAITING_KEYS 1
+#define CPATH_STATE_OPEN 2
+ struct crypt_path_t *next; /**< Link to next crypt_path_t in the circuit.
+ * (The list is circular, so the last node
+ * links to the first.) */
+ struct crypt_path_t *prev; /**< Link to previous crypt_path_t in the
+ * circuit. */
+
+ int package_window; /**< How many cells are we allowed to originate ending
+ * at this step? */
+ int deliver_window; /**< How many cells are we willing to deliver originating
+ * at this step? */
+};
+
+#endif
diff --git a/src/core/or/destroy_cell_queue_st.h b/src/core/or/destroy_cell_queue_st.h
new file mode 100644
index 0000000000..2839b0bd11
--- /dev/null
+++ b/src/core/or/destroy_cell_queue_st.h
@@ -0,0 +1,27 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef DESTROY_CELL_QUEUE_ST_H
+#define DESTROY_CELL_QUEUE_ST_H
+
+/** A single queued destroy cell. */
+struct destroy_cell_t {
+ TOR_SIMPLEQ_ENTRY(destroy_cell_t) next;
+ circid_t circid;
+ uint32_t inserted_timestamp; /**< Time (in timestamp units) when this cell
+ * was inserted */
+ uint8_t reason;
+};
+
+/** A queue of destroy cells on a channel. */
+struct destroy_cell_queue_t {
+ /** Linked list of packed_cell_t */
+ TOR_SIMPLEQ_HEAD(dcell_simpleq, destroy_cell_t) head;
+ int n; /**< The number of cells in the queue. */
+};
+
+#endif
+
diff --git a/src/or/dos.c b/src/core/or/dos.c
index ee731accea..52879c34d7 100644
--- a/src/or/dos.c
+++ b/src/core/or/dos.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/*
@@ -8,18 +8,22 @@
#define DOS_PRIVATE
-#include "or.h"
-#include "channel.h"
-#include "config.h"
-#include "crypto_rand.h"
-#include "geoip.h"
-#include "main.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "relay.h"
-#include "router.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_or.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/stats/geoip.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/relay.h"
+#include "feature/relay/router.h"
-#include "dos.h"
+#include "core/or/dos.h"
+
+#include "core/or/or_connection_st.h"
/*
* Circuit creation denial of service mitigation.
@@ -795,4 +799,3 @@ dos_init(void)
/* To initialize, we only need to get the parameters. */
set_dos_parameters(NULL);
}
-
diff --git a/src/or/dos.h b/src/core/or/dos.h
index 5d35a2b12e..760ef11057 100644
--- a/src/or/dos.h
+++ b/src/core/or/dos.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/*
diff --git a/src/core/or/edge_connection_st.h b/src/core/or/edge_connection_st.h
new file mode 100644
index 0000000000..f4388c10e6
--- /dev/null
+++ b/src/core/or/edge_connection_st.h
@@ -0,0 +1,77 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef EDGE_CONNECTION_ST_H
+#define EDGE_CONNECTION_ST_H
+
+#include "core/or/or.h"
+
+#include "core/or/connection_st.h"
+
+/** Subtype of connection_t for an "edge connection" -- that is, an entry (ap)
+ * connection, or an exit. */
+struct edge_connection_t {
+ connection_t base_;
+
+ struct edge_connection_t *next_stream; /**< Points to the next stream at this
+ * edge, if any */
+ int package_window; /**< How many more relay cells can I send into the
+ * circuit? */
+ int deliver_window; /**< How many more relay cells can end at me? */
+
+ struct circuit_t *on_circuit; /**< The circuit (if any) that this edge
+ * connection is using. */
+
+ /** A pointer to which node in the circ this conn exits at. Set for AP
+ * connections and for hidden service exit connections. */
+ struct crypt_path_t *cpath_layer;
+ /** What rendezvous service are we querying for (if an AP) or providing (if
+ * an exit)? */
+ rend_data_t *rend_data;
+
+ /* Hidden service connection identifier for edge connections. Used by the HS
+ * client-side code to identify client SOCKS connections and by the
+ * service-side code to match HS circuits with their streams. */
+ struct hs_ident_edge_conn_t *hs_ident;
+
+ uint32_t address_ttl; /**< TTL for address-to-addr mapping on exit
+ * connection. Exit connections only. */
+ uint32_t begincell_flags; /** Flags sent or received in the BEGIN cell
+ * for this connection */
+
+ streamid_t stream_id; /**< The stream ID used for this edge connection on its
+ * circuit */
+
+ /** The reason why this connection is closing; passed to the controller. */
+ uint16_t end_reason;
+
+ /** Bytes read since last call to control_event_stream_bandwidth_used() */
+ uint32_t n_read;
+
+ /** Bytes written since last call to control_event_stream_bandwidth_used() */
+ uint32_t n_written;
+
+ /** True iff this connection is for a DNS request only. */
+ unsigned int is_dns_request:1;
+ /** True iff this connection is for a PTR DNS request. (exit only) */
+ unsigned int is_reverse_dns_lookup:1;
+
+ unsigned int edge_has_sent_end:1; /**< For debugging; only used on edge
+ * connections. Set once we've set the stream end,
+ * and check in connection_about_to_close_connection().
+ */
+ /** True iff we've blocked reading until the circuit has fewer queued
+ * cells. */
+ unsigned int edge_blocked_on_circ:1;
+
+ /** Unique ID for directory requests; this used to be in connection_t, but
+ * that's going away and being used on channels instead. We still tag
+ * edge connections with dirreq_id from circuits, so it's copied here. */
+ uint64_t dirreq_id;
+};
+
+#endif
+
diff --git a/src/core/or/entry_connection_st.h b/src/core/or/entry_connection_st.h
new file mode 100644
index 0000000000..ebaee2f1a6
--- /dev/null
+++ b/src/core/or/entry_connection_st.h
@@ -0,0 +1,100 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef ENTRY_CONNECTION_ST_H
+#define ENTRY_CONNECTION_ST_H
+
+#include "core/or/edge_connection_st.h"
+
+/** Subtype of edge_connection_t for an "entry connection" -- that is, a SOCKS
+ * connection, a DNS request, a TransPort connection or a NATD connection */
+struct entry_connection_t {
+ struct edge_connection_t edge_;
+
+ /** Nickname of planned exit node -- used with .exit support. */
+ /* XXX prop220: we need to make chosen_exit_name able to encode Ed IDs too.
+ * That's logically part of the UI parts for prop220 though. */
+ char *chosen_exit_name;
+
+ socks_request_t *socks_request; /**< SOCKS structure describing request (AP
+ * only.) */
+
+ /* === Isolation related, AP only. === */
+ entry_port_cfg_t entry_cfg;
+ /** AP only: The newnym epoch in which we created this connection. */
+ unsigned nym_epoch;
+
+ /** AP only: The original requested address before we rewrote it. */
+ char *original_dest_address;
+ /* Other fields to isolate on already exist. The ClientAddr is addr. The
+ ClientProtocol is a combination of type and socks_request->
+ socks_version. SocksAuth is socks_request->username/password.
+ DestAddr is in socks_request->address. */
+
+ /** Number of times we've reassigned this application connection to
+ * a new circuit. We keep track because the timeout is longer if we've
+ * already retried several times. */
+ uint8_t num_socks_retries;
+
+ /** For AP connections only: buffer for data that we have sent
+ * optimistically, which we might need to re-send if we have to
+ * retry this connection. */
+ struct buf_t *pending_optimistic_data;
+ /* For AP connections only: buffer for data that we previously sent
+ * optimistically which we are currently re-sending as we retry this
+ * connection. */
+ struct buf_t *sending_optimistic_data;
+
+ /** If this is a DNSPort connection, this field holds the pending DNS
+ * request that we're going to try to answer. */
+ struct evdns_server_request *dns_server_request;
+
+#define DEBUGGING_17659
+
+#ifdef DEBUGGING_17659
+ uint16_t marked_pending_circ_line;
+ const char *marked_pending_circ_file;
+#endif
+
+#define NUM_CIRCUITS_LAUNCHED_THRESHOLD 10
+ /** Number of times we've launched a circuit to handle this stream. If
+ * it gets too high, that could indicate an inconsistency between our
+ * "launch a circuit to handle this stream" logic and our "attach our
+ * stream to one of the available circuits" logic. */
+ unsigned int num_circuits_launched:4;
+
+ /** True iff this stream must attach to a one-hop circuit (e.g. for
+ * begin_dir). */
+ unsigned int want_onehop:1;
+ /** True iff this stream should use a BEGIN_DIR relay command to establish
+ * itself rather than BEGIN (either via onehop or via a whole circuit). */
+ unsigned int use_begindir:1;
+
+ /** For AP connections only. If 1, and we fail to reach the chosen exit,
+ * stop requiring it. */
+ unsigned int chosen_exit_optional:1;
+ /** For AP connections only. If non-zero, this exit node was picked as
+ * a result of the TrackHostExit, and the value decrements every time
+ * we fail to complete a circuit to our chosen exit -- if it reaches
+ * zero, abandon the associated mapaddress. */
+ unsigned int chosen_exit_retries:3;
+
+ /** True iff this is an AP connection that came from a transparent or
+ * NATd connection */
+ unsigned int is_transparent_ap:1;
+
+ /** For AP connections only: Set if this connection's target exit node
+ * allows optimistic data (that is, data sent on this stream before
+ * the exit has sent a CONNECTED cell) and we have chosen to use it.
+ */
+ unsigned int may_use_optimistic_data : 1;
+};
+
+/** Cast a entry_connection_t subtype pointer to a edge_connection_t **/
+#define ENTRY_TO_EDGE_CONN(c) (&(((c))->edge_))
+
+#endif
+
diff --git a/src/core/or/entry_port_cfg_st.h b/src/core/or/entry_port_cfg_st.h
new file mode 100644
index 0000000000..492fafbd6d
--- /dev/null
+++ b/src/core/or/entry_port_cfg_st.h
@@ -0,0 +1,54 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef ENTRY_PORT_CFG_ST_H
+#define ENTRY_PORT_CFG_ST_H
+
+#include "lib/cc/torint.h"
+#include "core/or/or.h"
+
+struct entry_port_cfg_t {
+ /* Client port types (socks, dns, trans, natd) only: */
+ uint8_t isolation_flags; /**< Zero or more isolation flags */
+ int session_group; /**< A session group, or -1 if this port is not in a
+ * session group. */
+
+ /* Socks only: */
+ /** When both no-auth and user/pass are advertised by a SOCKS client, select
+ * no-auth. */
+ unsigned int socks_prefer_no_auth : 1;
+ /** When ISO_SOCKSAUTH is in use, Keep-Alive circuits indefinitely. */
+ unsigned int socks_iso_keep_alive : 1;
+
+ /* Client port types only: */
+ unsigned int ipv4_traffic : 1;
+ unsigned int ipv6_traffic : 1;
+ unsigned int prefer_ipv6 : 1;
+ unsigned int dns_request : 1;
+ unsigned int onion_traffic : 1;
+
+ /** For a socks listener: should we cache IPv4/IPv6 DNS information that
+ * exit nodes tell us?
+ *
+ * @{ */
+ unsigned int cache_ipv4_answers : 1;
+ unsigned int cache_ipv6_answers : 1;
+ /** @} */
+ /** For a socks listeners: if we find an answer in our client-side DNS cache,
+ * should we use it?
+ *
+ * @{ */
+ unsigned int use_cached_ipv4_answers : 1;
+ unsigned int use_cached_ipv6_answers : 1;
+ /** @} */
+ /** For socks listeners: When we can automap an address to IPv4 or IPv6,
+ * do we prefer IPv6? */
+ unsigned int prefer_ipv6_virtaddr : 1;
+
+};
+
+#endif
+
diff --git a/src/core/or/extend_info_st.h b/src/core/or/extend_info_st.h
new file mode 100644
index 0000000000..277766c4d6
--- /dev/null
+++ b/src/core/or/extend_info_st.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef EXTEND_INFO_ST_H
+#define EXTEND_INFO_ST_H
+
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+
+/** 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
+ * general-purpose tunnels, the onion_key is NULL. */
+struct extend_info_t {
+ char nickname[MAX_HEX_NICKNAME_LEN+1]; /**< This router's nickname for
+ * display. */
+ /** Hash of this router's RSA identity key. */
+ 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. */
+ curve25519_public_key_t curve25519_onion_key;
+};
+
+#endif
diff --git a/src/or/git_revision.c b/src/core/or/git_revision.c
index 8f326b8751..28ec1a7933 100644
--- a/src/or/git_revision.c
+++ b/src/core/or/git_revision.c
@@ -1,17 +1,16 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "git_revision.h"
+#include "core/or/git_revision.h"
/** String describing which Tor Git repository version the source was
* built from. This string is generated by a bit of shell kludging in
- * src/or/include.am, and is usually right.
+ * src/core/include.am, and is usually right.
*/
const char tor_git_revision[] =
#ifndef _MSC_VER
#include "micro-revision.i"
#endif
"";
-
diff --git a/src/or/git_revision.h b/src/core/or/git_revision.h
index 5613cb4335..02070cfd5e 100644
--- a/src/or/git_revision.h
+++ b/src/core/or/git_revision.h
@@ -1,6 +1,6 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_GIT_REVISION_H
diff --git a/src/core/or/listener_connection_st.h b/src/core/or/listener_connection_st.h
new file mode 100644
index 0000000000..ec350c1b0d
--- /dev/null
+++ b/src/core/or/listener_connection_st.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-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef LISTENER_CONNECTION_ST_H
+#define LISTENER_CONNECTION_ST_H
+
+#include "core/or/connection_st.h"
+
+/** Subtype of connection_t; used for a listener socket. */
+struct listener_connection_t {
+ connection_t base_;
+
+ /** If the connection is a CONN_TYPE_AP_DNS_LISTENER, this field points
+ * to the evdns_server_port it uses to listen to and answer connections. */
+ struct evdns_server_port *dns_server_port;
+
+ entry_port_cfg_t entry_cfg;
+
+};
+
+#endif
+
diff --git a/src/core/or/or.h b/src/core/or/or.h
new file mode 100644
index 0000000000..6edfd21dfb
--- /dev/null
+++ b/src/core/or/or.h
@@ -0,0 +1,1088 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file or.h
+ * \brief Master header file for Tor-specific functionality.
+ **/
+
+#ifndef TOR_OR_H
+#define TOR_OR_H
+
+#include "orconfig.h"
+#include "lib/cc/torint.h"
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#include "lib/arch/bytes.h"
+#include "lib/cc/compat_compiler.h"
+#include "lib/cc/torint.h"
+#include "lib/container/map.h"
+#include "lib/container/smartlist.h"
+#include "lib/crypt_ops/crypto.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/defs/dh_sizes.h"
+#include "lib/encoding/binascii.h"
+#include "lib/encoding/cstring.h"
+#include "lib/encoding/time_fmt.h"
+#include "lib/err/torerr.h"
+#include "lib/fs/dir.h"
+#include "lib/fs/files.h"
+#include "lib/fs/mmap.h"
+#include "lib/fs/path.h"
+#include "lib/fs/userdb.h"
+#include "lib/intmath/addsub.h"
+#include "lib/intmath/bits.h"
+#include "lib/intmath/cmp.h"
+#include "lib/intmath/logic.h"
+#include "lib/intmath/muldiv.h"
+#include "lib/log/escape.h"
+#include "lib/log/ratelim.h"
+#include "lib/log/util_bug.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/net/address.h"
+#include "lib/net/ipv4.h"
+#include "lib/net/ipv6.h"
+#include "lib/net/resolve.h"
+#include "lib/net/socket.h"
+#include "lib/string/compat_ctype.h"
+#include "lib/string/compat_string.h"
+#include "lib/string/parse_int.h"
+#include "lib/string/printf.h"
+#include "lib/string/scanf.h"
+#include "lib/string/util_string.h"
+#include "lib/testsupport/testsupport.h"
+#include "lib/thread/threads.h"
+#include "lib/time/compat_time.h"
+#include "lib/wallclock/approx_time.h"
+#include "lib/wallclock/timeval.h"
+
+#include "ht.h"
+
+// These, more than other includes, are for keeping the other struct
+// definitions working. We should remove them when we minimize our includes.
+#include "core/or/entry_port_cfg_st.h"
+
+struct ed25519_public_key_t;
+struct curve25519_public_key_t;
+
+/* These signals are defined to help handle_control_signal work.
+ */
+#ifndef SIGHUP
+#define SIGHUP 1
+#endif
+#ifndef SIGINT
+#define SIGINT 2
+#endif
+#ifndef SIGUSR1
+#define SIGUSR1 10
+#endif
+#ifndef SIGUSR2
+#define SIGUSR2 12
+#endif
+#ifndef SIGTERM
+#define SIGTERM 15
+#endif
+/* Controller signals start at a high number so we don't
+ * conflict with system-defined signals. */
+#define SIGNEWNYM 129
+#define SIGCLEARDNSCACHE 130
+#define SIGHEARTBEAT 131
+
+#if (SIZEOF_CELL_T != 0)
+/* On Irix, stdlib.h defines a cell_t type, so we need to make sure
+ * that our stuff always calls cell_t something different. */
+#define cell_t tor_cell_t
+#endif
+
+#ifdef ENABLE_TOR2WEB_MODE
+#define NON_ANONYMOUS_MODE_ENABLED 1
+#endif
+
+/** Helper macro: Given a pointer to to.base_, of type from*, return &to. */
+#define DOWNCAST(to, ptr) ((to*)SUBTYPE_P(ptr, to, base_))
+
+/** Length of longest allowable configured nickname. */
+#define MAX_NICKNAME_LEN 19
+/** Length of a router identity encoded as a hexadecimal digest, plus
+ * possible dollar sign. */
+#define MAX_HEX_NICKNAME_LEN (HEX_DIGEST_LEN+1)
+/** Maximum length of verbose router identifier: dollar sign, hex ID digest,
+ * equal sign or tilde, nickname. */
+#define MAX_VERBOSE_NICKNAME_LEN (1+HEX_DIGEST_LEN+1+MAX_NICKNAME_LEN)
+
+/** For HTTP parsing: Maximum number of bytes we'll accept in the headers
+ * of an HTTP request or response. */
+#define MAX_HEADERS_SIZE 50000
+
+/** Maximum size, in bytes, of a single router descriptor uploaded to us
+ * as a directory authority. Caches and clients fetch whatever descriptors
+ * the authorities tell them to fetch, and don't care about size. */
+#define MAX_DESCRIPTOR_UPLOAD_SIZE 20000
+
+/** Maximum size of a single extrainfo document, as above. */
+#define MAX_EXTRAINFO_UPLOAD_SIZE 50000
+
+/** Minimum lifetime for an onion key in days. */
+#define MIN_ONION_KEY_LIFETIME_DAYS (1)
+
+/** Maximum lifetime for an onion key in days. */
+#define MAX_ONION_KEY_LIFETIME_DAYS (90)
+
+/** Default lifetime for an onion key in days. */
+#define DEFAULT_ONION_KEY_LIFETIME_DAYS (28)
+
+/** Minimum grace period for acceptance of an onion key in days.
+ * The maximum value is defined in proposal #274 as being the current network
+ * consensus parameter for "onion-key-rotation-days". */
+#define MIN_ONION_KEY_GRACE_PERIOD_DAYS (1)
+
+/** Default grace period for acceptance of an onion key in days. */
+#define DEFAULT_ONION_KEY_GRACE_PERIOD_DAYS (7)
+
+/** How often we should check the network consensus if it is time to rotate or
+ * expire onion keys. */
+#define ONION_KEY_CONSENSUS_CHECK_INTERVAL (60*60)
+
+/** How often do we rotate TLS contexts? */
+#define MAX_SSL_KEY_LIFETIME_INTERNAL (2*60*60)
+
+/** How old do we allow a router to get before removing it
+ * from the router list? In seconds. */
+#define ROUTER_MAX_AGE (60*60*48)
+/** How old can a router get before we (as a server) will no longer
+ * consider it live? In seconds. */
+#define ROUTER_MAX_AGE_TO_PUBLISH (60*60*24)
+/** How old do we let a saved descriptor get before force-removing it? */
+#define OLD_ROUTER_DESC_MAX_AGE (60*60*24*5)
+
+/* Proxy client types */
+#define PROXY_NONE 0
+#define PROXY_CONNECT 1
+#define PROXY_SOCKS4 2
+#define PROXY_SOCKS5 3
+/* !!!! If there is ever a PROXY_* type over 3, we must grow the proxy_type
+ * field in or_connection_t */
+
+/* Pluggable transport proxy type. Don't use this in or_connection_t,
+ * instead use the actual underlying proxy type (see above). */
+#define PROXY_PLUGGABLE 4
+
+/** How many circuits do we want simultaneously in-progress to handle
+ * a given stream? */
+#define MIN_CIRCUITS_HANDLING_STREAM 2
+
+/* These RELAY_COMMAND constants define values for relay cell commands, and
+* must match those defined in tor-spec.txt. */
+#define RELAY_COMMAND_BEGIN 1
+#define RELAY_COMMAND_DATA 2
+#define RELAY_COMMAND_END 3
+#define RELAY_COMMAND_CONNECTED 4
+#define RELAY_COMMAND_SENDME 5
+#define RELAY_COMMAND_EXTEND 6
+#define RELAY_COMMAND_EXTENDED 7
+#define RELAY_COMMAND_TRUNCATE 8
+#define RELAY_COMMAND_TRUNCATED 9
+#define RELAY_COMMAND_DROP 10
+#define RELAY_COMMAND_RESOLVE 11
+#define RELAY_COMMAND_RESOLVED 12
+#define RELAY_COMMAND_BEGIN_DIR 13
+#define RELAY_COMMAND_EXTEND2 14
+#define RELAY_COMMAND_EXTENDED2 15
+
+#define RELAY_COMMAND_ESTABLISH_INTRO 32
+#define RELAY_COMMAND_ESTABLISH_RENDEZVOUS 33
+#define RELAY_COMMAND_INTRODUCE1 34
+#define RELAY_COMMAND_INTRODUCE2 35
+#define RELAY_COMMAND_RENDEZVOUS1 36
+#define RELAY_COMMAND_RENDEZVOUS2 37
+#define RELAY_COMMAND_INTRO_ESTABLISHED 38
+#define RELAY_COMMAND_RENDEZVOUS_ESTABLISHED 39
+#define RELAY_COMMAND_INTRODUCE_ACK 40
+
+/* Reasons why an OR connection is closed. */
+#define END_OR_CONN_REASON_DONE 1
+#define END_OR_CONN_REASON_REFUSED 2 /* connection refused */
+#define END_OR_CONN_REASON_OR_IDENTITY 3
+#define END_OR_CONN_REASON_CONNRESET 4 /* connection reset by peer */
+#define END_OR_CONN_REASON_TIMEOUT 5
+#define END_OR_CONN_REASON_NO_ROUTE 6 /* no route to host/net */
+#define END_OR_CONN_REASON_IO_ERROR 7 /* read/write error */
+#define END_OR_CONN_REASON_RESOURCE_LIMIT 8 /* sockets, buffers, etc */
+#define END_OR_CONN_REASON_PT_MISSING 9 /* PT failed or not available */
+#define END_OR_CONN_REASON_MISC 10
+
+/* Reasons why we (or a remote OR) might close a stream. See tor-spec.txt for
+ * documentation of these. The values must match. */
+#define END_STREAM_REASON_MISC 1
+#define END_STREAM_REASON_RESOLVEFAILED 2
+#define END_STREAM_REASON_CONNECTREFUSED 3
+#define END_STREAM_REASON_EXITPOLICY 4
+#define END_STREAM_REASON_DESTROY 5
+#define END_STREAM_REASON_DONE 6
+#define END_STREAM_REASON_TIMEOUT 7
+#define END_STREAM_REASON_NOROUTE 8
+#define END_STREAM_REASON_HIBERNATING 9
+#define END_STREAM_REASON_INTERNAL 10
+#define END_STREAM_REASON_RESOURCELIMIT 11
+#define END_STREAM_REASON_CONNRESET 12
+#define END_STREAM_REASON_TORPROTOCOL 13
+#define END_STREAM_REASON_NOTDIRECTORY 14
+#define END_STREAM_REASON_ENTRYPOLICY 15
+
+/* These high-numbered end reasons are not part of the official spec,
+ * and are not intended to be put in relay end cells. They are here
+ * to be more informative when sending back socks replies to the
+ * application. */
+/* XXXX 256 is no longer used; feel free to reuse it. */
+/** We were unable to attach the connection to any circuit at all. */
+/* XXXX the ways we use this one don't make a lot of sense. */
+#define END_STREAM_REASON_CANT_ATTACH 257
+/** We can't connect to any directories at all, so we killed our streams
+ * before they can time out. */
+#define END_STREAM_REASON_NET_UNREACHABLE 258
+/** This is a SOCKS connection, and the client used (or misused) the SOCKS
+ * protocol in a way we couldn't handle. */
+#define END_STREAM_REASON_SOCKSPROTOCOL 259
+/** This is a transparent proxy connection, but we can't extract the original
+ * target address:port. */
+#define END_STREAM_REASON_CANT_FETCH_ORIG_DEST 260
+/** This is a connection on the NATD port, and the destination IP:Port was
+ * either ill-formed or out-of-range. */
+#define END_STREAM_REASON_INVALID_NATD_DEST 261
+/** The target address is in a private network (like 127.0.0.1 or 10.0.0.1);
+ * you don't want to do that over a randomly chosen exit */
+#define END_STREAM_REASON_PRIVATE_ADDR 262
+/** This is an HTTP tunnel connection and the client used or misused HTTP in a
+ * way we can't handle.
+ */
+#define END_STREAM_REASON_HTTPPROTOCOL 263
+
+/** Bitwise-and this value with endreason to mask out all flags. */
+#define END_STREAM_REASON_MASK 511
+
+/** Bitwise-or this with the argument to control_event_stream_status
+ * to indicate that the reason came from an END cell. */
+#define END_STREAM_REASON_FLAG_REMOTE 512
+/** Bitwise-or this with the argument to control_event_stream_status
+ * to indicate that we already sent a CLOSED stream event. */
+#define END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED 1024
+/** Bitwise-or this with endreason to indicate that we already sent
+ * a socks reply, and no further reply needs to be sent from
+ * connection_mark_unattached_ap(). */
+#define END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED 2048
+
+/* 'type' values to use in RESOLVED cells. Specified in tor-spec.txt. */
+#define RESOLVED_TYPE_HOSTNAME 0
+#define RESOLVED_TYPE_IPV4 4
+#define RESOLVED_TYPE_IPV6 6
+#define RESOLVED_TYPE_ERROR_TRANSIENT 0xF0
+#define RESOLVED_TYPE_ERROR 0xF1
+
+/* Negative reasons are internal: we never send them in a DESTROY or TRUNCATE
+ * call; they only go to the controller for tracking */
+
+/* Closing introduction point that were opened in parallel. */
+#define END_CIRC_REASON_IP_NOW_REDUNDANT -4
+
+/** Our post-timeout circuit time measurement period expired.
+ * We must give up now */
+#define END_CIRC_REASON_MEASUREMENT_EXPIRED -3
+
+/** We couldn't build a path for this circuit. */
+#define END_CIRC_REASON_NOPATH -2
+/** Catch-all "other" reason for closing origin circuits. */
+#define END_CIRC_AT_ORIGIN -1
+
+/* Reasons why we (or a remote OR) might close a circuit. See tor-spec.txt
+ * section 5.4 for documentation of these. */
+#define END_CIRC_REASON_MIN_ 0
+#define END_CIRC_REASON_NONE 0
+#define END_CIRC_REASON_TORPROTOCOL 1
+#define END_CIRC_REASON_INTERNAL 2
+#define END_CIRC_REASON_REQUESTED 3
+#define END_CIRC_REASON_HIBERNATING 4
+#define END_CIRC_REASON_RESOURCELIMIT 5
+#define END_CIRC_REASON_CONNECTFAILED 6
+#define END_CIRC_REASON_OR_IDENTITY 7
+#define END_CIRC_REASON_CHANNEL_CLOSED 8
+#define END_CIRC_REASON_FINISHED 9
+#define END_CIRC_REASON_TIMEOUT 10
+#define END_CIRC_REASON_DESTROYED 11
+#define END_CIRC_REASON_NOSUCHSERVICE 12
+#define END_CIRC_REASON_MAX_ 12
+
+/** Bitwise-OR this with the argument to circuit_mark_for_close() or
+ * control_event_circuit_status() to indicate that the reason was
+ * passed through from a destroy or truncate cell. */
+#define END_CIRC_REASON_FLAG_REMOTE 512
+
+/** Length of 'y' portion of 'y.onion' URL. */
+#define REND_SERVICE_ID_LEN_BASE32 16
+
+/** Length of 'y.onion' including '.onion' URL. */
+#define REND_SERVICE_ADDRESS_LEN (16+1+5)
+
+/** Length of a binary-encoded rendezvous service ID. */
+#define REND_SERVICE_ID_LEN 10
+
+/** Time period for which a v2 descriptor will be valid. */
+#define REND_TIME_PERIOD_V2_DESC_VALIDITY (24*60*60)
+
+/** Time period within which two sets of v2 descriptors will be uploaded in
+ * parallel. */
+#define REND_TIME_PERIOD_OVERLAPPING_V2_DESCS (60*60)
+
+/** Number of non-consecutive replicas (i.e. distributed somewhere
+ * in the ring) for a descriptor. */
+#define REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS 2
+
+/** Number of consecutive replicas for a descriptor. */
+#define REND_NUMBER_OF_CONSECUTIVE_REPLICAS 3
+
+/** Length of v2 descriptor ID (32 base32 chars = 160 bits). */
+#define REND_DESC_ID_V2_LEN_BASE32 BASE32_DIGEST_LEN
+
+/** Length of the base32-encoded secret ID part of versioned hidden service
+ * descriptors. */
+#define REND_SECRET_ID_PART_LEN_BASE32 BASE32_DIGEST_LEN
+
+/** Length of the base32-encoded hash of an introduction point's
+ * identity key. */
+#define REND_INTRO_POINT_ID_LEN_BASE32 BASE32_DIGEST_LEN
+
+/** Length of the descriptor cookie that is used for client authorization
+ * to hidden services. */
+#define REND_DESC_COOKIE_LEN 16
+
+/** Length of the base64-encoded descriptor cookie that is used for
+ * exchanging client authorization between hidden service and client. */
+#define REND_DESC_COOKIE_LEN_BASE64 22
+
+/** Length of client identifier in encrypted introduction points for hidden
+ * service authorization type 'basic'. */
+#define REND_BASIC_AUTH_CLIENT_ID_LEN 4
+
+/** Multiple of the number of clients to which the real number of clients
+ * is padded with fake clients for hidden service authorization type
+ * 'basic'. */
+#define REND_BASIC_AUTH_CLIENT_MULTIPLE 16
+
+/** Length of client entry consisting of client identifier and encrypted
+ * session key for hidden service authorization type 'basic'. */
+#define REND_BASIC_AUTH_CLIENT_ENTRY_LEN (REND_BASIC_AUTH_CLIENT_ID_LEN \
+ + CIPHER_KEY_LEN)
+
+/** Maximum size of v2 hidden service descriptors. */
+#define REND_DESC_MAX_SIZE (20 * 1024)
+
+/** Legal characters for use in authorized client names for a hidden
+ * service. */
+#define REND_LEGAL_CLIENTNAME_CHARACTERS \
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-_"
+
+/** Maximum length of authorized client names for a hidden service. */
+#define REND_CLIENTNAME_MAX_LEN 16
+
+/** Length of the rendezvous cookie that is used to connect circuits at the
+ * rendezvous point. */
+#define REND_COOKIE_LEN DIGEST_LEN
+
+/** Client authorization type that a hidden service performs. */
+typedef enum rend_auth_type_t {
+ REND_NO_AUTH = 0,
+ REND_BASIC_AUTH = 1,
+ REND_STEALTH_AUTH = 2,
+} rend_auth_type_t;
+
+/** Client-side configuration of authorization for a hidden service. */
+typedef struct rend_service_authorization_t {
+ uint8_t descriptor_cookie[REND_DESC_COOKIE_LEN];
+ char onion_address[REND_SERVICE_ADDRESS_LEN+1];
+ rend_auth_type_t auth_type;
+} rend_service_authorization_t;
+
+/** Client- and server-side data that is used for hidden service connection
+ * establishment. Not all fields contain data depending on where this struct
+ * is used. */
+typedef struct rend_data_t {
+ /* Hidden service protocol version of this base object. */
+ uint32_t version;
+
+ /** List of HSDir fingerprints on which this request has been sent to. This
+ * contains binary identity digest of the directory of size DIGEST_LEN. */
+ smartlist_t *hsdirs_fp;
+
+ /** Rendezvous cookie used by both, client and service. */
+ char rend_cookie[REND_COOKIE_LEN];
+
+ /** Number of streams associated with this rendezvous circuit. */
+ int nr_streams;
+} rend_data_t;
+
+typedef struct rend_data_v2_t {
+ /* Rendezvous base data. */
+ rend_data_t base_;
+
+ /** Onion address (without the .onion part) that a client requests. */
+ char onion_address[REND_SERVICE_ID_LEN_BASE32+1];
+
+ /** Descriptor ID for each replicas computed from the onion address. If
+ * the onion address is empty, this array MUST be empty. We keep them so
+ * we know when to purge our entry in the last hsdir request table. */
+ char descriptor_id[REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS][DIGEST_LEN];
+
+ /** (Optional) descriptor cookie that is used by a client. */
+ char descriptor_cookie[REND_DESC_COOKIE_LEN];
+
+ /** Authorization type for accessing a service used by a client. */
+ rend_auth_type_t auth_type;
+
+ /** Descriptor ID for a client request. The control port command HSFETCH
+ * uses this. It's set if the descriptor query should only use this
+ * descriptor ID. */
+ char desc_id_fetch[DIGEST_LEN];
+
+ /** Hash of the hidden service's PK used by a service. */
+ char rend_pk_digest[DIGEST_LEN];
+} rend_data_v2_t;
+
+/* From a base rend_data_t object <b>d</d>, return the v2 object. */
+static inline
+rend_data_v2_t *TO_REND_DATA_V2(const rend_data_t *d)
+{
+ tor_assert(d);
+ tor_assert(d->version == 2);
+ return DOWNCAST(rend_data_v2_t, d);
+}
+
+/* Stub because we can't include hs_ident.h. */
+struct hs_ident_edge_conn_t;
+struct hs_ident_dir_conn_t;
+struct hs_ident_circuit_t;
+
+typedef struct hsdir_index_t hsdir_index_t;
+
+/** Time interval for tracking replays of DH public keys received in
+ * INTRODUCE2 cells. Used only to avoid launching multiple
+ * simultaneous attempts to connect to the same rendezvous point. */
+#define REND_REPLAY_TIME_INTERVAL (5 * 60)
+
+/** Used to indicate which way a cell is going on a circuit. */
+typedef enum {
+ CELL_DIRECTION_IN=1, /**< The cell is moving towards the origin. */
+ CELL_DIRECTION_OUT=2, /**< The cell is moving away from the origin. */
+} cell_direction_t;
+
+/** Initial value for both sides of a circuit transmission window when the
+ * circuit is initialized. Measured in cells. */
+#define CIRCWINDOW_START 1000
+#define CIRCWINDOW_START_MIN 100
+#define CIRCWINDOW_START_MAX 1000
+/** Amount to increment a circuit window when we get a circuit SENDME. */
+#define CIRCWINDOW_INCREMENT 100
+/** Initial value on both sides of a stream transmission window when the
+ * stream is initialized. Measured in cells. */
+#define STREAMWINDOW_START 500
+#define STREAMWINDOW_START_MAX 500
+/** Amount to increment a stream window when we get a stream SENDME. */
+#define STREAMWINDOW_INCREMENT 50
+
+/** Maximum number of queued cells on a circuit for which we are the
+ * midpoint before we give up and kill it. This must be >= circwindow
+ * to avoid killing innocent circuits, and >= circwindow*2 to give
+ * leaky-pipe a chance of working someday. The ORCIRC_MAX_MIDDLE_KILL_THRESH
+ * ratio controls the margin of error between emitting a warning and
+ * killing the circuit.
+ */
+#define ORCIRC_MAX_MIDDLE_CELLS (CIRCWINDOW_START_MAX*2)
+/** Ratio of hard (circuit kill) to soft (warning) thresholds for the
+ * ORCIRC_MAX_MIDDLE_CELLS tests.
+ */
+#define ORCIRC_MAX_MIDDLE_KILL_THRESH (1.1f)
+
+/* Cell commands. These values are defined in tor-spec.txt. */
+#define CELL_PADDING 0
+#define CELL_CREATE 1
+#define CELL_CREATED 2
+#define CELL_RELAY 3
+#define CELL_DESTROY 4
+#define CELL_CREATE_FAST 5
+#define CELL_CREATED_FAST 6
+#define CELL_VERSIONS 7
+#define CELL_NETINFO 8
+#define CELL_RELAY_EARLY 9
+#define CELL_CREATE2 10
+#define CELL_CREATED2 11
+#define CELL_PADDING_NEGOTIATE 12
+
+#define CELL_VPADDING 128
+#define CELL_CERTS 129
+#define CELL_AUTH_CHALLENGE 130
+#define CELL_AUTHENTICATE 131
+#define CELL_AUTHORIZE 132
+#define CELL_COMMAND_MAX_ 132
+
+/** How long to test reachability before complaining to the user. */
+#define TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT (20*60)
+
+/** Legal characters in a nickname. */
+#define LEGAL_NICKNAME_CHARACTERS \
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+
+/** Name to use in client TLS certificates if no nickname is given. Once
+ * Tor 0.1.2.x is obsolete, we can remove this. */
+#define DEFAULT_CLIENT_NICKNAME "client"
+
+/** Name chosen by routers that don't configure nicknames */
+#define UNNAMED_ROUTER_NICKNAME "Unnamed"
+
+/** Number of bytes in a SOCKS4 header. */
+#define SOCKS4_NETWORK_LEN 8
+
+/*
+ * Relay payload:
+ * Relay command [1 byte]
+ * Recognized [2 bytes]
+ * Stream ID [2 bytes]
+ * Partial SHA-1 [4 bytes]
+ * Length [2 bytes]
+ * Relay payload [498 bytes]
+ */
+
+/** Number of bytes in a cell, minus cell header. */
+#define CELL_PAYLOAD_SIZE 509
+/** Number of bytes in a cell transmitted over the network, in the longest
+ * form */
+#define CELL_MAX_NETWORK_SIZE 514
+
+/** Maximum length of a header on a variable-length cell. */
+#define VAR_CELL_MAX_HEADER_SIZE 7
+
+static int get_cell_network_size(int wide_circ_ids);
+static inline int get_cell_network_size(int wide_circ_ids)
+{
+ return wide_circ_ids ? CELL_MAX_NETWORK_SIZE : CELL_MAX_NETWORK_SIZE - 2;
+}
+static int get_var_cell_header_size(int wide_circ_ids);
+static inline int get_var_cell_header_size(int wide_circ_ids)
+{
+ return wide_circ_ids ? VAR_CELL_MAX_HEADER_SIZE :
+ VAR_CELL_MAX_HEADER_SIZE - 2;
+}
+static int get_circ_id_size(int wide_circ_ids);
+static inline int get_circ_id_size(int wide_circ_ids)
+{
+ return wide_circ_ids ? 4 : 2;
+}
+
+/** Number of bytes in a relay cell's header (not including general cell
+ * header). */
+#define RELAY_HEADER_SIZE (1+2+2+4+2)
+/** Largest number of bytes that can fit in a relay cell payload. */
+#define RELAY_PAYLOAD_SIZE (CELL_PAYLOAD_SIZE-RELAY_HEADER_SIZE)
+
+/** Identifies a circuit on an or_connection */
+typedef uint32_t circid_t;
+/** Identifies a stream on a circuit */
+typedef uint16_t streamid_t;
+
+/* channel_t typedef; struct channel_s is in channel.h */
+
+typedef struct channel_s channel_t;
+
+/* channel_listener_t typedef; struct channel_listener_s is in channel.h */
+
+typedef struct channel_listener_s channel_listener_t;
+
+/* TLS channel stuff */
+
+typedef struct channel_tls_s channel_tls_t;
+
+/* circuitmux_t typedef; struct circuitmux_s is in circuitmux.h */
+
+typedef struct circuitmux_s circuitmux_t;
+
+typedef struct cell_t cell_t;
+typedef struct var_cell_t var_cell_t;
+typedef struct packed_cell_t packed_cell_t;
+typedef struct cell_queue_t cell_queue_t;
+typedef struct destroy_cell_t destroy_cell_t;
+typedef struct destroy_cell_queue_t destroy_cell_queue_t;
+typedef struct ext_or_cmd_t ext_or_cmd_t;
+
+/** Beginning of a RELAY cell payload. */
+typedef struct {
+ uint8_t command; /**< The end-to-end relay command. */
+ uint16_t recognized; /**< Used to tell whether cell is for us. */
+ streamid_t stream_id; /**< Which stream is this cell associated with? */
+ char integrity[4]; /**< Used to tell whether cell is corrupted. */
+ uint16_t length; /**< How long is the payload body? */
+} relay_header_t;
+
+typedef struct socks_request_t socks_request_t;
+typedef struct entry_port_cfg_t entry_port_cfg_t;
+typedef struct server_port_cfg_t server_port_cfg_t;
+
+/** Minimum length of the random part of an AUTH_CHALLENGE cell. */
+#define OR_AUTH_CHALLENGE_LEN 32
+
+/**
+ * @name Certificate types for CERTS cells.
+ *
+ * These values are defined by the protocol, and affect how an X509
+ * certificate in a CERTS cell is interpreted and used.
+ *
+ * @{ */
+/** A certificate that authenticates a TLS link key. The subject key
+ * must match the key used in the TLS handshake; it must be signed by
+ * the identity key. */
+#define OR_CERT_TYPE_TLS_LINK 1
+/** A self-signed identity certificate. The subject key must be a
+ * 1024-bit RSA key. */
+#define OR_CERT_TYPE_ID_1024 2
+/** A certificate that authenticates a key used in an AUTHENTICATE cell
+ * in the v3 handshake. The subject key must be a 1024-bit RSA key; it
+ * must be signed by the identity key */
+#define OR_CERT_TYPE_AUTH_1024 3
+/* DOCDOC */
+#define OR_CERT_TYPE_RSA_ED_CROSSCERT 7
+/**@}*/
+
+/** The first supported type of AUTHENTICATE cell. It contains
+ * a bunch of structures signed with an RSA1024 key. The signed
+ * structures include a HMAC using negotiated TLS secrets, and a digest
+ * of all cells sent or received before the AUTHENTICATE cell (including
+ * the random server-generated AUTH_CHALLENGE cell).
+ */
+#define AUTHTYPE_RSA_SHA256_TLSSECRET 1
+/** As AUTHTYPE_RSA_SHA256_TLSSECRET, but instead of using the
+ * negotiated TLS secrets, uses exported keying material from the TLS
+ * session as described in RFC 5705.
+ *
+ * Not used by today's tors, since everything that supports this
+ * also supports ED25519_SHA256_5705, which is better.
+ **/
+#define AUTHTYPE_RSA_SHA256_RFC5705 2
+/** As AUTHTYPE_RSA_SHA256_RFC5705, but uses an Ed25519 identity key to
+ * authenticate. */
+#define AUTHTYPE_ED25519_SHA256_RFC5705 3
+/*
+ * NOTE: authchallenge_type_is_better() relies on these AUTHTYPE codes
+ * being sorted in order of preference. If we someday add one with
+ * a higher numerical value that we don't like as much, we should revise
+ * authchallenge_type_is_better().
+ */
+
+/** The length of the part of the AUTHENTICATE cell body that the client and
+ * server can generate independently (when using RSA_SHA256_TLSSECRET). It
+ * contains everything except the client's timestamp, the client's randomly
+ * generated nonce, and the signature. */
+#define V3_AUTH_FIXED_PART_LEN (8+(32*6))
+/** The length of the part of the AUTHENTICATE cell body that the client
+ * signs. */
+#define V3_AUTH_BODY_LEN (V3_AUTH_FIXED_PART_LEN + 8 + 16)
+
+typedef struct or_handshake_certs_t or_handshake_certs_t;
+typedef struct or_handshake_state_t or_handshake_state_t;
+
+/** Length of Extended ORPort connection identifier. */
+#define EXT_OR_CONN_ID_LEN DIGEST_LEN /* 20 */
+/*
+ * OR_CONN_HIGHWATER and OR_CONN_LOWWATER moved from connection_or.c so
+ * channeltls.c can see them too.
+ */
+
+/** When adding cells to an OR connection's outbuf, keep adding until the
+ * outbuf is at least this long, or we run out of cells. */
+#define OR_CONN_HIGHWATER (32*1024)
+
+/** Add cells to an OR connection's outbuf whenever the outbuf's data length
+ * drops below this size. */
+#define OR_CONN_LOWWATER (16*1024)
+
+typedef struct connection_t connection_t;
+typedef struct control_connection_t control_connection_t;
+typedef struct dir_connection_t dir_connection_t;
+typedef struct edge_connection_t edge_connection_t;
+typedef struct entry_connection_t entry_connection_t;
+typedef struct listener_connection_t listener_connection_t;
+typedef struct or_connection_t or_connection_t;
+
+/** Cast a connection_t subtype pointer to a connection_t **/
+#define TO_CONN(c) (&(((c)->base_)))
+
+/** Cast a entry_connection_t subtype pointer to a connection_t **/
+#define ENTRY_TO_CONN(c) (TO_CONN(ENTRY_TO_EDGE_CONN(c)))
+
+typedef struct addr_policy_t addr_policy_t;
+
+typedef struct cached_dir_t cached_dir_t;
+
+/** Enum used to remember where a signed_descriptor_t is stored and how to
+ * manage the memory for signed_descriptor_body. */
+typedef enum {
+ /** The descriptor isn't stored on disk at all: the copy in memory is
+ * canonical; the saved_offset field is meaningless. */
+ SAVED_NOWHERE=0,
+ /** The descriptor is stored in the cached_routers file: the
+ * signed_descriptor_body is meaningless; the signed_descriptor_len and
+ * saved_offset are used to index into the mmaped cache file. */
+ SAVED_IN_CACHE,
+ /** The descriptor is stored in the cached_routers.new file: the
+ * signed_descriptor_body and saved_offset fields are both set. */
+ /* FFFF (We could also mmap the file and grow the mmap as needed, or
+ * lazy-load the descriptor text by using seek and read. We don't, for
+ * now.)
+ */
+ SAVED_IN_JOURNAL
+} saved_location_t;
+#define saved_location_bitfield_t ENUM_BF(saved_location_t)
+
+/** Enumeration: what directory object is being downloaded?
+ * This determines which schedule is selected to perform the download. */
+typedef enum {
+ DL_SCHED_GENERIC = 0,
+ DL_SCHED_CONSENSUS = 1,
+ DL_SCHED_BRIDGE = 2,
+} download_schedule_t;
+#define download_schedule_bitfield_t ENUM_BF(download_schedule_t)
+
+/** Enumeration: is the download schedule for downloading from an authority,
+ * or from any available directory mirror?
+ * During bootstrap, "any" means a fallback (or an authority, if there
+ * are no fallbacks).
+ * When we have a valid consensus, "any" means any directory server. */
+typedef enum {
+ DL_WANT_ANY_DIRSERVER = 0,
+ DL_WANT_AUTHORITY = 1,
+} download_want_authority_t;
+#define download_want_authority_bitfield_t \
+ ENUM_BF(download_want_authority_t)
+
+/** Enumeration: do we want to increment the schedule position each time a
+ * connection is attempted (these attempts can be concurrent), or do we want
+ * to increment the schedule position after a connection fails? */
+typedef enum {
+ DL_SCHED_INCREMENT_FAILURE = 0,
+ DL_SCHED_INCREMENT_ATTEMPT = 1,
+} download_schedule_increment_t;
+#define download_schedule_increment_bitfield_t \
+ ENUM_BF(download_schedule_increment_t)
+
+typedef struct download_status_t download_status_t;
+
+/** If n_download_failures is this high, the download can never happen. */
+#define IMPOSSIBLE_TO_DOWNLOAD 255
+
+/** The max size we expect router descriptor annotations we create to
+ * be. We'll accept larger ones if we see them on disk, but we won't
+ * create any that are larger than this. */
+#define ROUTER_ANNOTATION_BUF_LEN 256
+
+typedef struct signed_descriptor_t signed_descriptor_t;
+
+/** A signed integer representing a country code. */
+typedef int16_t country_t;
+
+/** Flags used to summarize the declared protocol versions of a relay,
+ * so we don't need to parse them again and again. */
+typedef struct protover_summary_flags_t {
+ /** True iff we have a proto line for this router, or a versions line
+ * from which we could infer the protocols. */
+ unsigned int protocols_known:1;
+
+ /** True iff this router has a version or protocol list that allows it to
+ * accept EXTEND2 cells. This requires Relay=2. */
+ unsigned int supports_extend2_cells: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. */
+ unsigned int supports_ed25519_link_handshake_compat:1;
+
+ /** True iff this router has a protocol list that allows it to negotiate
+ * ed25519 identity keys on a link handshake, at all. This requires some
+ * LinkAuth=X for X >= 3. */
+ unsigned int supports_ed25519_link_handshake_any:1;
+
+ /** True iff this router has a protocol list that allows it to be an
+ * introduction point supporting ed25519 authentication key which is part of
+ * 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 be an hidden
+ * service directory supporting version 3 as seen in proposal 224. This
+ * requires HSDir=2. */
+ unsigned int supports_v3_hsdir : 1;
+
+ /** True iff this router has a protocol list that allows it to be an hidden
+ * service rendezvous point supporting version 3 as seen in proposal 224.
+ * This requires HSRend=2. */
+ unsigned int supports_v3_rendezvous_point: 1;
+} protover_summary_flags_t;
+
+typedef struct routerinfo_t routerinfo_t;
+typedef struct extrainfo_t extrainfo_t;
+typedef struct routerstatus_t routerstatus_t;
+
+typedef struct microdesc_t microdesc_t;
+typedef struct node_t node_t;
+typedef struct vote_microdesc_hash_t vote_microdesc_hash_t;
+typedef struct vote_routerstatus_t vote_routerstatus_t;
+typedef struct document_signature_t document_signature_t;
+typedef struct networkstatus_voter_info_t networkstatus_voter_info_t;
+typedef struct networkstatus_sr_info_t networkstatus_sr_info_t;
+
+/** Enumerates recognized flavors of a consensus networkstatus document. All
+ * flavors of a consensus are generated from the same set of votes, but they
+ * present different types information to different versions of Tor. */
+typedef enum {
+ FLAV_NS = 0,
+ FLAV_MICRODESC = 1,
+} consensus_flavor_t;
+
+/** How many different consensus flavors are there? */
+#define N_CONSENSUS_FLAVORS ((int)(FLAV_MICRODESC)+1)
+
+typedef struct networkstatus_t networkstatus_t;
+typedef struct ns_detached_signatures_t ns_detached_signatures_t;
+typedef struct desc_store_t desc_store_t;
+typedef struct routerlist_t routerlist_t;
+typedef struct extend_info_t extend_info_t;
+typedef struct authority_cert_t authority_cert_t;
+
+/** Bitfield enum type listing types of information that directory authorities
+ * can be authoritative about, and that directory caches may or may not cache.
+ *
+ * Note that the granularity here is based on authority granularity and on
+ * cache capabilities. Thus, one particular bit may correspond in practice to
+ * a few types of directory info, so long as every authority that pronounces
+ * officially about one of the types prounounces officially about all of them,
+ * and so long as every cache that caches one of them caches all of them.
+ */
+typedef enum {
+ NO_DIRINFO = 0,
+ /** Serves/signs v3 directory information: votes, consensuses, certs */
+ V3_DIRINFO = 1 << 2,
+ /** Serves bridge descriptors. */
+ BRIDGE_DIRINFO = 1 << 4,
+ /** Serves extrainfo documents. */
+ EXTRAINFO_DIRINFO=1 << 5,
+ /** Serves microdescriptors. */
+ MICRODESC_DIRINFO=1 << 6,
+} dirinfo_type_t;
+
+#define ALL_DIRINFO ((dirinfo_type_t)((1<<7)-1))
+
+#define ONION_HANDSHAKE_TYPE_TAP 0x0000
+#define ONION_HANDSHAKE_TYPE_FAST 0x0001
+#define ONION_HANDSHAKE_TYPE_NTOR 0x0002
+#define MAX_ONION_HANDSHAKE_TYPE 0x0002
+
+typedef struct onion_handshake_state_t onion_handshake_state_t;
+typedef struct relay_crypto_t relay_crypto_t;
+typedef struct crypt_path_t crypt_path_t;
+typedef struct crypt_path_reference_t crypt_path_reference_t;
+
+#define CPATH_KEY_MATERIAL_LEN (20*2+16*2)
+
+typedef struct cpath_build_state_t cpath_build_state_t;
+
+struct create_cell_t;
+
+/** Entry in the cell stats list of a circuit; used only if CELL_STATS
+ * events are enabled. */
+typedef struct testing_cell_stats_entry_t {
+ uint8_t command; /**< cell command number. */
+ /** Waiting time in centiseconds if this event is for a removed cell,
+ * or 0 if this event is for adding a cell to the queue. 22 bits can
+ * store more than 11 hours, enough to assume that a circuit with this
+ * delay would long have been closed. */
+ unsigned int waiting_time:22;
+ unsigned int removed:1; /**< 0 for added to, 1 for removed from queue. */
+ unsigned int exitward:1; /**< 0 for app-ward, 1 for exit-ward. */
+} testing_cell_stats_entry_t;
+
+typedef struct circuit_t circuit_t;
+typedef struct origin_circuit_t origin_circuit_t;
+typedef struct or_circuit_t or_circuit_t;
+
+/** Largest number of relay_early cells that we can send on a given
+ * circuit. */
+#define MAX_RELAY_EARLY_CELLS_PER_CIRCUIT 8
+
+typedef enum path_state_t path_state_t;
+#define path_state_bitfield_t ENUM_BF(path_state_t)
+
+#if REND_COOKIE_LEN != DIGEST_LEN
+#error "The REND_TOKEN_LEN macro assumes REND_COOKIE_LEN == DIGEST_LEN"
+#endif
+#define REND_TOKEN_LEN DIGEST_LEN
+
+/** Convert a circuit subtype to a circuit_t. */
+#define TO_CIRCUIT(x) (&((x)->base_))
+
+/** @name Isolation flags
+
+ Ways to isolate client streams
+
+ @{
+*/
+/** Isolate based on destination port */
+#define ISO_DESTPORT (1u<<0)
+/** Isolate based on destination address */
+#define ISO_DESTADDR (1u<<1)
+/** Isolate based on SOCKS authentication */
+#define ISO_SOCKSAUTH (1u<<2)
+/** Isolate based on client protocol choice */
+#define ISO_CLIENTPROTO (1u<<3)
+/** Isolate based on client address */
+#define ISO_CLIENTADDR (1u<<4)
+/** Isolate based on session group (always on). */
+#define ISO_SESSIONGRP (1u<<5)
+/** Isolate based on newnym epoch (always on). */
+#define ISO_NYM_EPOCH (1u<<6)
+/** Isolate all streams (Internal only). */
+#define ISO_STREAM (1u<<7)
+/**@}*/
+
+/** Default isolation level for ports. */
+#define ISO_DEFAULT (ISO_CLIENTADDR|ISO_SOCKSAUTH|ISO_SESSIONGRP|ISO_NYM_EPOCH)
+
+/** Indicates that we haven't yet set a session group on a port_cfg_t. */
+#define SESSION_GROUP_UNSET -1
+/** Session group reserved for directory connections */
+#define SESSION_GROUP_DIRCONN -2
+/** Session group reserved for resolve requests launched by a controller */
+#define SESSION_GROUP_CONTROL_RESOLVE -3
+/** First automatically allocated session group number */
+#define SESSION_GROUP_FIRST_AUTO -4
+
+typedef struct port_cfg_t port_cfg_t;
+typedef struct routerset_t routerset_t;
+
+/** A magic value for the (Socks|OR|...)Port options below, telling Tor
+ * to pick its own port. */
+#define CFG_AUTO_PORT 0xc4005e
+
+typedef struct or_options_t or_options_t;
+
+#define LOG_PROTOCOL_WARN (get_protocol_warning_severity_level())
+
+typedef struct or_state_t or_state_t;
+
+#define MAX_SOCKS_ADDR_LEN 256
+
+/********************************* circuitbuild.c **********************/
+
+/** How many hops does a general-purpose circuit have by default? */
+#define DEFAULT_ROUTE_LEN 3
+
+/* Circuit Build Timeout "public" structures. */
+
+/** Precision multiplier for the Bw weights */
+#define BW_WEIGHT_SCALE 10000
+#define BW_MIN_WEIGHT_SCALE 1
+#define BW_MAX_WEIGHT_SCALE INT32_MAX
+
+typedef struct circuit_build_times_s circuit_build_times_t;
+
+/********************************* config.c ***************************/
+
+/********************************* connection_edge.c *************************/
+
+/** Enumerates possible origins of a client-side address mapping. */
+typedef enum {
+ /** We're remapping this address because the controller told us to. */
+ ADDRMAPSRC_CONTROLLER,
+ /** We're remapping this address because of an AutomapHostsOnResolve
+ * configuration. */
+ ADDRMAPSRC_AUTOMAP,
+ /** We're remapping this address because our configuration (via torrc, the
+ * command line, or a SETCONF command) told us to. */
+ ADDRMAPSRC_TORRC,
+ /** We're remapping this address because we have TrackHostExit configured,
+ * and we want to remember to use the same exit next time. */
+ ADDRMAPSRC_TRACKEXIT,
+ /** We're remapping this address because we got a DNS resolution from a
+ * Tor server that told us what its value was. */
+ ADDRMAPSRC_DNS,
+
+ /** No remapping has occurred. This isn't a possible value for an
+ * addrmap_entry_t; it's used as a null value when we need to answer "Why
+ * did this remapping happen." */
+ ADDRMAPSRC_NONE
+} addressmap_entry_source_t;
+#define addressmap_entry_source_bitfield_t ENUM_BF(addressmap_entry_source_t)
+
+#define WRITE_STATS_INTERVAL (24*60*60)
+
+/********************************* dirvote.c ************************/
+
+typedef struct vote_timing_t vote_timing_t;
+
+/********************************* microdesc.c *************************/
+
+typedef struct microdesc_cache_t microdesc_cache_t;
+
+/********************************* rendcommon.c ***************************/
+
+typedef struct rend_authorized_client_t rend_authorized_client_t;
+typedef struct rend_encoded_v2_service_descriptor_t
+ rend_encoded_v2_service_descriptor_t;
+
+/** The maximum number of non-circuit-build-timeout failures a hidden
+ * service client will tolerate while trying to build a circuit to an
+ * introduction point. See also rend_intro_point_t.unreachable_count. */
+#define MAX_INTRO_POINT_REACHABILITY_FAILURES 5
+
+/** The minimum and maximum number of distinct INTRODUCE2 cells which a
+ * hidden service's introduction point will receive before it begins to
+ * expire. */
+#define INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS 16384
+/* Double the minimum value so the interval is [min, min * 2]. */
+#define INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS \
+ (INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS * 2)
+
+/** The minimum number of seconds that an introduction point will last
+ * before expiring due to old age. (If it receives
+ * INTRO_POINT_LIFETIME_INTRODUCTIONS INTRODUCE2 cells, it may expire
+ * sooner.)
+ *
+ * XXX Should this be configurable? */
+#define INTRO_POINT_LIFETIME_MIN_SECONDS (18*60*60)
+/** The maximum number of seconds that an introduction point will last
+ * before expiring due to old age.
+ *
+ * XXX Should this be configurable? */
+#define INTRO_POINT_LIFETIME_MAX_SECONDS (24*60*60)
+
+/** The maximum number of circuit creation retry we do to an intro point
+ * before giving up. We try to reuse intro point that fails during their
+ * lifetime so this is a hard limit on the amount of time we do that. */
+#define MAX_INTRO_POINT_CIRCUIT_RETRIES 3
+
+typedef struct rend_intro_point_t rend_intro_point_t;
+typedef struct rend_service_descriptor_t rend_service_descriptor_t;
+
+/********************************* routerlist.c ***************************/
+
+typedef struct dir_server_t dir_server_t;
+
+#define RELAY_REQUIRED_MIN_BANDWIDTH (75*1024)
+#define BRIDGE_REQUIRED_MIN_BANDWIDTH (50*1024)
+
+#define ROUTER_MAX_DECLARED_BANDWIDTH INT32_MAX
+
+typedef struct tor_version_t tor_version_t;
+
+#endif /* !defined(TOR_OR_H) */
diff --git a/src/core/or/or_circuit_st.h b/src/core/or/or_circuit_st.h
new file mode 100644
index 0000000000..b5e21d9867
--- /dev/null
+++ b/src/core/or/or_circuit_st.h
@@ -0,0 +1,80 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef OR_CIRCUIT_ST_H
+#define OR_CIRCUIT_ST_H
+
+#include "core/or/or.h"
+
+#include "core/or/circuit_st.h"
+#include "core/or/crypt_path_st.h"
+
+struct onion_queue_t;
+
+/** An or_circuit_t holds information needed to implement a circuit at an
+ * OR. */
+struct or_circuit_t {
+ circuit_t base_;
+
+ /** Pointer to an entry on the onion queue, if this circuit is waiting for a
+ * chance to give an onionskin to a cpuworker. Used only in onion.c */
+ struct onion_queue_t *onionqueue_entry;
+ /** Pointer to a workqueue entry, if this circuit has given an onionskin to
+ * a cpuworker and is waiting for a response. Used to decide whether it is
+ * safe to free a circuit or if it is still in use by a cpuworker. */
+ struct workqueue_entry_s *workqueue_entry;
+
+ /** The circuit_id used in the previous (backward) hop of this circuit. */
+ circid_t p_circ_id;
+ /** Queue of cells waiting to be transmitted on p_conn. */
+ cell_queue_t p_chan_cells;
+ /** The channel that is previous in this circuit. */
+ channel_t *p_chan;
+ /**
+ * Circuit mux associated with p_chan to which this circuit is attached;
+ * NULL if we have no p_chan.
+ */
+ circuitmux_t *p_mux;
+ /** Linked list of Exit streams associated with this circuit. */
+ edge_connection_t *n_streams;
+ /** Linked list of Exit streams associated with this circuit that are
+ * still being resolved. */
+ edge_connection_t *resolving_streams;
+
+ /** Cryptographic state used for encrypting and authenticating relay
+ * cells to and from this hop. */
+ relay_crypto_t crypto;
+
+ /** Points to spliced circuit if purpose is REND_ESTABLISHED, and circuit
+ * is not marked for close. */
+ struct or_circuit_t *rend_splice;
+
+ /** Stores KH for the handshake. */
+ char rend_circ_nonce[DIGEST_LEN];/* KH in tor-spec.txt */
+
+ /** How many more relay_early cells can we send on this circuit, according
+ * to the specification? */
+ unsigned int remaining_relay_early_cells : 4;
+
+ /* We have already received an INTRODUCE1 cell on this circuit. */
+ unsigned int already_received_introduce1 : 1;
+
+ /** If set, this circuit carries HS traffic. Consider it in any HS
+ * statistics. */
+ unsigned int circuit_carries_hs_traffic_stats : 1;
+
+ /** Number of cells that were removed from circuit queue; reset every
+ * time when writing buffer stats to disk. */
+ uint32_t processed_cells;
+
+ /** Total time in milliseconds that cells spent in both app-ward and
+ * exit-ward queues of this circuit; reset every time when writing
+ * buffer stats to disk. */
+ uint64_t total_cell_waiting_time;
+};
+
+#endif
+
diff --git a/src/core/or/or_connection_st.h b/src/core/or/or_connection_st.h
new file mode 100644
index 0000000000..020a717c11
--- /dev/null
+++ b/src/core/or/or_connection_st.h
@@ -0,0 +1,92 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef OR_CONNECTION_ST_H
+#define OR_CONNECTION_ST_H
+
+#include "core/or/connection_st.h"
+#include "lib/evloop/token_bucket.h"
+
+struct tor_tls_t;
+
+/** Subtype of connection_t for an "OR connection" -- that is, one that speaks
+ * cells over TLS. */
+struct or_connection_t {
+ connection_t base_;
+
+ /** Hash of the public RSA key for the other side's identity key, or zeroes
+ * if the other side hasn't shown us a valid identity key. */
+ char identity_digest[DIGEST_LEN];
+
+ /** Extended ORPort connection identifier. */
+ char *ext_or_conn_id;
+ /** 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
+ * client. */
+ char *ext_or_auth_correct_client_hash;
+ /** String carrying the name of the pluggable transport
+ * (e.g. "obfs2") that is obfuscating this connection. If no
+ * pluggable transports are used, it's NULL. */
+ char *ext_or_transport;
+
+ char *nickname; /**< Nickname of OR on other side (if any). */
+
+ struct tor_tls_t *tls; /**< TLS connection state. */
+ int tls_error; /**< Last tor_tls error code. */
+ /** When we last used this conn for any client traffic. If not
+ * recent, we can rate limit it further. */
+
+ /* 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>. */
+
+ /** 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
+ * sure we aren't getting MITMed, either because we're connected to an
+ * address listed in a server descriptor, or because an authenticated
+ * NETINFO cell listed the address we're connected to as recognized. */
+ unsigned int is_canonical:1;
+
+ /** True iff this is an outgoing connection. */
+ unsigned int is_outgoing:1;
+ unsigned int proxy_type:2; /**< One of PROXY_NONE...PROXY_SOCKS5 */
+ unsigned int wide_circ_ids:1;
+ /** True iff this connection has had its bootstrap failure logged with
+ * control_event_bootstrap_problem. */
+ unsigned int have_noted_bootstrap_problem:1;
+ /** True iff this is a client connection and its address has been put in the
+ * geoip cache and handled by the DoS mitigation subsystem. We use this to
+ * insure we have a coherent count of concurrent connection. */
+ unsigned int tracked_for_dos_mitigation : 1;
+
+ uint16_t link_proto; /**< What protocol version are we using? 0 for
+ * "none negotiated yet." */
+ uint16_t idle_timeout; /**< How long can this connection sit with no
+ * circuits on it before we close it? Based on
+ * IDLE_CIRCUIT_TIMEOUT_{NON,}CANONICAL and
+ * on is_canonical, randomized. */
+ or_handshake_state_t *handshake_state; /**< If we are setting this connection
+ * up, state information to do so. */
+
+ time_t timestamp_lastempty; /**< When was the outbuf last completely empty?*/
+
+ token_bucket_rw_t bucket; /**< Used for rate limiting when the connection is
+ * in state CONN_OPEN. */
+
+ /*
+ * Count the number of bytes flushed out on this orconn, and the number of
+ * bytes TLS actually sent - used for overhead estimation for scheduling.
+ */
+ uint64_t bytes_xmitted, bytes_xmitted_by_tls;
+};
+
+#endif
diff --git a/src/core/or/or_handshake_certs_st.h b/src/core/or/or_handshake_certs_st.h
new file mode 100644
index 0000000000..38e798b5e2
--- /dev/null
+++ b/src/core/or/or_handshake_certs_st.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-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef OR_HANDSHAKE_CERTS_ST
+#define OR_HANDSHAKE_CERTS_ST
+
+struct tor_x509_cert_t;
+
+/** Structure to hold all the certificates we've received on an OR connection
+ */
+struct or_handshake_certs_t {
+ /** True iff we originated this connection. */
+ int started_here;
+ /** The cert for the 'auth' RSA key that's supposed to sign the AUTHENTICATE
+ * cell. Signed with the RSA identity key. */
+ struct tor_x509_cert_t *auth_cert;
+ /** The cert for the 'link' RSA key that was used to negotiate the TLS
+ * connection. Signed with the RSA identity key. */
+ struct tor_x509_cert_t *link_cert;
+ /** A self-signed identity certificate: the RSA identity key signed
+ * with itself. */
+ struct tor_x509_cert_t *id_cert;
+ /** The Ed25519 signing key, signed with the Ed25519 identity key. */
+ struct tor_cert_st *ed_id_sign;
+ /** A digest of the X509 link certificate for the TLS connection, signed
+ * with the Ed25519 siging key. */
+ struct tor_cert_st *ed_sign_link;
+ /** The Ed25519 authentication key (that's supposed to sign an AUTHENTICATE
+ * cell) , signed with the Ed25519 siging key. */
+ struct tor_cert_st *ed_sign_auth;
+ /** The Ed25519 identity key, crosssigned with the RSA identity key. */
+ uint8_t *ed_rsa_crosscert;
+ /** The length of <b>ed_rsa_crosscert</b> in bytes */
+ size_t ed_rsa_crosscert_len;
+};
+
+#endif
diff --git a/src/core/or/or_handshake_state_st.h b/src/core/or/or_handshake_state_st.h
new file mode 100644
index 0000000000..4ee095d9af
--- /dev/null
+++ b/src/core/or/or_handshake_state_st.h
@@ -0,0 +1,78 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef OR_HANDSHAKE_STATE_ST
+#define OR_HANDSHAKE_STATE_ST
+
+/** Stores flags and information related to the portion of a v2/v3 Tor OR
+ * connection handshake that happens after the TLS handshake is finished.
+ */
+struct or_handshake_state_t {
+ /** When was the VERSIONS cell sent on this connection? Used to get
+ * an estimate of the skew in the returning NETINFO reply. */
+ time_t sent_versions_at;
+ /** True iff we originated this connection */
+ unsigned int started_here : 1;
+ /** True iff we have received and processed a VERSIONS cell. */
+ unsigned int received_versions : 1;
+ /** True iff we have received and processed an AUTH_CHALLENGE cell */
+ unsigned int received_auth_challenge : 1;
+ /** True iff we have received and processed a CERTS cell. */
+ unsigned int received_certs_cell : 1;
+ /** True iff we have received and processed an AUTHENTICATE cell */
+ unsigned int received_authenticate : 1;
+
+ /* True iff we've received valid authentication to some identity. */
+ unsigned int authenticated : 1;
+ unsigned int authenticated_rsa : 1;
+ unsigned int authenticated_ed25519 : 1;
+
+ /* True iff we have sent a netinfo cell */
+ unsigned int sent_netinfo : 1;
+
+ /** The signing->ed25519 link certificate corresponding to the x509
+ * certificate we used on the TLS connection (if this is a server-side
+ * connection). We make a copy of this here to prevent a race condition
+ * caused by TLS context rotation. */
+ struct tor_cert_st *own_link_cert;
+
+ /** True iff we should feed outgoing cells into digest_sent and
+ * digest_received respectively.
+ *
+ * From the server's side of the v3 handshake, we want to capture everything
+ * from the VERSIONS cell through and including the AUTH_CHALLENGE cell.
+ * From the client's, we want to capture everything from the VERSIONS cell
+ * through but *not* including the AUTHENTICATE cell.
+ *
+ * @{ */
+ unsigned int digest_sent_data : 1;
+ unsigned int digest_received_data : 1;
+ /**@}*/
+
+ /** Identity RSA digest that we have received and authenticated for our peer
+ * on this connection. */
+ uint8_t authenticated_rsa_peer_id[DIGEST_LEN];
+ /** Identity Ed25519 public key that we have received and authenticated for
+ * our peer on this connection. */
+ ed25519_public_key_t authenticated_ed25519_peer_id;
+
+ /** Digests of the cells that we have sent or received as part of a V3
+ * handshake. Used for making and checking AUTHENTICATE cells.
+ *
+ * @{
+ */
+ crypto_digest_t *digest_sent;
+ crypto_digest_t *digest_received;
+ /** @} */
+
+ /** Certificates that a connection initiator sent us in a CERTS cell; we're
+ * holding on to them until we get an AUTHENTICATE cell.
+ */
+ or_handshake_certs_t *certs;
+};
+
+#endif
+
diff --git a/src/core/or/origin_circuit_st.h b/src/core/or/origin_circuit_st.h
new file mode 100644
index 0000000000..e7b864e825
--- /dev/null
+++ b/src/core/or/origin_circuit_st.h
@@ -0,0 +1,290 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef ORIGIN_CIRCUIT_ST_H
+#define ORIGIN_CIRCUIT_ST_H
+
+#include "core/or/or.h"
+
+#include "core/or/circuit_st.h"
+
+struct onion_queue_t;
+
+/**
+ * Describes the circuit building process in simplified terms based
+ * on the path bias accounting state for a circuit.
+ *
+ * NOTE: These state values are enumerated in the order for which we
+ * expect circuits to transition through them. If you add states,
+ * you need to preserve this overall ordering. The various pathbias
+ * state transition and accounting functions (pathbias_mark_* and
+ * pathbias_count_*) contain ordinal comparisons to enforce proper
+ * state transitions for corrections.
+ *
+ * This state machine and the associated logic was created to prevent
+ * miscounting due to unknown cases of circuit reuse. See also tickets
+ * #6475 and #7802.
+ */
+enum path_state_t {
+ /** This circuit is "new". It has not yet completed a first hop
+ * or been counted by the path bias code. */
+ PATH_STATE_NEW_CIRC = 0,
+ /** This circuit has completed one/two hops, and has been counted by
+ * the path bias logic. */
+ PATH_STATE_BUILD_ATTEMPTED = 1,
+ /** This circuit has been completely built */
+ PATH_STATE_BUILD_SUCCEEDED = 2,
+ /** Did we try to attach any SOCKS streams or hidserv introductions to
+ * this circuit?
+ *
+ * Note: If we ever implement end-to-end stream timing through test
+ * stream probes (#5707), we must *not* set this for those probes
+ * (or any other automatic streams) because the adversary could
+ * just tag at a later point.
+ */
+ PATH_STATE_USE_ATTEMPTED = 3,
+ /** Did any SOCKS streams or hidserv introductions actually succeed on
+ * this circuit?
+ *
+ * If any streams detatch/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.
+ */
+ PATH_STATE_USE_SUCCEEDED = 4,
+
+ /**
+ * This is a special state to indicate that we got a corrupted
+ * relay cell on a circuit and we don't intend to probe it.
+ */
+ PATH_STATE_USE_FAILED = 5,
+
+ /**
+ * This is a special state to indicate that we already counted
+ * the circuit. Used to guard against potential state machine
+ * violations.
+ */
+ PATH_STATE_ALREADY_COUNTED = 6,
+};
+
+/** An origin_circuit_t holds data necessary to build and use a circuit.
+ */
+struct origin_circuit_t {
+ circuit_t base_;
+
+ /** Linked list of AP streams (or EXIT streams if hidden service)
+ * associated with this circuit. */
+ edge_connection_t *p_streams;
+
+ /** Bytes read on this circuit since last call to
+ * control_event_circ_bandwidth_used(). Only used if we're configured
+ * to emit CIRC_BW events. */
+ uint32_t n_read_circ_bw;
+
+ /** Bytes written to on this circuit since last call to
+ * control_event_circ_bandwidth_used(). Only used if we're configured
+ * to emit CIRC_BW events. */
+ uint32_t n_written_circ_bw;
+
+ /** Total known-valid relay cell bytes since last call to
+ * control_event_circ_bandwidth_used(). Only used if we're configured
+ * to emit CIRC_BW events. */
+ uint32_t n_delivered_read_circ_bw;
+
+ /** Total written relay cell bytes since last call to
+ * control_event_circ_bandwidth_used(). Only used if we're configured
+ * to emit CIRC_BW events. */
+ uint32_t n_delivered_written_circ_bw;
+
+ /** Total overhead data in all known-valid relay data cells since last
+ * call to control_event_circ_bandwidth_used(). Only used if we're
+ * configured to emit CIRC_BW events. */
+ uint32_t n_overhead_read_circ_bw;
+
+ /** Total written overhead data in all relay data cells since last call to
+ * control_event_circ_bandwidth_used(). Only used if we're configured
+ * to emit CIRC_BW events. */
+ uint32_t n_overhead_written_circ_bw;
+
+ /** Build state for this circuit. It includes the intended path
+ * length, the chosen exit router, rendezvous information, etc.
+ */
+ cpath_build_state_t *build_state;
+ /** The doubly-linked list of crypt_path_t entries, one per hop,
+ * for this circuit. This includes ciphers for each hop,
+ * integrity-checking digests for each hop, and package/delivery
+ * windows for each hop.
+ */
+ crypt_path_t *cpath;
+
+ /** Holds all rendezvous data on either client or service side. */
+ rend_data_t *rend_data;
+
+ /** Holds hidden service identifier on either client or service side. This
+ * is for both introduction and rendezvous circuit. */
+ struct hs_ident_circuit_t *hs_ident;
+
+ /** Holds the data that the entry guard system uses to track the
+ * status of the guard this circuit is using, and thereby to determine
+ * whether this circuit can be used. */
+ struct circuit_guard_state_t *guard_state;
+
+ /** Index into global_origin_circuit_list for this circuit. -1 if not
+ * present. */
+ int global_origin_circuit_list_idx;
+
+ /** How many more relay_early cells can we send on this circuit, according
+ * to the specification? */
+ unsigned int remaining_relay_early_cells : 4;
+
+ /** Set if this circuit is insanely old and we already informed the user */
+ unsigned int is_ancient : 1;
+
+ /** Set if this circuit has already been opened. Used to detect
+ * cannibalized circuits. */
+ unsigned int has_opened : 1;
+
+ /**
+ * Path bias state machine. Used to ensure integrity of our
+ * circuit building and usage accounting. See path_state_t
+ * for more details.
+ */
+ path_state_bitfield_t path_state : 3;
+
+ /* If this flag is set, we should not consider attaching any more
+ * connections to this circuit. */
+ unsigned int unusable_for_new_conns : 1;
+
+ /**
+ * Tristate variable to guard against pathbias miscounting
+ * due to circuit purpose transitions changing the decision
+ * of pathbias_should_count(). This variable is informational
+ * only. The current results of pathbias_should_count() are
+ * the official decision for pathbias accounting.
+ */
+ uint8_t pathbias_shouldcount;
+#define PATHBIAS_SHOULDCOUNT_UNDECIDED 0
+#define PATHBIAS_SHOULDCOUNT_IGNORED 1
+#define PATHBIAS_SHOULDCOUNT_COUNTED 2
+
+ /** For path probing. Store the temporary probe stream ID
+ * for response comparison */
+ streamid_t pathbias_probe_id;
+
+ /** For path probing. Store the temporary probe address nonce
+ * (in host byte order) for response comparison. */
+ uint32_t pathbias_probe_nonce;
+
+ /** Set iff this is a hidden-service circuit which has timed out
+ * according to our current circuit-build timeout, but which has
+ * been kept around because it might still succeed in connecting to
+ * its destination, and which is not a fully-connected rendezvous
+ * circuit.
+ *
+ * (We clear this flag for client-side rendezvous circuits when they
+ * are 'joined' to the other side's rendezvous circuit, so that
+ * connection_ap_handshake_attach_circuit can put client streams on
+ * the circuit. We also clear this flag for service-side rendezvous
+ * circuits when they are 'joined' to a client's rend circ, but only
+ * for symmetry with the client case. Client-side introduction
+ * circuits are closed when we get a joined rend circ, and
+ * service-side introduction circuits never have this flag set.) */
+ unsigned int hs_circ_has_timed_out : 1;
+
+ /** Set iff this circuit has been given a relaxed timeout because
+ * no circuits have opened. Used to prevent spamming logs. */
+ unsigned int relaxed_timeout : 1;
+
+ /** Set iff this is a service-side rendezvous circuit for which a
+ * new connection attempt has been launched. We consider launching
+ * a new service-side rend circ to a client when the previous one
+ * fails; now that we don't necessarily close a service-side rend
+ * circ when we launch a new one to the same client, this flag keeps
+ * us from launching two retries for the same failed rend circ. */
+ unsigned int hs_service_side_rend_circ_has_been_relaunched : 1;
+
+ /** What commands were sent over this circuit that decremented the
+ * RELAY_EARLY counter? This is for debugging task 878. */
+ uint8_t relay_early_commands[MAX_RELAY_EARLY_CELLS_PER_CIRCUIT];
+
+ /** How many RELAY_EARLY cells have been sent over this circuit? This is
+ * for debugging task 878, too. */
+ int relay_early_cells_sent;
+
+ /** The next stream_id that will be tried when we're attempting to
+ * construct a new AP stream originating at this circuit. */
+ streamid_t next_stream_id;
+
+ /* The intro key replaces the hidden service's public key if purpose is
+ * S_ESTABLISH_INTRO or S_INTRO, provided that no unversioned rendezvous
+ * descriptor is used. */
+ crypto_pk_t *intro_key;
+
+ /** Quasi-global identifier for this circuit; used for control.c */
+ /* XXXX NM This can get re-used after 2**32 circuits. */
+ uint32_t global_identifier;
+
+ /** True if we have associated one stream to this circuit, thereby setting
+ * the isolation parameters for this circuit. Note that this doesn't
+ * necessarily mean that we've <em>attached</em> any streams to the circuit:
+ * we may only have marked up this circuit during the launch process.
+ */
+ unsigned int isolation_values_set : 1;
+ /** True iff any stream has <em>ever</em> been attached to this circuit.
+ *
+ * In a better world we could use timestamp_dirty for this, but
+ * timestamp_dirty is far too overloaded at the moment.
+ */
+ unsigned int isolation_any_streams_attached : 1;
+
+ /** A bitfield of ISO_* flags for every isolation field such that this
+ * circuit has had streams with more than one value for that field
+ * attached to it. */
+ uint8_t isolation_flags_mixed;
+
+ /** @name Isolation parameters
+ *
+ * If any streams have been associated with this circ (isolation_values_set
+ * == 1), and all streams associated with the circuit have had the same
+ * value for some field ((isolation_flags_mixed & ISO_FOO) == 0), then these
+ * elements hold the value for that field.
+ *
+ * Note again that "associated" is not the same as "attached": we
+ * preliminarily associate streams with a circuit while the circuit is being
+ * launched, so that we can tell whether we need to launch more circuits.
+ *
+ * @{
+ */
+ uint8_t client_proto_type;
+ uint8_t client_proto_socksver;
+ uint16_t dest_port;
+ tor_addr_t client_addr;
+ char *dest_address;
+ int session_group;
+ unsigned nym_epoch;
+ size_t socks_username_len;
+ uint8_t socks_password_len;
+ /* Note that the next two values are NOT NUL-terminated; see
+ socks_username_len and socks_password_len for their lengths. */
+ char *socks_username;
+ char *socks_password;
+ /** Global identifier for the first stream attached here; used by
+ * ISO_STREAM. */
+ uint64_t associated_isolated_stream_global_id;
+ /**@}*/
+ /** A list of addr_policy_t for this circuit in particular. Used by
+ * adjust_exit_policy_from_exitpolicy_failure.
+ */
+ smartlist_t *prepend_policy;
+
+ /** How long do we wait before closing this circuit if it remains
+ * completely idle after it was built, in seconds? This value
+ * is randomized on a per-circuit basis from CircuitsAvailableTimoeut
+ * to 2*CircuitsAvailableTimoeut. */
+ int circuit_idle_timeout;
+
+};
+
+#endif
diff --git a/src/or/policies.c b/src/core/or/policies.c
index 1210ca687d..e01415f95e 100644
--- a/src/or/policies.c
+++ b/src/core/or/policies.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,18 +17,27 @@
#define POLICIES_PRIVATE
-#include "or.h"
-#include "bridges.h"
-#include "config.h"
-#include "dirserv.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "policies.h"
-#include "router.h"
-#include "routerparse.h"
-#include "geoip.h"
+#include "core/or/or.h"
+#include "feature/client/bridges.h"
+#include "app/config/config.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/stats/geoip.h"
#include "ht.h"
+#include "lib/encoding/confline.h"
+
+#include "core/or/addr_policy_st.h"
+#include "feature/dirclient/dir_server_st.h"
+#include "feature/nodelist/microdesc_st.h"
+#include "feature/nodelist/node_st.h"
+#include "core/or/port_cfg_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerstatus_st.h"
/** Policy that addresses for incoming SOCKS connections must match. */
static smartlist_t *socks_policy = NULL;
@@ -2401,7 +2410,7 @@ policy_summary_item_split(policy_summary_item_t* old, uint16_t new_starts)
#define REJECT_CUTOFF_SCALE_IPV4 (0)
/* Ports are rejected in an IPv4 summary if they are rejected in more than two
* IPv4 /8 address blocks */
-#define REJECT_CUTOFF_COUNT_IPV4 (U64_LITERAL(1) << \
+#define REJECT_CUTOFF_COUNT_IPV4 (UINT64_C(1) << \
(IPV4_BITS - REJECT_CUTOFF_SCALE_IPV4 - 7))
#define IPV6_BITS (128)
@@ -2413,7 +2422,7 @@ policy_summary_item_split(policy_summary_item_t* old, uint16_t new_starts)
* some scattered smaller blocks) have been allocated to the RIRs.
* Network providers are typically allocated one or more IPv6 /32s.
*/
-#define REJECT_CUTOFF_COUNT_IPV6 (U64_LITERAL(1) << \
+#define REJECT_CUTOFF_COUNT_IPV6 (UINT64_C(1) << \
(IPV6_BITS - REJECT_CUTOFF_SCALE_IPV6 - 16))
/** Split an exit policy summary so that prt_min and prt_max
@@ -2508,7 +2517,7 @@ policy_summary_reject(smartlist_t *summary,
* in the range. */
count = UINT64_MAX;
} else {
- count = (U64_LITERAL(1) << (addrbits - scale - maskbits));
+ count = (UINT64_C(1) << (addrbits - scale - maskbits));
}
tor_assert_nonfatal_once(count > 0);
while (i < smartlist_len(summary) &&
@@ -3136,4 +3145,3 @@ policies_free_all(void)
}
HT_CLEAR(policy_map, &policy_root);
}
-
diff --git a/src/or/policies.h b/src/core/or/policies.h
index 4879acdd8d..7da3ba031f 100644
--- a/src/or/policies.h
+++ b/src/core/or/policies.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -34,6 +34,39 @@ typedef enum firewall_connection_t {
typedef int exit_policy_parser_cfg_t;
+/** Outcome of applying an address policy to an address. */
+typedef enum {
+ /** The address was accepted */
+ ADDR_POLICY_ACCEPTED=0,
+ /** The address was rejected */
+ ADDR_POLICY_REJECTED=-1,
+ /** Part of the address was unknown, but as far as we can tell, it was
+ * accepted. */
+ ADDR_POLICY_PROBABLY_ACCEPTED=1,
+ /** Part of the address was unknown, but as far as we can tell, it was
+ * rejected. */
+ ADDR_POLICY_PROBABLY_REJECTED=2,
+} addr_policy_result_t;
+
+/** A single entry in a parsed policy summary, describing a range of ports. */
+typedef struct short_policy_entry_t {
+ uint16_t min_port, max_port;
+} short_policy_entry_t;
+
+/** A short_poliy_t is the parsed version of a policy summary. */
+typedef struct short_policy_t {
+ /** True if the members of 'entries' are port ranges to accept; false if
+ * they are port ranges to reject */
+ unsigned int is_accept : 1;
+ /** The actual number of values in 'entries'. */
+ unsigned int n_entries : 31;
+ /** An array of 0 or more short_policy_entry_t values, each describing a
+ * range of ports that this policy accepts or rejects (depending on the
+ * value of is_accept).
+ */
+ short_policy_entry_t entries[FLEXIBLE_ARRAY_MEMBER];
+} 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);
@@ -88,7 +121,8 @@ int policies_parse_exit_policy_from_options(
uint32_t local_address,
const tor_addr_t *ipv6_local_address,
smartlist_t **result);
-int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
+struct config_line_t;
+int policies_parse_exit_policy(struct config_line_t *cfg, smartlist_t **dest,
exit_policy_parser_cfg_t options,
const smartlist_t *configured_addresses);
void policies_parse_exit_policy_reject_private(
@@ -151,4 +185,3 @@ STATIC const tor_addr_port_t * fascist_firewall_choose_address(
#endif /* defined(POLICIES_PRIVATE) */
#endif /* !defined(TOR_POLICIES_H) */
-
diff --git a/src/core/or/port_cfg_st.h b/src/core/or/port_cfg_st.h
new file mode 100644
index 0000000000..19410871ed
--- /dev/null
+++ b/src/core/or/port_cfg_st.h
@@ -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-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef PORT_CFG_ST_H
+#define PORT_CFG_ST_H
+
+#include "core/or/entry_port_cfg_st.h"
+#include "core/or/server_port_cfg_st.h"
+
+/** Configuration for a single port that we're listening on. */
+struct port_cfg_t {
+ tor_addr_t addr; /**< The actual IP to listen on, if !is_unix_addr. */
+ int port; /**< The configured port, or CFG_AUTO_PORT to tell Tor to pick its
+ * own port. */
+ uint8_t type; /**< One of CONN_TYPE_*_LISTENER */
+ unsigned is_unix_addr : 1; /**< True iff this is an AF_UNIX address. */
+
+ unsigned is_group_writable : 1;
+ unsigned is_world_writable : 1;
+ unsigned relax_dirmode_check : 1;
+
+ entry_port_cfg_t entry_cfg;
+
+ server_port_cfg_t server_cfg;
+
+ /* Unix sockets only: */
+ /** Path for an AF_UNIX address */
+ char unix_addr[FLEXIBLE_ARRAY_MEMBER];
+};
+
+#endif
+
diff --git a/src/or/protover.c b/src/core/or/protover.c
index 0e8902196d..362a5becac 100644
--- a/src/or/protover.c
+++ b/src/core/or/protover.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -23,9 +23,9 @@
#define PROTOVER_PRIVATE
-#include "or.h"
-#include "protover.h"
-#include "routerparse.h"
+#include "core/or/or.h"
+#include "core/or/protover.h"
+#include "feature/nodelist/routerparse.h"
#ifndef HAVE_RUST
diff --git a/src/or/protover.h b/src/core/or/protover.h
index c46a13de66..7319d2f8c4 100644
--- a/src/or/protover.h
+++ b/src/core/or/protover.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,7 +9,10 @@
#ifndef TOR_PROTOVER_H
#define TOR_PROTOVER_H
-#include "container.h"
+#include <stdbool.h>
+#include "lib/cc/torint.h"
+#include "lib/testsupport/testsupport.h"
+struct smartlist_t;
/** The first version of Tor that included "proto" entries in its
* descriptors. Authorities should use this to decide whether to
@@ -47,7 +50,7 @@ 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);
-char *protover_compute_vote(const smartlist_t *list_of_proto_strings,
+char *protover_compute_vote(const struct smartlist_t *list_of_proto_strings,
int threshold);
const char *protover_compute_for_old_tor(const char *version);
int protocol_list_supports_protocol(const char *list, protocol_type_t tp,
@@ -75,12 +78,12 @@ typedef struct proto_entry_t {
*/
char *name;
/** Smartlist of proto_range_t */
- smartlist_t *ranges;
+ struct smartlist_t *ranges;
} proto_entry_t;
#if !defined(HAVE_RUST) && defined(TOR_UNIT_TESTS)
-STATIC smartlist_t *parse_protocol_list(const char *s);
-STATIC char *encode_protocol_list(const smartlist_t *sl);
+STATIC struct smartlist_t *parse_protocol_list(const char *s);
+STATIC char *encode_protocol_list(const struct smartlist_t *sl);
STATIC const char *protocol_type_to_str(protocol_type_t pr);
STATIC int str_to_protocol_type(const char *s, protocol_type_t *pr_out);
STATIC void proto_entry_free_(proto_entry_t *entry);
@@ -92,4 +95,3 @@ STATIC void proto_entry_free_(proto_entry_t *entry);
#endif /* defined(PROTOVER_PRIVATE) */
#endif /* !defined(TOR_PROTOVER_H) */
-
diff --git a/src/or/reasons.c b/src/core/or/reasons.c
index ce1259b8f3..7a1e09e9f8 100644
--- a/src/or/reasons.c
+++ b/src/core/or/reasons.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,9 +14,11 @@
* to another.
**/
-#include "or.h"
-#include "config.h"
-#include "reasons.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "core/or/reasons.h"
+#include "feature/nodelist/routerlist.h"
+#include "lib/tls/tortls.h"
/***************************** Edge (stream) reasons **********************/
@@ -493,4 +495,3 @@ end_reason_to_http_connect_response_line(int endreason)
return "HTTP/1.0 500 Internal Server Error (weird end reason)\r\n\r\n";
}
}
-
diff --git a/src/or/reasons.h b/src/core/or/reasons.h
index 3d6ba8fc83..837b4a0f1a 100644
--- a/src/or/reasons.h
+++ b/src/core/or/reasons.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,6 +12,9 @@
#ifndef TOR_REASONS_H
#define TOR_REASONS_H
+#include "lib/net/socks5_status.h"
+enum bandwidth_weight_rule_t;
+
const char *stream_end_reason_to_control_string(int reason);
const char *stream_end_reason_to_string(int reason);
socks5_reply_status_t stream_end_reason_to_socks5_response(int reason);
@@ -29,4 +32,3 @@ const char *bandwidth_weight_rule_to_string(enum bandwidth_weight_rule_t rule);
const char *end_reason_to_http_connect_response_line(int endreason);
#endif /* !defined(TOR_REASONS_H) */
-
diff --git a/src/or/relay.c b/src/core/or/relay.c
index 3632678af6..32bb69d25f 100644
--- a/src/or/relay.c
+++ b/src/core/or/relay.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -46,40 +46,55 @@
**/
#define RELAY_PRIVATE
-#include "or.h"
-#include "addressmap.h"
-#include "backtrace.h"
-#include "buffers.h"
-#include "channel.h"
-#include "circpathbias.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "compress.h"
-#include "config.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "connection_or.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "geoip.h"
-#include "hs_cache.h"
-#include "main.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "onion.h"
-#include "policies.h"
-#include "reasons.h"
-#include "relay.h"
-#include "relay_crypto.h"
-#include "rendcache.h"
-#include "rendcommon.h"
-#include "router.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "scheduler.h"
-#include "rephist.h"
+#include "core/or/or.h"
+#include "feature/client/addressmap.h"
+#include "lib/err/backtrace.h"
+#include "lib/container/buffers.h"
+#include "core/or/channel.h"
+#include "feature/client/circpathbias.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "lib/compress/compress.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "core/or/connection_or.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/dircache/directory.h"
+#include "feature/stats/geoip.h"
+#include "feature/hs/hs_cache.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/crypto/onion.h"
+#include "core/or/policies.h"
+#include "core/or/reasons.h"
+#include "core/or/relay.h"
+#include "core/crypto/relay_crypto.h"
+#include "feature/rend/rendcache.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "core/or/scheduler.h"
+#include "feature/stats/rephist.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/cell_queue_st.h"
+#include "core/or/cpath_build_state_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "core/or/destroy_cell_queue_st.h"
+#include "core/or/entry_connection_st.h"
+#include "core/or/extend_info_st.h"
+#include "core/or/or_circuit_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "core/or/socks_request_st.h"
+
+#include "lib/intmath/weakrng.h"
static edge_connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell,
cell_direction_t cell_direction,
@@ -1783,15 +1798,15 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
return 0;
}
- /* Don't allow the other endpoint to request more than our maximim
- * (ie initial) stream SENDME window worth of data. Well-behaved
+ /* Don't allow the other endpoint to request more than our maximum
+ * (i.e. initial) stream SENDME window worth of data. Well-behaved
* stock clients will not request more than this max (as per the check
* in the while loop of connection_edge_consider_sending_sendme()).
*/
if (conn->package_window + STREAMWINDOW_INCREMENT >
STREAMWINDOW_START_MAX) {
static struct ratelim_t stream_warn_ratelim = RATELIM_INIT(600);
- log_fn_ratelim(&stream_warn_ratelim,LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ log_fn_ratelim(&stream_warn_ratelim, LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Unexpected stream sendme cell. Closing circ (window %d).",
conn->package_window);
return -END_CIRC_REASON_TORPROTOCOL;
@@ -3071,4 +3086,3 @@ circuit_queue_streams_are_blocked(circuit_t *circ)
return circ->streams_blocked_on_p_chan;
}
}
-
diff --git a/src/or/relay.h b/src/core/or/relay.h
index ce0969b46c..db7f17b96c 100644
--- a/src/or/relay.h
+++ b/src/core/or/relay.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/relay_crypto_st.h b/src/core/or/relay_crypto_st.h
new file mode 100644
index 0000000000..f186e182f0
--- /dev/null
+++ b/src/core/or/relay_crypto_st.h
@@ -0,0 +1,31 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef RELAY_CRYPTO_ST_H
+#define RELAY_CRYPTO_ST_H
+
+#define crypto_cipher_t aes_cnt_cipher
+struct crypto_cipher_t;
+struct crypto_digest_t;
+
+struct relay_crypto_t {
+ /* crypto environments */
+ /** Encryption key and counter for cells heading towards the OR at this
+ * step. */
+ struct crypto_cipher_t *f_crypto;
+ /** Encryption key and counter for cells heading back from the OR at this
+ * step. */
+ struct crypto_cipher_t *b_crypto;
+
+ /** Digest state for cells heading towards the OR at this step. */
+ struct crypto_digest_t *f_digest; /* for integrity checking */
+ /** Digest state for cells heading away from the OR at this step. */
+ struct crypto_digest_t *b_digest;
+
+};
+#undef crypto_cipher_t
+
+#endif
diff --git a/src/or/scheduler.c b/src/core/or/scheduler.c
index da894294bf..e19059f0c5 100644
--- a/src/or/scheduler.c
+++ b/src/core/or/scheduler.c
@@ -1,17 +1,20 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
+/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "config.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
-#include "compat_libevent.h"
+#include "lib/evloop/compat_libevent.h"
#define SCHEDULER_PRIVATE_
#define SCHEDULER_KIST_PRIVATE
-#include "scheduler.h"
-#include "main.h"
-#include "buffers.h"
+#include "core/or/scheduler.h"
+#include "core/mainloop/main.h"
+#include "lib/container/buffers.h"
#define TOR_CHANNEL_INTERNAL_
-#include "channeltls.h"
+#include "core/or/channeltls.h"
+#include "lib/evloop/compat_libevent.h"
+
+#include "core/or/or_connection_st.h"
/**
* \file scheduler.c
@@ -763,4 +766,3 @@ scheduler_touch_channel(channel_t *chan)
}
#endif /* defined(TOR_UNIT_TESTS) */
-
diff --git a/src/or/scheduler.h b/src/core/or/scheduler.h
index 08b02e286f..05a888365b 100644
--- a/src/or/scheduler.h
+++ b/src/core/or/scheduler.h
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2017, The Tor Project, Inc. */
+/* * Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,9 +9,9 @@
#ifndef TOR_SCHEDULER_H
#define TOR_SCHEDULER_H
-#include "or.h"
-#include "channel.h"
-#include "testsupport.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "lib/testsupport/testsupport.h"
/** Scheduler type, we build an ordered list with those values from the
* parsed strings in Schedulers. The reason to do such a thing is so we can
diff --git a/src/or/scheduler_kist.c b/src/core/or/scheduler_kist.c
index c6e9b72c48..449478df78 100644
--- a/src/or/scheduler_kist.c
+++ b/src/core/or/scheduler_kist.c
@@ -1,21 +1,28 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define SCHEDULER_KIST_PRIVATE
-#include "or.h"
-#include "buffers.h"
-#include "config.h"
-#include "connection.h"
-#include "networkstatus.h"
+#include "core/or/or.h"
+#include "lib/container/buffers.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "feature/nodelist/networkstatus.h"
#define TOR_CHANNEL_INTERNAL_
-#include "channel.h"
-#include "channeltls.h"
+#include "core/or/channel.h"
+#include "core/or/channeltls.h"
#define SCHEDULER_PRIVATE_
-#include "scheduler.h"
+#include "core/or/scheduler.h"
+#include "lib/math/fp.h"
+
+#include "core/or/or_connection_st.h"
#define TLS_PER_CELL_OVERHEAD 29
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
#ifdef HAVE_KIST_SUPPORT
/* Kernel interface needed for KIST. */
#include <netinet/tcp.h>
@@ -833,4 +840,3 @@ scheduler_can_use_kist(void)
}
#endif /* defined(HAVE_KIST_SUPPORT) */
-
diff --git a/src/or/scheduler_vanilla.c b/src/core/or/scheduler_vanilla.c
index b674d8256c..db8374eadb 100644
--- a/src/or/scheduler_vanilla.c
+++ b/src/core/or/scheduler_vanilla.c
@@ -1,12 +1,12 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "config.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
#define TOR_CHANNEL_INTERNAL_
-#include "channel.h"
+#include "core/or/channel.h"
#define SCHEDULER_PRIVATE_
-#include "scheduler.h"
+#include "core/or/scheduler.h"
/*****************************************************************************
* Other internal data
@@ -72,9 +72,9 @@ vanilla_scheduler_run(void)
n_cells = channel_num_cells_writeable(chan);
if (n_cells > 0) {
log_debug(LD_SCHED,
- "Scheduler saw pending channel " U64_FORMAT " at %p with "
+ "Scheduler saw pending channel %"PRIu64 " at %p with "
"%d cells writeable",
- U64_PRINTF_ARG(chan->global_identifier), chan, n_cells);
+ (chan->global_identifier), chan, n_cells);
flushed = 0;
while (flushed < n_cells) {
@@ -97,9 +97,9 @@ vanilla_scheduler_run(void)
if (!to_readd) to_readd = smartlist_new();
smartlist_add(to_readd, chan);
log_debug(LD_SCHED,
- "Channel " U64_FORMAT " at %p "
+ "Channel %"PRIu64 " at %p "
"is still pending",
- U64_PRINTF_ARG(chan->global_identifier),
+ (chan->global_identifier),
chan);
} else {
/* It's waiting to be able to write more */
@@ -125,14 +125,14 @@ vanilla_scheduler_run(void)
log_debug(LD_SCHED,
"Scheduler flushed %d cells onto pending channel "
- U64_FORMAT " at %p",
- (int)flushed, U64_PRINTF_ARG(chan->global_identifier),
+ "%"PRIu64 " at %p",
+ (int)flushed, (chan->global_identifier),
chan);
} else {
log_info(LD_SCHED,
- "Scheduler saw pending channel " U64_FORMAT " at %p with "
+ "Scheduler saw pending channel %"PRIu64 " at %p with "
"no cells writeable",
- U64_PRINTF_ARG(chan->global_identifier), chan);
+ (chan->global_identifier), chan);
/* Put it back to WAITING_TO_WRITE */
scheduler_set_channel_state(chan, SCHED_CHAN_WAITING_TO_WRITE);
}
diff --git a/src/core/or/server_port_cfg_st.h b/src/core/or/server_port_cfg_st.h
new file mode 100644
index 0000000000..e1a9ca496a
--- /dev/null
+++ b/src/core/or/server_port_cfg_st.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef SERVER_PORT_CFG_ST_H
+#define SERVER_PORT_CFG_ST_H
+
+struct server_port_cfg_t {
+ /* Server port types (or, dir) only: */
+ unsigned int no_advertise : 1;
+ unsigned int no_listen : 1;
+ unsigned int all_addrs : 1;
+ unsigned int bind_ipv4_only : 1;
+ unsigned int bind_ipv6_only : 1;
+};
+
+#endif
+
diff --git a/src/core/or/socks_request_st.h b/src/core/or/socks_request_st.h
new file mode 100644
index 0000000000..d7b979c3eb
--- /dev/null
+++ b/src/core/or/socks_request_st.h
@@ -0,0 +1,75 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef SOCKS_REQUEST_ST_H
+#define SOCKS_REQUEST_ST_H
+
+#define MAX_SOCKS_REPLY_LEN 1024
+
+#define SOCKS_NO_AUTH 0x00
+#define SOCKS_USER_PASS 0x02
+
+/** Please open a TCP connection to this addr:port. */
+#define SOCKS_COMMAND_CONNECT 0x01
+/** Please turn this FQDN into an IP address, privately. */
+#define SOCKS_COMMAND_RESOLVE 0xF0
+/** Please turn this IP address into an FQDN, privately. */
+#define SOCKS_COMMAND_RESOLVE_PTR 0xF1
+
+/* || 0 is for -Wparentheses-equality (-Wall?) appeasement under clang */
+#define SOCKS_COMMAND_IS_CONNECT(c) (((c)==SOCKS_COMMAND_CONNECT) || 0)
+#define SOCKS_COMMAND_IS_RESOLVE(c) ((c)==SOCKS_COMMAND_RESOLVE || \
+ (c)==SOCKS_COMMAND_RESOLVE_PTR)
+
+/** State of a SOCKS request from a user to an OP. Also used to encode other
+ * information for non-socks user request (such as those on TransPort and
+ * DNSPort) */
+struct socks_request_t {
+ /** Which version of SOCKS did the client use? One of "0, 4, 5" -- where
+ * 0 means that no socks handshake ever took place, and this is just a
+ * stub connection (e.g. see connection_ap_make_link()). */
+ uint8_t socks_version;
+ /** If using socks5 authentication, which authentication type did we
+ * negotiate? currently we support 0 (no authentication) and 2
+ * (username/password). */
+ uint8_t auth_type;
+ /** What is this stream's goal? One of the SOCKS_COMMAND_* values */
+ uint8_t command;
+ /** Which kind of listener created this stream? */
+ uint8_t listener_type;
+ size_t replylen; /**< Length of <b>reply</b>. */
+ uint8_t reply[MAX_SOCKS_REPLY_LEN]; /**< Write an entry into this string if
+ * we want to specify our own socks reply,
+ * rather than using the default socks4 or
+ * socks5 socks reply. We use this for the
+ * two-stage socks5 handshake.
+ */
+ char address[MAX_SOCKS_ADDR_LEN]; /**< What address did the client ask to
+ connect to/resolve? */
+ uint16_t port; /**< What port did the client ask to connect to? */
+ unsigned int has_finished : 1; /**< Has the SOCKS handshake finished? Used to
+ * make sure we send back a socks reply for
+ * every connection. */
+ unsigned int got_auth : 1; /**< Have we received any authentication data? */
+ /** If this is set, we will choose "no authentication" instead of
+ * "username/password" authentication if both are offered. Used as input to
+ * parse_socks. */
+ unsigned int socks_prefer_no_auth : 1;
+
+ /** Number of bytes in username; 0 if username is NULL */
+ size_t usernamelen;
+ /** Number of bytes in password; 0 if password is NULL */
+ uint8_t passwordlen;
+ /** The negotiated username value if any (for socks5), or the entire
+ * authentication string (for socks4). This value is NOT nul-terminated;
+ * see usernamelen for its length. */
+ char *username;
+ /** The negotiated password value if any (for socks5). This value is NOT
+ * nul-terminated; see passwordlen for its length. */
+ char *password;
+};
+
+#endif
diff --git a/src/or/status.c b/src/core/or/status.c
index 4b8033d114..30a65b1d4c 100644
--- a/src/or/status.c
+++ b/src/core/or/status.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2017, The Tor Project, Inc. */
+/* Copyright (c) 2010-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,24 +14,28 @@
#define STATUS_PRIVATE
-#include "or.h"
-#include "circuituse.h"
-#include "config.h"
-#include "status.h"
-#include "nodelist.h"
-#include "relay.h"
-#include "router.h"
-#include "circuitlist.h"
-#include "main.h"
-#include "rephist.h"
-#include "hibernate.h"
-#include "statefile.h"
-#include "hs_stats.h"
-#include "hs_service.h"
-#include "dos.h"
+#include "core/or/or.h"
+#include "core/or/circuituse.h"
+#include "app/config/config.h"
+#include "core/or/status.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/relay.h"
+#include "feature/relay/router.h"
+#include "core/or/circuitlist.h"
+#include "core/mainloop/main.h"
+#include "feature/stats/rephist.h"
+#include "feature/hibernate/hibernate.h"
+#include "app/config/statefile.h"
+#include "feature/hs/hs_stats.h"
+#include "feature/hs/hs_service.h"
+#include "core/or/dos.h"
+
+#include "app/config/or_state_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "lib/tls/tortls.h"
static void log_accounting(const time_t now, const or_options_t *options);
-#include "geoip.h"
+#include "feature/stats/geoip.h"
/** Return the total number of circuits. */
STATIC int
@@ -75,12 +79,12 @@ bytes_to_usage(uint64_t bytes)
char *bw_string = NULL;
if (bytes < (1<<20)) { /* Less than a megabyte. */
- tor_asprintf(&bw_string, U64_FORMAT" kB", U64_PRINTF_ARG(bytes>>10));
+ tor_asprintf(&bw_string, "%"PRIu64" kB", (bytes>>10));
} else if (bytes < (1<<30)) { /* Megabytes. Let's add some precision. */
- double bw = U64_TO_DBL(bytes);
+ double bw = ((double)bytes);
tor_asprintf(&bw_string, "%.2f MB", bw/(1<<20));
} else { /* Gigabytes. */
- double bw = U64_TO_DBL(bytes);
+ double bw = ((double)bytes);
tor_asprintf(&bw_string, "%.2f GB", bw/(1<<30));
}
@@ -148,8 +152,8 @@ log_heartbeat(time_t now)
double fullness_pct = 100;
if (stats_n_data_cells_packaged && !hibernating) {
fullness_pct =
- 100*(U64_TO_DBL(stats_n_data_bytes_packaged) /
- U64_TO_DBL(stats_n_data_cells_packaged*RELAY_PAYLOAD_SIZE));
+ 100*(((double)stats_n_data_bytes_packaged) /
+ ((double)stats_n_data_cells_packaged*RELAY_PAYLOAD_SIZE));
}
const double overhead_pct = ( r - 1.0 ) * 100.0;
@@ -186,12 +190,12 @@ log_heartbeat(time_t now)
const uint64_t main_loop_idle_count = get_main_loop_idle_count();
log_fn(LOG_NOTICE, LD_HEARTBEAT, "Main event loop statistics: "
- U64_FORMAT " successful returns, "
- U64_FORMAT " erroneous returns, and "
- U64_FORMAT " idle returns.",
- U64_PRINTF_ARG(main_loop_success_count),
- U64_PRINTF_ARG(main_loop_error_count),
- U64_PRINTF_ARG(main_loop_idle_count));
+ "%"PRIu64 " successful returns, "
+ "%"PRIu64 " erroneous returns, and "
+ "%"PRIu64 " idle returns.",
+ (main_loop_success_count),
+ (main_loop_error_count),
+ (main_loop_idle_count));
}
/** Now, if we are an HS service, log some stats about our usage */
@@ -245,4 +249,3 @@ log_accounting(const time_t now, const or_options_t *options)
tor_free(acc_max);
tor_free(remaining);
}
-
diff --git a/src/or/status.h b/src/core/or/status.h
index 49da6abc0f..7258ed5939 100644
--- a/src/or/status.h
+++ b/src/core/or/status.h
@@ -1,10 +1,10 @@
-/* Copyright (c) 2010-2017, The Tor Project, Inc. */
+/* Copyright (c) 2010-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_STATUS_H
#define TOR_STATUS_H
-#include "testsupport.h"
+#include "lib/testsupport/testsupport.h"
int log_heartbeat(time_t now);
diff --git a/src/core/or/tor_version_st.h b/src/core/or/tor_version_st.h
new file mode 100644
index 0000000000..5950c5d5c4
--- /dev/null
+++ b/src/core/or/tor_version_st.h
@@ -0,0 +1,32 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_VERSION_ST_H
+#define TOR_VERSION_ST_H
+
+#define MAX_STATUS_TAG_LEN 32
+/** Structure to hold parsed Tor versions. This is a little messier
+ * than we would like it to be, because we changed version schemes with 0.1.0.
+ *
+ * See version-spec.txt for the whole business.
+ */
+struct tor_version_t {
+ int major;
+ int minor;
+ int micro;
+ /** Release status. For version in the post-0.1 format, this is always
+ * VER_RELEASE. */
+ enum { VER_PRE=0, VER_RC=1, VER_RELEASE=2, } status;
+ int patchlevel;
+ char status_tag[MAX_STATUS_TAG_LEN];
+ int svn_revision;
+
+ int git_tag_len;
+ char git_tag[DIGEST_LEN];
+};
+
+#endif
+
diff --git a/src/core/or/var_cell_st.h b/src/core/or/var_cell_st.h
new file mode 100644
index 0000000000..514afc44b1
--- /dev/null
+++ b/src/core/or/var_cell_st.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef VAR_CELL_ST_H
+#define VAR_CELL_ST_H
+
+/** Parsed variable-length onion routing cell. */
+struct var_cell_t {
+ /** Type of the cell: CELL_VERSIONS, etc. */
+ uint8_t command;
+ /** Circuit thich received the cell */
+ circid_t circ_id;
+ /** Number of bytes actually stored in <b>payload</b> */
+ uint16_t payload_len;
+ /** Payload of this cell */
+ uint8_t payload[FLEXIBLE_ARRAY_MEMBER];
+};
+
+#endif
+
diff --git a/src/or/proto_cell.c b/src/core/proto/proto_cell.c
index 75eb2a7e7f..49b07663d7 100644
--- a/src/or/proto_cell.c
+++ b/src/core/proto/proto_cell.c
@@ -1,14 +1,16 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "buffers.h"
-#include "proto_cell.h"
+#include "core/or/or.h"
+#include "lib/container/buffers.h"
+#include "core/proto/proto_cell.h"
-#include "connection_or.h"
+#include "core/or/connection_or.h"
+
+#include "core/or/var_cell_st.h"
/** True iff the cell command <b>command</b> is one that implies a
* variable-length cell in Tor link protocol <b>linkproto</b>. */
diff --git a/src/or/proto_cell.h b/src/core/proto/proto_cell.h
index bbc14b9a02..b29645e41d 100644
--- a/src/or/proto_cell.h
+++ b/src/core/proto/proto_cell.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_PROTO_CELL_H
diff --git a/src/or/proto_control0.c b/src/core/proto/proto_control0.c
index c17ba34948..d26c69753a 100644
--- a/src/or/proto_control0.c
+++ b/src/core/proto/proto_control0.c
@@ -1,12 +1,12 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "buffers.h"
-#include "proto_control0.h"
+#include "core/or/or.h"
+#include "lib/container/buffers.h"
+#include "core/proto/proto_control0.h"
/** Return 1 iff buf looks more like it has an (obsolete) v0 controller
* command on it than any valid v1 controller command. */
diff --git a/src/or/proto_control0.h b/src/core/proto/proto_control0.h
index 0cc8eacad0..b80dc6c8f8 100644
--- a/src/or/proto_control0.h
+++ b/src/core/proto/proto_control0.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_PROTO_CONTROL0_H
diff --git a/src/or/proto_ext_or.c b/src/core/proto/proto_ext_or.c
index 057cf109ec..04bec4e6b9 100644
--- a/src/or/proto_ext_or.c
+++ b/src/core/proto/proto_ext_or.c
@@ -1,13 +1,13 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "buffers.h"
-#include "ext_orport.h"
-#include "proto_ext_or.h"
+#include "core/or/or.h"
+#include "lib/container/buffers.h"
+#include "feature/relay/ext_orport.h"
+#include "core/proto/proto_ext_or.h"
/** The size of the header of an Extended ORPort message: 2 bytes for
* COMMAND, 2 bytes for BODYLEN */
diff --git a/src/or/proto_ext_or.h b/src/core/proto/proto_ext_or.h
index cc504d18e3..708a45974b 100644
--- a/src/or/proto_ext_or.h
+++ b/src/core/proto/proto_ext_or.h
@@ -1,17 +1,22 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_PROTO_EXT_OR_H
#define TOR_PROTO_EXT_OR_H
struct buf_t;
-struct ext_or_cmt_t;
+
+/** A parsed Extended ORPort message. */
+typedef struct ext_or_cmd_t {
+ uint16_t cmd; /** Command type */
+ uint16_t len; /** Body length */
+ char body[FLEXIBLE_ARRAY_MEMBER]; /** Message body */
+} ext_or_cmd_t;
int fetch_ext_or_command_from_buf(struct buf_t *buf,
struct ext_or_cmd_t **out);
#endif /* !defined(TOR_PROTO_EXT_OR_H) */
-
diff --git a/src/or/proto_http.c b/src/core/proto/proto_http.c
index 3762429e1e..37298d1284 100644
--- a/src/or/proto_http.c
+++ b/src/core/proto/proto_http.c
@@ -1,13 +1,13 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define PROTO_HTTP_PRIVATE
-#include "or.h"
-#include "buffers.h"
-#include "proto_http.h"
+#include "core/or/or.h"
+#include "lib/container/buffers.h"
+#include "core/proto/proto_http.h"
/** Return true if <b>cmd</b> looks like a HTTP (proxy) request. */
int
diff --git a/src/or/proto_http.h b/src/core/proto/proto_http.h
index 805686070f..587e435ede 100644
--- a/src/or/proto_http.h
+++ b/src/core/proto/proto_http.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_PROTO_HTTP_H
diff --git a/src/or/proto_socks.c b/src/core/proto/proto_socks.c
index 57a7d1cd64..6912441472 100644
--- a/src/or/proto_socks.c
+++ b/src/core/proto/proto_socks.c
@@ -1,18 +1,21 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "addressmap.h"
-#include "buffers.h"
-#include "control.h"
-#include "config.h"
-#include "crypto_util.h"
-#include "ext_orport.h"
-#include "proto_socks.h"
-#include "reasons.h"
+#include "core/or/or.h"
+#include "feature/client/addressmap.h"
+#include "lib/container/buffers.h"
+#include "core/mainloop/connection.h"
+#include "feature/control/control.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/relay/ext_orport.h"
+#include "core/proto/proto_socks.h"
+#include "core/or/reasons.h"
+
+#include "core/or/socks_request_st.h"
static void socks_request_set_socks5_error(socks_request_t *req,
socks5_reply_status_t reason);
@@ -708,4 +711,3 @@ parse_socks_client(const uint8_t *data, size_t datalen,
return -1;
/* LCOV_EXCL_STOP */
}
-
diff --git a/src/or/proto_socks.h b/src/core/proto/proto_socks.h
index 02e0aca7e9..53de288f65 100644
--- a/src/or/proto_socks.h
+++ b/src/core/proto/proto_socks.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_PROTO_SOCKS_H
@@ -19,4 +19,3 @@ int fetch_from_buf_socks(struct buf_t *buf, socks_request_t *req,
int fetch_from_buf_socks_client(buf_t *buf, int state, char **reason);
#endif /* !defined(TOR_PROTO_SOCKS_H) */
-
diff --git a/src/or/protover_rust.c b/src/core/proto/protover_rust.c
index 99304f8b51..dbdd5c8237 100644
--- a/src/or/protover_rust.c
+++ b/src/core/proto/protover_rust.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/*
@@ -7,8 +7,8 @@
* and safe translation/handling between the Rust/C boundary.
*/
-#include "or.h"
-#include "protover.h"
+#include "core/or/or.h"
+#include "core/or/protover.h"
#ifdef HAVE_RUST
diff --git a/src/ext/OpenBSD_malloc_Linux.c b/src/ext/OpenBSD_malloc_Linux.c
index 855c912310..9c30570c41 100644
--- a/src/ext/OpenBSD_malloc_Linux.c
+++ b/src/ext/OpenBSD_malloc_Linux.c
@@ -59,7 +59,7 @@
#include <errno.h>
#include <err.h>
/* For SIZE_MAX */
-#include "torint.h"
+#include "lib/cc/torint.h"
//#include "thread_private.h"
diff --git a/src/ext/csiphash.c b/src/ext/csiphash.c
index 0427c87950..a6a9846db4 100644
--- a/src/ext/csiphash.c
+++ b/src/ext/csiphash.c
@@ -29,12 +29,12 @@
Jean-Philippe Aumasson (https://131002.net/siphash/siphash24.c)
*/
-#include "torint.h"
+#include "lib/cc/torint.h"
+#include "lib/log/util_bug.h"
+
#include "siphash.h"
-/* for tor_assert */
-#include "util.h"
-/* for memcpy */
#include <string.h>
+#include <stdlib.h>
#include "byteorder.h"
#define ROTATE(x, b) (uint64_t)( ((x) << (b)) | ( (x) >> (64 - (b))) )
diff --git a/src/ext/curve25519_donna/curve25519-donna-c64.c b/src/ext/curve25519_donna/curve25519-donna-c64.c
index b68ff3695a..45da7bf1e6 100644
--- a/src/ext/curve25519_donna/curve25519-donna-c64.c
+++ b/src/ext/curve25519_donna/curve25519-donna-c64.c
@@ -25,7 +25,7 @@
#include "orconfig.h"
#include <string.h>
-#include "torint.h"
+#include "lib/cc/torint.h"
typedef uint8_t u8;
typedef uint64_t limb;
diff --git a/src/ext/curve25519_donna/curve25519-donna.c b/src/ext/curve25519_donna/curve25519-donna.c
index 1c5a27ab8a..d64b95c113 100644
--- a/src/ext/curve25519_donna/curve25519-donna.c
+++ b/src/ext/curve25519_donna/curve25519-donna.c
@@ -48,7 +48,7 @@
#include "orconfig.h"
#include <string.h>
-#include "torint.h"
+#include "lib/cc/torint.h"
typedef uint8_t u8;
typedef int32_t s32;
diff --git a/src/ext/ed25519/donna/ed25519-hash-custom.h b/src/ext/ed25519/donna/ed25519-hash-custom.h
index cdeab3e45b..ff8bbde3da 100644
--- a/src/ext/ed25519/donna/ed25519-hash-custom.h
+++ b/src/ext/ed25519/donna/ed25519-hash-custom.h
@@ -9,7 +9,7 @@
void ed25519_hash(uint8_t *hash, const uint8_t *in, size_t inlen);
*/
-#include "crypto_digest.h"
+#include "lib/crypt_ops/crypto_digest.h"
typedef struct ed25519_hash_context {
crypto_digest_t *ctx;
diff --git a/src/ext/ed25519/donna/ed25519-randombytes-custom.h b/src/ext/ed25519/donna/ed25519-randombytes-custom.h
index 27eade4f95..d92a51d1d3 100644
--- a/src/ext/ed25519/donna/ed25519-randombytes-custom.h
+++ b/src/ext/ed25519/donna/ed25519-randombytes-custom.h
@@ -8,7 +8,7 @@
*/
/* Tor: Instead of calling OpenSSL's CSPRNG directly, call the wrapper. */
-#include "crypto_rand.h"
+#include "lib/crypt_ops/crypto_rand.h"
static void
ED25519_FN(ed25519_randombytes_unsafe) (void *p, size_t len)
diff --git a/src/ext/ed25519/donna/ed25519_donna_tor.h b/src/ext/ed25519/donna/ed25519_donna_tor.h
index 7d7b8c0625..20e9b5e99c 100644
--- a/src/ext/ed25519/donna/ed25519_donna_tor.h
+++ b/src/ext/ed25519/donna/ed25519_donna_tor.h
@@ -1,7 +1,7 @@
/* Added for Tor. */
#ifndef SRC_EXT_ED25519_DONNA_H_INCLUDED_
#define SRC_EXT_ED25519_DONNA_H_INCLUDED_
-#include <torint.h>
+#include "lib/cc/torint.h"
typedef unsigned char curved25519_key[32];
diff --git a/src/ext/ed25519/donna/ed25519_tor.c b/src/ext/ed25519/donna/ed25519_tor.c
index 43de9faaea..7f5ab398d8 100644
--- a/src/ext/ed25519/donna/ed25519_tor.c
+++ b/src/ext/ed25519/donna/ed25519_tor.c
@@ -40,7 +40,7 @@
#include "ed25519-randombytes.h"
#include "ed25519-hash.h"
-#include "crypto_util.h"
+#include "lib/crypt_ops/crypto_util.h"
typedef unsigned char ed25519_signature[64];
typedef unsigned char ed25519_public_key[32];
diff --git a/src/ext/ed25519/ref10/blinding.c b/src/ext/ed25519/ref10/blinding.c
index 88e84cac20..8485524e5d 100644
--- a/src/ext/ed25519/ref10/blinding.c
+++ b/src/ext/ed25519/ref10/blinding.c
@@ -7,7 +7,7 @@
#include "ed25519_ref10.h"
#include <string.h>
-#include "crypto_util.h"
+#include "lib/crypt_ops/crypto_util.h"
static void
ed25519_ref10_gettweak(unsigned char *out, const unsigned char *param)
diff --git a/src/ext/ed25519/ref10/crypto_hash_sha512.h b/src/ext/ed25519/ref10/crypto_hash_sha512.h
index 7faddb1597..25e6a90cec 100644
--- a/src/ext/ed25519/ref10/crypto_hash_sha512.h
+++ b/src/ext/ed25519/ref10/crypto_hash_sha512.h
@@ -1,5 +1,5 @@
/* Added for Tor. */
-#include "crypto_digest.h"
+#include "lib/crypt_ops/crypto_digest.h"
/* Set 'out' to the 512-bit SHA512 hash of the 'len'-byte string in 'inp' */
#define crypto_hash_sha512(out, inp, len) \
diff --git a/src/ext/ed25519/ref10/crypto_int32.h b/src/ext/ed25519/ref10/crypto_int32.h
index dd13c91bd0..26271e917b 100644
--- a/src/ext/ed25519/ref10/crypto_int32.h
+++ b/src/ext/ed25519/ref10/crypto_int32.h
@@ -3,7 +3,7 @@
#ifndef CRYPTO_INT32_H
#define CRYPTO_INT32_H
-#include "torint.h"
+#include "lib/cc/torint.h"
#define crypto_int32 int32_t
#define crypto_uint32 uint32_t
diff --git a/src/ext/ed25519/ref10/crypto_int64.h b/src/ext/ed25519/ref10/crypto_int64.h
index 46e8852ed0..3b066a9c0c 100644
--- a/src/ext/ed25519/ref10/crypto_int64.h
+++ b/src/ext/ed25519/ref10/crypto_int64.h
@@ -3,7 +3,7 @@
#ifndef CRYPTO_INT64_H
#define CRYPTO_INT64_H
-#include "torint.h"
+#include "lib/cc/torint.h"
#define crypto_int64 int64_t
#define crypto_uint64 uint64_t
diff --git a/src/ext/ed25519/ref10/crypto_uint32.h b/src/ext/ed25519/ref10/crypto_uint32.h
index 62655a5b66..a7a77723bd 100644
--- a/src/ext/ed25519/ref10/crypto_uint32.h
+++ b/src/ext/ed25519/ref10/crypto_uint32.h
@@ -1,3 +1,3 @@
/* Added for Tor. */
-#include "torint.h"
+#include "lib/cc/torint.h"
#define crypto_uint32 uint32_t
diff --git a/src/ext/ed25519/ref10/crypto_uint64.h b/src/ext/ed25519/ref10/crypto_uint64.h
index cbda882a6a..adaaa08042 100644
--- a/src/ext/ed25519/ref10/crypto_uint64.h
+++ b/src/ext/ed25519/ref10/crypto_uint64.h
@@ -1,3 +1,3 @@
/* Added for Tor. */
-#include "torint.h"
+#include "lib/cc/torint.h"
#define crypto_uint64 uint64_t
diff --git a/src/ext/ed25519/ref10/crypto_verify_32.h b/src/ext/ed25519/ref10/crypto_verify_32.h
index 0f63efc7a3..5299928754 100644
--- a/src/ext/ed25519/ref10/crypto_verify_32.h
+++ b/src/ext/ed25519/ref10/crypto_verify_32.h
@@ -1,5 +1,4 @@
/* Added for Tor. */
-#include "di_ops.h"
+#include "lib/ctime/di_ops.h"
#define crypto_verify_32(a,b) \
(! tor_memeq((a), (b), 32))
-
diff --git a/src/ext/ed25519/ref10/ed25519_ref10.h b/src/ext/ed25519/ref10/ed25519_ref10.h
index 5965694977..bb72af6c0b 100644
--- a/src/ext/ed25519/ref10/ed25519_ref10.h
+++ b/src/ext/ed25519/ref10/ed25519_ref10.h
@@ -1,7 +1,7 @@
/* Added for Tor */
#ifndef SRC_EXT_ED25519_REF10_H_INCLUDED_
#define SRC_EXT_ED25519_REF10_H_INCLUDED_
-#include <torint.h>
+#include "lib/cc/torint.h"
int ed25519_ref10_seckey(unsigned char *sk);
int ed25519_ref10_seckey_expand(unsigned char *sk, const unsigned char *sk_seed);
diff --git a/src/ext/ed25519/ref10/keypair.c b/src/ext/ed25519/ref10/keypair.c
index c437f0a4f2..a6e2d4c781 100644
--- a/src/ext/ed25519/ref10/keypair.c
+++ b/src/ext/ed25519/ref10/keypair.c
@@ -6,8 +6,8 @@
#include "crypto_hash_sha512.h"
#include "ge.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
int
crypto_sign_seckey(unsigned char *sk)
@@ -52,4 +52,3 @@ int crypto_sign_keypair(unsigned char *pk,unsigned char *sk)
return 0;
}
-
diff --git a/src/ext/ed25519/ref10/randombytes.h b/src/ext/ed25519/ref10/randombytes.h
index a21dde8540..c2cef10ceb 100644
--- a/src/ext/ed25519/ref10/randombytes.h
+++ b/src/ext/ed25519/ref10/randombytes.h
@@ -1,4 +1,4 @@
/* Added for Tor. */
-#include "crypto_rand.h"
+#include "lib/crypt_ops/crypto_rand.h"
#define randombytes(b, n) \
(crypto_strongest_rand((b), (n)), 0)
diff --git a/src/ext/ht.h b/src/ext/ht.h
index 99da773faf..df9f60ba1d 100644
--- a/src/ext/ht.h
+++ b/src/ext/ht.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2002, Christopher Clark.
* Copyright (c) 2005-2006, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See license at end. */
/* Based on ideas by Christopher Clark and interfaces from Niels Provos. */
diff --git a/src/ext/keccak-tiny/keccak-tiny-unrolled.c b/src/ext/keccak-tiny/keccak-tiny-unrolled.c
index 07e8c95bcf..05cf0ec3f0 100644
--- a/src/ext/keccak-tiny/keccak-tiny-unrolled.c
+++ b/src/ext/keccak-tiny/keccak-tiny-unrolled.c
@@ -9,7 +9,7 @@
#include "keccak-tiny.h"
#include <string.h>
-#include "crypto_util.h"
+#include "lib/crypt_ops/crypto_util.h"
#include "byteorder.h"
/******** Endianness conversion helpers ********/
diff --git a/src/ext/keccak-tiny/keccak-tiny.h b/src/ext/keccak-tiny/keccak-tiny.h
index 7efea2319e..a9c8ed6420 100644
--- a/src/ext/keccak-tiny/keccak-tiny.h
+++ b/src/ext/keccak-tiny/keccak-tiny.h
@@ -2,7 +2,7 @@
#define KECCAK_FIPS202_H
#include <stddef.h>
-#include "torint.h"
+#include "lib/cc/torint.h"
#define KECCAK_MAX_RATE 200
diff --git a/src/ext/mulodi/mulodi4.c b/src/ext/mulodi/mulodi4.c
index 9891bbf1af..accce1ce01 100644
--- a/src/ext/mulodi/mulodi4.c
+++ b/src/ext/mulodi/mulodi4.c
@@ -18,7 +18,7 @@
#define COMPILER_RT_ABI
#define di_int int64_t
#define di_uint uint64_t
-#include "torint.h"
+#include "lib/cc/torint.h"
di_int __mulodi4(di_int a, di_int b, int* overflow);
#endif
diff --git a/src/or/tor_api.c b/src/feature/api/tor_api.c
index 4260cc88f4..2a4458bf69 100644
--- a/src/or/tor_api.c
+++ b/src/feature/api/tor_api.c
@@ -1,15 +1,15 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file tor_api.c
**/
-#include "tor_api.h"
-#include "tor_api_internal.h"
+#include "feature/api/tor_api.h"
+#include "feature/api/tor_api_internal.h"
// Include this after the above headers, to insure that they don't
// depend on anything else.
diff --git a/src/or/tor_api.h b/src/feature/api/tor_api.h
index 6d4a9518e0..ead9493c1f 100644
--- a/src/or/tor_api.h
+++ b/src/feature/api/tor_api.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/or/tor_api_internal.h b/src/feature/api/tor_api_internal.h
index 10b6278b7b..2c392a68de 100644
--- a/src/or/tor_api_internal.h
+++ b/src/feature/api/tor_api_internal.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_API_INTERNAL_H
diff --git a/src/or/addressmap.c b/src/feature/client/addressmap.c
index 7f861e4d24..e62d82b7f3 100644
--- a/src/or/addressmap.c
+++ b/src/feature/client/addressmap.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,16 +15,19 @@
#define ADDRESSMAP_PRIVATE
-#include "or.h"
-#include "addressmap.h"
-#include "circuituse.h"
-#include "config.h"
-#include "connection_edge.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "dns.h"
-#include "nodelist.h"
-#include "routerset.h"
+#include "lib/crypt_ops/crypto_rand.h"
+
+#include "core/or/or.h"
+#include "feature/client/addressmap.h"
+#include "core/or/circuituse.h"
+#include "app/config/config.h"
+#include "core/or/connection_edge.h"
+#include "feature/control/control.h"
+#include "feature/relay/dns.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerset.h"
+
+#include "core/or/entry_connection_st.h"
/** A client-side struct to remember requests to rewrite addresses
* to new addresses. These structs are stored in the hash table
@@ -640,7 +643,7 @@ client_dns_incr_failures(const char *address)
ent->expires = time(NULL) + MAX_DNS_ENTRY_AGE;
strmap_set(addressmap,address,ent);
}
- if (ent->num_resolve_failures < SHORT_MAX)
+ if (ent->num_resolve_failures < SHRT_MAX)
++ent->num_resolve_failures; /* don't overflow */
log_info(LD_APP, "Address %s now has %d resolve failures.",
safe_str_client(address),
@@ -1151,4 +1154,3 @@ addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
iter = strmap_iter_next(addressmap,iter);
}
}
-
diff --git a/src/or/addressmap.h b/src/feature/client/addressmap.h
index 1544b76e10..b0db5c8b4e 100644
--- a/src/or/addressmap.h
+++ b/src/feature/client/addressmap.h
@@ -1,13 +1,13 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_ADDRESSMAP_H
#define TOR_ADDRESSMAP_H
-#include "testsupport.h"
+#include "lib/testsupport/testsupport.h"
void addressmap_init(void);
void addressmap_clear_excluded_trackexithosts(const or_options_t *options);
diff --git a/src/or/bridges.c b/src/feature/client/bridges.c
index 699e030e6c..4bffe16036 100644
--- a/src/or/bridges.c
+++ b/src/feature/client/bridges.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,19 +13,24 @@
#define TOR_BRIDGES_PRIVATE
-#include "or.h"
-#include "bridges.h"
-#include "circuitbuild.h"
-#include "config.h"
-#include "connection.h"
-#include "directory.h"
-#include "entrynodes.h"
-#include "nodelist.h"
-#include "policies.h"
-#include "router.h"
-#include "routerlist.h"
-#include "routerset.h"
-#include "transports.h"
+#include "core/or/or.h"
+#include "feature/client/bridges.h"
+#include "core/or/circuitbuild.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "feature/dircache/directory.h"
+#include "feature/client/entrynodes.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerset.h"
+#include "feature/client/transports.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"
/** Information about a configured bridge. Currently this just matches the
* ones in the torrc file, but one day we may be able to learn about new
diff --git a/src/or/bridges.h b/src/feature/client/bridges.h
index 3108eb555d..70588c1b91 100644
--- a/src/or/bridges.h
+++ b/src/feature/client/bridges.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,6 +13,7 @@
#define TOR_BRIDGES_H
struct bridge_line_t;
+struct ed25519_public_key_t;
/* Opaque handle to a configured bridge */
typedef struct bridge_info_t bridge_info_t;
@@ -38,7 +39,7 @@ int routerinfo_is_a_configured_bridge(const routerinfo_t *ri);
int node_is_a_configured_bridge(const node_t *node);
void learned_router_identity(const tor_addr_t *addr, uint16_t port,
const char *digest,
- const ed25519_public_key_t *ed_id);
+ const struct ed25519_public_key_t *ed_id);
void bridge_add_from_config(struct bridge_line_t *bridge_line);
void retry_bridge_descriptor_fetch_directly(const char *digest);
@@ -77,4 +78,3 @@ STATIC void bridge_resolve_conflicts(const tor_addr_t *addr,
#endif /* defined(TOR_BRIDGES_PRIVATE) */
#endif /* !defined(TOR_BRIDGES_H) */
-
diff --git a/src/or/circpathbias.c b/src/feature/client/circpathbias.c
index ff42bf91e4..1ee29c639d 100644
--- a/src/or/circpathbias.c
+++ b/src/feature/client/circpathbias.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -21,19 +21,27 @@
* each guard, and stored persistently in the state file.
*/
-#include "or.h"
-#include "channel.h"
-#include "circpathbias.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "circuitstats.h"
-#include "connection_edge.h"
-#include "config.h"
-#include "crypto_rand.h"
-#include "entrynodes.h"
-#include "networkstatus.h"
-#include "relay.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "feature/client/circpathbias.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "core/or/circuitstats.h"
+#include "core/or/connection_edge.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/client/entrynodes.h"
+#include "feature/nodelist/networkstatus.h"
+#include "core/or/relay.h"
+#include "lib/math/fp.h"
+#include "lib/math/laplace.h"
+
+#include "core/or/cell_st.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"
static void pathbias_count_successful_close(origin_circuit_t *circ);
static void pathbias_count_collapse(origin_circuit_t *circ);
@@ -1568,4 +1576,3 @@ pathbias_scale_use_rates(entry_guard_t *guard)
entry_guards_changed();
}
}
-
diff --git a/src/or/circpathbias.h b/src/feature/client/circpathbias.h
index c9e572d2ae..c99d1277bb 100644
--- a/src/or/circpathbias.h
+++ b/src/feature/client/circpathbias.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -23,7 +23,6 @@ int pathbias_check_probe_response(circuit_t *circ, const cell_t *cell);
void pathbias_count_use_attempt(origin_circuit_t *circ);
void pathbias_mark_use_success(origin_circuit_t *circ);
void pathbias_mark_use_rollback(origin_circuit_t *circ);
-const char *pathbias_state_to_string(path_state_t state);
+const char *pathbias_state_to_string(enum path_state_t state);
#endif /* !defined(TOR_CIRCPATHBIAS_H) */
-
diff --git a/src/or/dnsserv.c b/src/feature/client/dnsserv.c
index 7e344deeab..31cc3eff79 100644
--- a/src/or/dnsserv.c
+++ b/src/feature/client/dnsserv.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2017, The Tor Project, Inc. */
+/* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -21,14 +21,21 @@
* DNS client.
**/
-#include "or.h"
-#include "dnsserv.h"
-#include "config.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "control.h"
-#include "main.h"
-#include "policies.h"
+#include "core/or/or.h"
+#include "feature/client/dnsserv.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "feature/control/control.h"
+#include "core/mainloop/main.h"
+#include "core/or/policies.h"
+
+#include "feature/control/control_connection_st.h"
+#include "core/or/entry_connection_st.h"
+#include "core/or/listener_connection_st.h"
+#include "core/or/socks_request_st.h"
+#include "lib/evloop/compat_libevent.h"
+
#include <event2/dns.h>
#include <event2/dns_compat.h>
/* XXXX this implies we want an improved evdns */
@@ -406,4 +413,3 @@ dnsserv_close_listener(connection_t *conn)
listener_conn->dns_server_port = NULL;
}
}
-
diff --git a/src/or/dnsserv.h b/src/feature/client/dnsserv.h
index 2af366eee5..afdde3a342 100644
--- a/src/or/dnsserv.h
+++ b/src/feature/client/dnsserv.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/or/entrynodes.c b/src/feature/client/entrynodes.c
index 27d760f1a8..664be8ce11 100644
--- a/src/or/entrynodes.c
+++ b/src/feature/client/entrynodes.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -112,32 +112,40 @@
#define ENTRYNODES_PRIVATE
-#include "or.h"
-#include "channel.h"
-#include "bridges.h"
-#include "circpathbias.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "circuitstats.h"
-#include "config.h"
-#include "confparse.h"
-#include "connection.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "directory.h"
-#include "entrynodes.h"
-#include "main.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "policies.h"
-#include "router.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "routerset.h"
-#include "transports.h"
-#include "statefile.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "feature/client/bridges.h"
+#include "feature/client/circpathbias.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "core/or/circuitstats.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "core/mainloop/connection.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/dircache/directory.h"
+#include "feature/client/entrynodes.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/routerset.h"
+#include "feature/client/transports.h"
+#include "app/config/statefile.h"
+#include "lib/math/fp.h"
+#include "lib/encoding/confline.h"
+
+#include "feature/nodelist/node_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "app/config/or_state_st.h"
+
+#include "lib/crypt_ops/digestset.h"
/** A list of existing guard selection contexts. */
static smartlist_t *guard_contexts = NULL;
@@ -1060,7 +1068,7 @@ get_eligible_guards(const or_options_t *options,
continue;
}
++n_guards;
- if (digestset_contains(sampled_guard_ids, node->identity))
+ if (digestset_probably_contains(sampled_guard_ids, node->identity))
continue;
smartlist_add(eligible_guards, (node_t*)node);
} SMARTLIST_FOREACH_END(node);
@@ -3684,4 +3692,3 @@ entry_guards_free_all(void)
}
circuit_build_times_free_timeouts(get_circuit_build_times_mutable());
}
-
diff --git a/src/or/entrynodes.h b/src/feature/client/entrynodes.h
index e8c91da41b..5f9b5bdcba 100644
--- a/src/or/entrynodes.h
+++ b/src/feature/client/entrynodes.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,7 @@
#ifndef TOR_ENTRYNODES_H
#define TOR_ENTRYNODES_H
-#include "handles.h"
+#include "lib/container/handles.h"
/* Forward declare for guard_selection_t; entrynodes.c has the real struct */
typedef struct guard_selection_s guard_selection_t;
@@ -64,6 +64,8 @@ typedef struct guard_pathbias_t {
} guard_pathbias_t;
#if defined(ENTRYNODES_PRIVATE)
+#include "lib/crypt_ops/crypto_ed25519.h"
+
/**
* @name values for entry_guard_t.is_reachable.
*
@@ -635,4 +637,3 @@ guard_get_guardfraction_bandwidth(guardfraction_bandwidth_t *guardfraction_bw,
uint32_t guardfraction_percentage);
#endif /* !defined(TOR_ENTRYNODES_H) */
-
diff --git a/src/or/transports.c b/src/feature/client/transports.c
index 614fc81da8..85d4d2e080 100644
--- a/src/or/transports.c
+++ b/src/feature/client/transports.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Tor Project, Inc. */
+/* Copyright (c) 2011-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -90,17 +90,20 @@
**/
#define PT_PRIVATE
-#include "or.h"
-#include "bridges.h"
-#include "config.h"
-#include "circuitbuild.h"
-#include "transports.h"
-#include "util.h"
-#include "router.h"
-#include "statefile.h"
-#include "connection_or.h"
-#include "ext_orport.h"
-#include "control.h"
+#include "core/or/or.h"
+#include "feature/client/bridges.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/circuitbuild.h"
+#include "feature/client/transports.h"
+#include "feature/relay/router.h"
+#include "app/config/statefile.h"
+#include "core/or/connection_or.h"
+#include "feature/relay/ext_orport.h"
+#include "feature/control/control.h"
+
+#include "lib/process/env.h"
+#include "lib/process/subprocess.h"
static process_environment_t *
create_managed_proxy_environment(const managed_proxy_t *mp);
@@ -1697,3 +1700,39 @@ pt_free_all(void)
}
}
+/** Return a newly allocated string equal to <b>string</b>, except that every
+ * character in <b>chars_to_escape</b> is preceded by a backslash. */
+char *
+tor_escape_str_for_pt_args(const char *string, const char *chars_to_escape)
+{
+ char *new_string = NULL;
+ char *new_cp = NULL;
+ size_t length, new_length;
+
+ tor_assert(string);
+
+ length = strlen(string);
+
+ if (!length) /* If we were given the empty string, return the same. */
+ return tor_strdup("");
+ /* (new_length > SIZE_MAX) => ((length * 2) + 1 > SIZE_MAX) =>
+ (length*2 > SIZE_MAX - 1) => (length > (SIZE_MAX - 1)/2) */
+ if (length > (SIZE_MAX - 1)/2) /* check for overflow */
+ return NULL;
+
+ /* this should be enough even if all characters must be escaped */
+ new_length = (length * 2) + 1;
+
+ new_string = new_cp = tor_malloc(new_length);
+
+ while (*string) {
+ if (strchr(chars_to_escape, *string))
+ *new_cp++ = '\\';
+
+ *new_cp++ = *string++;
+ }
+
+ *new_cp = '\0'; /* NUL-terminate the new string */
+
+ return new_string;
+}
diff --git a/src/or/transports.h b/src/feature/client/transports.h
index 022b926a03..d304dcd485 100644
--- a/src/or/transports.h
+++ b/src/feature/client/transports.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -66,6 +66,9 @@ char *pt_stringify_socks_args(const smartlist_t *socks_args);
char *pt_get_socks_args_for_proxy_addrport(const tor_addr_t *addr,
uint16_t port);
+char *tor_escape_str_for_pt_args(const char *string,
+ const char *chars_to_escape);
+
#ifdef PT_PRIVATE
/** State of the managed proxy configuration protocol. */
enum pt_proto_state {
@@ -78,6 +81,8 @@ enum pt_proto_state {
PT_PROTO_FAILED_LAUNCH /* failed while launching */
};
+struct process_handle_t;
+
/** Structure containing information of a managed proxy. */
typedef struct {
enum pt_proto_state conf_state; /* the current configuration state */
@@ -90,7 +95,7 @@ typedef struct {
int is_server; /* is it a server proxy? */
/* A pointer to the process handle of this managed proxy. */
- process_handle_t *process_handle;
+ struct process_handle_t *process_handle;
int pid; /* The Process ID this managed proxy is using. */
@@ -140,4 +145,3 @@ STATIC void free_execve_args(char **arg);
#endif /* defined(PT_PRIVATE) */
#endif /* !defined(TOR_TRANSPORTS_H) */
-
diff --git a/src/or/control.c b/src/feature/control/control.c
index 09cf833e37..12f10926b7 100644
--- a/src/or/control.c
+++ b/src/feature/control/control.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -35,59 +35,86 @@
#define CONTROL_PRIVATE
-#include "or.h"
-#include "addressmap.h"
-#include "bridges.h"
-#include "buffers.h"
-#include "channel.h"
-#include "channeltls.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuitstats.h"
-#include "circuituse.h"
-#include "command.h"
-#include "compat_libevent.h"
-#include "config.h"
-#include "confparse.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "connection_or.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "directory.h"
-#include "dirserv.h"
-#include "dnsserv.h"
-#include "entrynodes.h"
-#include "geoip.h"
-#include "hibernate.h"
-#include "hs_cache.h"
-#include "hs_common.h"
-#include "hs_control.h"
-#include "main.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "policies.h"
-#include "proto_control0.h"
-#include "proto_http.h"
-#include "reasons.h"
-#include "rendclient.h"
-#include "rendcommon.h"
-#include "rendservice.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "shared_random_client.h"
+#include "core/or/or.h"
+#include "feature/client/addressmap.h"
+#include "feature/client/bridges.h"
+#include "lib/container/buffers.h"
+#include "core/or/channel.h"
+#include "core/or/channeltls.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuitstats.h"
+#include "core/or/circuituse.h"
+#include "core/or/command.h"
+#include "lib/evloop/compat_libevent.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "core/or/connection_or.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/dircache/directory.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/client/dnsserv.h"
+#include "feature/client/entrynodes.h"
+#include "feature/stats/geoip.h"
+#include "feature/hibernate/hibernate.h"
+#include "feature/hs/hs_cache.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_control.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "core/proto/proto_control0.h"
+#include "core/proto/proto_http.h"
+#include "core/or/reasons.h"
+#include "feature/rend/rendclient.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/rend/rendservice.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/hs_common/shared_random_client.h"
+#include "lib/encoding/confline.h"
+
+#include "feature/dircache/cached_dir_st.h"
+#include "feature/control/control_connection_st.h"
+#include "core/or/cpath_build_state_st.h"
+#include "core/or/entry_connection_st.h"
+#include "feature/nodelist/extrainfo_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/node_st.h"
+#include "core/or/or_connection_st.h"
+#include "core/or/or_circuit_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "feature/nodelist/microdesc_st.h"
+#include "feature/rend/rend_authorized_client_st.h"
+#include "feature/rend/rend_encoded_v2_service_descriptor_st.h"
+#include "feature/rend/rend_service_descriptor_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerlist_st.h"
+#include "core/or/socks_request_st.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
#ifndef _WIN32
#include <pwd.h>
#include <sys/resource.h>
#endif
-#include "crypto_s2k.h"
-#include "procmon.h"
+#include "lib/crypt_ops/crypto_s2k.h"
+#include "lib/evloop/procmon.h"
+#include "lib/evloop/compat_libevent.h"
/** Yield true iff <b>s</b> is the state of a control_connection_t that has
* finished authentication and is accepting commands. */
@@ -226,6 +253,15 @@ static void flush_queued_events_cb(mainloop_event_t *event, void *arg);
static char * download_status_to_string(const download_status_t *dl);
static void control_get_bytes_rw_last_sec(uint64_t *r, uint64_t *w);
+/** Convert a connection_t* to an control_connection_t*; assert if the cast is
+ * invalid. */
+control_connection_t *
+TO_CONTROL_CONN(connection_t *c)
+{
+ tor_assert(c->magic == CONTROL_CONNECTION_MAGIC);
+ return DOWNCAST(control_connection_t, c);
+}
+
/** Given a control event code for a message event, return the corresponding
* log severity. */
static inline int
@@ -1857,9 +1893,9 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
}
*answer = tor_dup_ip(addr);
} else if (!strcmp(question, "traffic/read")) {
- tor_asprintf(answer, U64_FORMAT, U64_PRINTF_ARG(get_bytes_read()));
+ tor_asprintf(answer, "%"PRIu64, (get_bytes_read()));
} else if (!strcmp(question, "traffic/written")) {
- tor_asprintf(answer, U64_FORMAT, U64_PRINTF_ARG(get_bytes_written()));
+ tor_asprintf(answer, "%"PRIu64, (get_bytes_written()));
} else if (!strcmp(question, "process/pid")) {
int myPid = -1;
@@ -1894,8 +1930,8 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
int max_fds = get_max_sockets();
tor_asprintf(answer, "%d", max_fds);
} else if (!strcmp(question, "limits/max-mem-in-queues")) {
- tor_asprintf(answer, U64_FORMAT,
- U64_PRINTF_ARG(get_options()->MaxMemInQueues));
+ tor_asprintf(answer, "%"PRIu64,
+ (get_options()->MaxMemInQueues));
} else if (!strcmp(question, "fingerprint")) {
crypto_pk_t *server_key;
if (!server_mode(get_options())) {
@@ -2207,6 +2243,27 @@ getinfo_helper_dir(control_connection_t *control_conn,
return -1;
}
}
+ } else if (!strcmp(question, "md/all")) {
+ const smartlist_t *nodes = nodelist_get_list();
+ tor_assert(nodes);
+
+ if (smartlist_len(nodes) == 0) {
+ *answer = tor_strdup("");
+ return 0;
+ }
+
+ smartlist_t *microdescs = smartlist_new();
+
+ SMARTLIST_FOREACH_BEGIN(nodes, node_t *, n) {
+ if (n->md && n->md->body) {
+ char *copy = tor_strndup(n->md->body, n->md->bodylen);
+ smartlist_add(microdescs, copy);
+ }
+ } SMARTLIST_FOREACH_END(n);
+
+ *answer = smartlist_join_strings(microdescs, "", 0, NULL);
+ SMARTLIST_FOREACH(microdescs, char *, md, tor_free(md));
+ smartlist_free(microdescs);
} else if (!strcmpstart(question, "md/id/")) {
const node_t *node = node_get_by_hex_id(question+strlen("md/id/"), 0);
const microdesc_t *md = NULL;
@@ -3241,6 +3298,7 @@ static const getinfo_item_t getinfo_items[] = {
ITEM("desc/download-enabled", dir,
"Do we try to download router descriptors?"),
ITEM("desc/all-recent-extrainfo-hack", dir, NULL), /* Hack. */
+ ITEM("md/all", dir, "All known microdescriptors."),
PREFIX("md/id/", dir, "Microdescriptors by ID"),
PREFIX("md/name/", dir, "Microdescriptors by name"),
ITEM("md/download-enabled", dir,
@@ -3400,6 +3458,7 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
SMARTLIST_FOREACH_BEGIN(questions, const char *, q) {
const char *errmsg = NULL;
+
if (handle_getinfo_helper(conn, q, &ans, &errmsg) < 0) {
if (!errmsg)
errmsg = "Internal error";
@@ -4629,7 +4688,7 @@ handle_control_add_onion(control_connection_t *conn,
static const char *max_s_prefix = "MaxStreams=";
static const char *auth_prefix = "ClientAuth=";
- const char *arg = smartlist_get(args, i);
+ const char *arg = smartlist_get(args, (int)i);
if (!strcasecmpstart(arg, port_prefix)) {
/* "Port=VIRTPORT[,TARGET]". */
const char *port_str = arg + strlen(port_prefix);
@@ -5832,8 +5891,8 @@ control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp,
if (circ && CIRCUIT_IS_ORIGIN(circ))
origin_circ = TO_ORIGIN_CIRCUIT(circ);
send_control_event(EVENT_STREAM_STATUS,
- "650 STREAM "U64_FORMAT" %s %lu %s%s%s%s\r\n",
- U64_PRINTF_ARG(ENTRY_TO_CONN(conn)->global_identifier),
+ "650 STREAM %"PRIu64" %s %lu %s%s%s%s\r\n",
+ (ENTRY_TO_CONN(conn)->global_identifier),
status,
origin_circ?
(unsigned long)origin_circ->global_identifier : 0ul,
@@ -5904,12 +5963,12 @@ control_event_or_conn_status(or_connection_t *conn, or_conn_status_event_t tp,
orconn_target_get_name(name, sizeof(name), conn);
send_control_event(EVENT_OR_CONN_STATUS,
- "650 ORCONN %s %s%s%s%s ID="U64_FORMAT"\r\n",
+ "650 ORCONN %s %s%s%s%s ID=%"PRIu64"\r\n",
name, status,
reason ? " REASON=" : "",
orconn_end_reason_to_control_string(reason),
ncircs_buf,
- U64_PRINTF_ARG(conn->base_.global_identifier));
+ (conn->base_.global_identifier));
return 0;
}
@@ -5929,8 +5988,8 @@ control_event_stream_bandwidth(edge_connection_t *edge_conn)
tor_gettimeofday(&now);
format_iso_time_nospace_usec(tbuf, &now);
send_control_event(EVENT_STREAM_BANDWIDTH_USED,
- "650 STREAM_BW "U64_FORMAT" %lu %lu %s\r\n",
- U64_PRINTF_ARG(edge_conn->base_.global_identifier),
+ "650 STREAM_BW %"PRIu64" %lu %lu %s\r\n",
+ (edge_conn->base_.global_identifier),
(unsigned long)edge_conn->n_read,
(unsigned long)edge_conn->n_written,
tbuf);
@@ -5963,8 +6022,8 @@ control_event_stream_bandwidth_used(void)
tor_gettimeofday(&now);
format_iso_time_nospace_usec(tbuf, &now);
send_control_event(EVENT_STREAM_BANDWIDTH_USED,
- "650 STREAM_BW "U64_FORMAT" %lu %lu %s\r\n",
- U64_PRINTF_ARG(edge_conn->base_.global_identifier),
+ "650 STREAM_BW %"PRIu64" %lu %lu %s\r\n",
+ (edge_conn->base_.global_identifier),
(unsigned long)edge_conn->n_read,
(unsigned long)edge_conn->n_written,
tbuf);
@@ -6042,9 +6101,9 @@ control_event_conn_bandwidth(connection_t *conn)
return 0;
}
send_control_event(EVENT_CONN_BW,
- "650 CONN_BW ID="U64_FORMAT" TYPE=%s "
+ "650 CONN_BW ID=%"PRIu64" TYPE=%s "
"READ=%lu WRITTEN=%lu\r\n",
- U64_PRINTF_ARG(conn->global_identifier),
+ (conn->global_identifier),
conn_type_str,
(unsigned long)conn->n_read_conn_bw,
(unsigned long)conn->n_written_conn_bw);
@@ -6109,9 +6168,9 @@ append_cell_stats_by_command(smartlist_t *event_parts, const char *key,
int i;
for (i = 0; i <= CELL_COMMAND_MAX_; i++) {
if (include_if_non_zero[i] > 0) {
- smartlist_add_asprintf(key_value_strings, "%s:"U64_FORMAT,
+ smartlist_add_asprintf(key_value_strings, "%s:%"PRIu64,
cell_command_to_string(i),
- U64_PRINTF_ARG(number_to_include[i]));
+ (number_to_include[i]));
}
}
if (smartlist_len(key_value_strings) > 0) {
@@ -6138,8 +6197,8 @@ format_cell_stats(char **event_string, circuit_t *circ,
or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
smartlist_add_asprintf(event_parts, "InboundQueue=%lu",
(unsigned long)or_circ->p_circ_id);
- smartlist_add_asprintf(event_parts, "InboundConn="U64_FORMAT,
- U64_PRINTF_ARG(or_circ->p_chan->global_identifier));
+ smartlist_add_asprintf(event_parts, "InboundConn=%"PRIu64,
+ (or_circ->p_chan->global_identifier));
append_cell_stats_by_command(event_parts, "InboundAdded",
cell_stats->added_cells_appward,
cell_stats->added_cells_appward);
@@ -6153,8 +6212,8 @@ format_cell_stats(char **event_string, circuit_t *circ,
if (circ->n_chan) {
smartlist_add_asprintf(event_parts, "OutboundQueue=%lu",
(unsigned long)circ->n_circ_id);
- smartlist_add_asprintf(event_parts, "OutboundConn="U64_FORMAT,
- U64_PRINTF_ARG(circ->n_chan->global_identifier));
+ smartlist_add_asprintf(event_parts, "OutboundConn=%"PRIu64,
+ (circ->n_chan->global_identifier));
append_cell_stats_by_command(event_parts, "OutboundAdded",
cell_stats->added_cells_exitward,
cell_stats->added_cells_exitward);
@@ -7741,4 +7800,3 @@ control_testing_set_global_event_mask(uint64_t mask)
global_event_mask = mask;
}
#endif /* defined(TOR_UNIT_TESTS) */
-
diff --git a/src/or/control.h b/src/feature/control/control.h
index 92cbf866dd..5c5fe8a917 100644
--- a/src/or/control.h
+++ b/src/feature/control/control.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,6 +12,93 @@
#ifndef TOR_CONTROL_H
#define TOR_CONTROL_H
+/** Used to indicate the type of a circuit event passed to the controller.
+ * The various types are defined in control-spec.txt */
+typedef enum circuit_status_event_t {
+ CIRC_EVENT_LAUNCHED = 0,
+ CIRC_EVENT_BUILT = 1,
+ CIRC_EVENT_EXTENDED = 2,
+ CIRC_EVENT_FAILED = 3,
+ CIRC_EVENT_CLOSED = 4,
+} circuit_status_event_t;
+
+/** Used to indicate the type of a CIRC_MINOR event passed to the controller.
+ * The various types are defined in control-spec.txt . */
+typedef enum circuit_status_minor_event_t {
+ CIRC_MINOR_EVENT_PURPOSE_CHANGED,
+ CIRC_MINOR_EVENT_CANNIBALIZED,
+} circuit_status_minor_event_t;
+
+/** Used to indicate the type of a stream event passed to the controller.
+ * The various types are defined in control-spec.txt */
+typedef enum stream_status_event_t {
+ STREAM_EVENT_SENT_CONNECT = 0,
+ STREAM_EVENT_SENT_RESOLVE = 1,
+ STREAM_EVENT_SUCCEEDED = 2,
+ STREAM_EVENT_FAILED = 3,
+ STREAM_EVENT_CLOSED = 4,
+ STREAM_EVENT_NEW = 5,
+ STREAM_EVENT_NEW_RESOLVE = 6,
+ STREAM_EVENT_FAILED_RETRIABLE = 7,
+ STREAM_EVENT_REMAP = 8
+} stream_status_event_t;
+
+/** Used to indicate the type of an OR connection event passed to the
+ * controller. The various types are defined in control-spec.txt */
+typedef enum or_conn_status_event_t {
+ OR_CONN_EVENT_LAUNCHED = 0,
+ OR_CONN_EVENT_CONNECTED = 1,
+ OR_CONN_EVENT_FAILED = 2,
+ OR_CONN_EVENT_CLOSED = 3,
+ OR_CONN_EVENT_NEW = 4,
+} or_conn_status_event_t;
+
+/** Used to indicate the type of a buildtime event */
+typedef enum buildtimeout_set_event_t {
+ BUILDTIMEOUT_SET_EVENT_COMPUTED = 0,
+ BUILDTIMEOUT_SET_EVENT_RESET = 1,
+ BUILDTIMEOUT_SET_EVENT_SUSPENDED = 2,
+ BUILDTIMEOUT_SET_EVENT_DISCARD = 3,
+ BUILDTIMEOUT_SET_EVENT_RESUME = 4
+} buildtimeout_set_event_t;
+
+/** Enum describing various stages of bootstrapping, for use with controller
+ * bootstrap status events. The values range from 0 to 100. */
+typedef enum {
+ BOOTSTRAP_STATUS_UNDEF=-1,
+ BOOTSTRAP_STATUS_STARTING=0,
+ BOOTSTRAP_STATUS_CONN_DIR=5,
+ BOOTSTRAP_STATUS_HANDSHAKE=-2,
+ BOOTSTRAP_STATUS_HANDSHAKE_DIR=10,
+ BOOTSTRAP_STATUS_ONEHOP_CREATE=15,
+ BOOTSTRAP_STATUS_REQUESTING_STATUS=20,
+ BOOTSTRAP_STATUS_LOADING_STATUS=25,
+ BOOTSTRAP_STATUS_LOADING_KEYS=40,
+ BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS=45,
+ BOOTSTRAP_STATUS_LOADING_DESCRIPTORS=50,
+ BOOTSTRAP_STATUS_CONN_OR=80,
+ BOOTSTRAP_STATUS_HANDSHAKE_OR=85,
+ BOOTSTRAP_STATUS_CIRCUIT_CREATE=90,
+ BOOTSTRAP_STATUS_DONE=100
+} bootstrap_status_t;
+
+control_connection_t *TO_CONTROL_CONN(connection_t *);
+
+#define CONTROL_CONN_STATE_MIN_ 1
+/** State for a control connection: Authenticated and accepting v1 commands. */
+#define CONTROL_CONN_STATE_OPEN 1
+/** State for a control connection: Waiting for authentication; speaking
+ * protocol v1. */
+#define CONTROL_CONN_STATE_NEEDAUTH 2
+#define CONTROL_CONN_STATE_MAX_ 2
+
+/** Reason for remapping an AP connection's address: we have a cached
+ * answer. */
+#define REMAP_STREAM_SOURCE_CACHE 1
+/** Reason for remapping an AP connection's address: the exit node told us an
+ * answer. */
+#define REMAP_STREAM_SOURCE_EXIT 2
+
void control_initialize_event_queue(void);
void control_update_global_event_mask(void);
@@ -97,7 +184,8 @@ int control_event_signal(uintptr_t signal);
int init_control_cookie_authentication(int enabled);
char *get_controller_cookie_file_name(void);
-smartlist_t *decode_hashed_passwords(config_line_t *passwords);
+struct config_line_t;
+smartlist_t *decode_hashed_passwords(struct config_line_t *passwords);
void disable_control_logging(void);
void enable_control_logging(void);
@@ -160,6 +248,8 @@ void control_event_hs_descriptor_content(const char *onion_address,
void control_free_all(void);
#ifdef CONTROL_PRIVATE
+#include "lib/crypt_ops/crypto_ed25519.h"
+
/* Recognized asynchronous event types. It's okay to expand this list
* because it is used both as a list of v0 event types, and as indices
* into the bitfield to determine which controllers want which events.
@@ -323,4 +413,3 @@ STATIC int getinfo_helper_current_time(
#endif /* defined(CONTROL_PRIVATE) */
#endif /* !defined(TOR_CONTROL_H) */
-
diff --git a/src/feature/control/control_connection_st.h b/src/feature/control/control_connection_st.h
new file mode 100644
index 0000000000..ff6264a9a5
--- /dev/null
+++ b/src/feature/control/control_connection_st.h
@@ -0,0 +1,46 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef CONTROL_CONNECTION_ST_H
+#define CONTROL_CONNECTION_ST_H
+
+#include "core/or/or.h"
+#include "core/or/connection_st.h"
+
+/** Subtype of connection_t for an connection to a controller. */
+struct control_connection_t {
+ connection_t base_;
+
+ uint64_t event_mask; /**< Bitfield: which events does this controller
+ * care about?
+ * EVENT_MAX_ is >31, so we need a 64 bit mask */
+
+ /** True if we have sent a protocolinfo reply on this connection. */
+ unsigned int have_sent_protocolinfo:1;
+ /** True if we have received a takeownership command on this
+ * connection. */
+ unsigned int is_owning_control_connection:1;
+
+ /** List of ephemeral onion services belonging to this connection. */
+ smartlist_t *ephemeral_onion_services;
+
+ /** If we have sent an AUTHCHALLENGE reply on this connection and
+ * have not received a successful AUTHENTICATE command, points to
+ * the value which the client must send to authenticate itself;
+ * otherwise, NULL. */
+ char *safecookie_client_hash;
+
+ /** Amount of space allocated in incoming_cmd. */
+ uint32_t incoming_cmd_len;
+ /** Number of bytes currently stored in incoming_cmd. */
+ uint32_t incoming_cmd_cur_len;
+ /** A control command that we're reading from the inbuf, but which has not
+ * yet arrived completely. */
+ char *incoming_cmd;
+};
+
+#endif
+
diff --git a/src/or/dirauth/dircollate.c b/src/feature/dirauth/dircollate.c
index dec6f75154..ca8e5b7873 100644
--- a/src/or/dirauth/dircollate.c
+++ b/src/feature/dirauth/dircollate.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -22,8 +22,11 @@
*/
#define DIRCOLLATE_PRIVATE
-#include "dircollate.h"
-#include "dirvote.h"
+#include "feature/dirauth/dircollate.h"
+#include "feature/dirauth/dirvote.h"
+
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/vote_routerstatus_st.h"
static void dircollator_collate_by_ed25519(dircollator_t *dc);
diff --git a/src/or/dirauth/dircollate.h b/src/feature/dirauth/dircollate.h
index 0584b2fe06..0e84c66e6f 100644
--- a/src/or/dirauth/dircollate.h
+++ b/src/feature/dirauth/dircollate.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,8 +12,8 @@
#ifndef TOR_DIRCOLLATE_H
#define TOR_DIRCOLLATE_H
-#include "testsupport.h"
-#include "or.h"
+#include "lib/testsupport/testsupport.h"
+#include "core/or/or.h"
typedef struct dircollator_s dircollator_t;
diff --git a/src/or/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c
index b097b10cf9..ce67c1bb9a 100644
--- a/src/or/dirauth/dirvote.c
+++ b/src/feature/dirauth/dirvote.c
@@ -1,32 +1,51 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define DIRVOTE_PRIVATE
-#include "or.h"
-#include "config.h"
-#include "dircollate.h"
-#include "directory.h"
-#include "dirserv.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "parsecommon.h"
-#include "policies.h"
-#include "protover.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerkeys.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "entrynodes.h" /* needed for guardfraction methods */
-#include "torcert.h"
-#include "voting_schedule.h"
-
-#include "dirauth/dirvote.h"
-#include "dirauth/mode.h"
-#include "dirauth/shared_random_state.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "feature/dirauth/dircollate.h"
+#include "feature/dircache/directory.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/parsecommon.h"
+#include "core/or/policies.h"
+#include "core/or/protover.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routerkeys.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/client/entrynodes.h" /* needed for guardfraction methods */
+#include "feature/nodelist/torcert.h"
+#include "feature/dircommon/voting_schedule.h"
+
+#include "feature/dirauth/dirvote.h"
+#include "feature/dirauth/mode.h"
+#include "feature/dirauth/shared_random_state.h"
+
+#include "feature/nodelist/authority_cert_st.h"
+#include "feature/dircache/cached_dir_st.h"
+#include "feature/dirclient/dir_server_st.h"
+#include "feature/nodelist/document_signature_st.h"
+#include "feature/nodelist/microdesc_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/networkstatus_voter_info_st.h"
+#include "feature/nodelist/node_st.h"
+#include "feature/dirauth/ns_detached_signatures_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerlist_st.h"
+#include "feature/dirauth/vote_microdesc_hash_st.h"
+#include "feature/nodelist/vote_routerstatus_st.h"
+#include "feature/dircommon/vote_timing_st.h"
+
+#include "lib/container/order.h"
+#include "lib/encoding/confline.h"
+#include "lib/crypt_ops/crypto_format.h"
/**
* \file dirvote.c
@@ -982,13 +1001,13 @@ networkstatus_check_weights(int64_t Wgg, int64_t Wgd, int64_t Wmg,
out:
if (berr) {
log_info(LD_DIR,
- "Bw weight mismatch %d. G="I64_FORMAT" M="I64_FORMAT
- " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT
+ "Bw weight mismatch %d. G=%"PRId64" M=%"PRId64
+ " E=%"PRId64" D=%"PRId64" T=%"PRId64
" Wmd=%d Wme=%d Wmg=%d Wed=%d Wee=%d"
" Wgd=%d Wgg=%d Wme=%d Wmg=%d",
berr,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ (G), (M), (E),
+ (D), (T),
(int)Wmd, (int)Wme, (int)Wmg, (int)Wed, (int)Wee,
(int)Wgd, (int)Wgg, (int)Wme, (int)Wmg);
}
@@ -1014,10 +1033,10 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
if (G <= 0 || M <= 0 || E <= 0 || D <= 0) {
log_warn(LD_DIR, "Consensus with empty bandwidth: "
- "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
- " D="I64_FORMAT" T="I64_FORMAT,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T));
+ "G=%"PRId64" M=%"PRId64" E=%"PRId64
+ " D=%"PRId64" T=%"PRId64,
+ (G), (M), (E),
+ (D), (T));
return 0;
}
@@ -1048,13 +1067,13 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
if (berr) {
log_warn(LD_DIR,
- "Bw Weights error %d for %s v10. G="I64_FORMAT" M="I64_FORMAT
- " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT
+ "Bw Weights error %d for %s v10. G=%"PRId64" M=%"PRId64
+ " E=%"PRId64" D=%"PRId64" T=%"PRId64
" Wmd=%d Wme=%d Wmg=%d Wed=%d Wee=%d"
" Wgd=%d Wgg=%d Wme=%d Wmg=%d weight_scale=%d",
berr, casename,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ (G), (M), (E),
+ (D), (T),
(int)Wmd, (int)Wme, (int)Wmg, (int)Wed, (int)Wee,
(int)Wgd, (int)Wgg, (int)Wme, (int)Wmg, (int)weight_scale);
return 0;
@@ -1119,13 +1138,13 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
if (berr != BW_WEIGHTS_NO_ERROR &&
berr != BW_WEIGHTS_BALANCE_MID_ERROR) {
log_warn(LD_DIR,
- "Bw Weights error %d for %s v10. G="I64_FORMAT" M="I64_FORMAT
- " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT
+ "Bw Weights error %d for %s v10. G=%"PRId64" M=%"PRId64
+ " E=%"PRId64" D=%"PRId64" T=%"PRId64
" Wmd=%d Wme=%d Wmg=%d Wed=%d Wee=%d"
" Wgd=%d Wgg=%d Wme=%d Wmg=%d weight_scale=%d",
berr, casename,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ (G), (M), (E),
+ (D), (T),
(int)Wmd, (int)Wme, (int)Wmg, (int)Wed, (int)Wee,
(int)Wgd, (int)Wgg, (int)Wme, (int)Wmg, (int)weight_scale);
return 0;
@@ -1136,10 +1155,10 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
// Case 3: Exactly one of Guard or Exit is scarce
if (!(3*E < T || 3*G < T) || !(3*G >= T || 3*E >= T)) {
log_warn(LD_BUG,
- "Bw-Weights Case 3 v10 but with G="I64_FORMAT" M="
- I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T));
+ "Bw-Weights Case 3 v10 but with G=%"PRId64" M="
+ "%"PRId64" E=%"PRId64" D=%"PRId64" T=%"PRId64,
+ (G), (M), (E),
+ (D), (T));
}
if (3*(S+D) < T) { // Subcase a: S+D < T/3
@@ -1191,13 +1210,13 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
}
if (berr) {
log_warn(LD_DIR,
- "Bw Weights error %d for %s v10. G="I64_FORMAT" M="I64_FORMAT
- " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT
+ "Bw Weights error %d for %s v10. G=%"PRId64" M=%"PRId64
+ " E=%"PRId64" D=%"PRId64" T=%"PRId64
" Wmd=%d Wme=%d Wmg=%d Wed=%d Wee=%d"
" Wgd=%d Wgg=%d Wme=%d Wmg=%d weight_scale=%d",
berr, casename,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ (G), (M), (E),
+ (D), (T),
(int)Wmd, (int)Wme, (int)Wmg, (int)Wed, (int)Wee,
(int)Wgd, (int)Wgg, (int)Wme, (int)Wmg, (int)weight_scale);
return 0;
@@ -1231,11 +1250,11 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
(int)weight_scale, (int)Wmd, (int)Wme, (int)Wmg, (int)weight_scale);
log_notice(LD_CIRC, "Computed bandwidth weights for %s with v10: "
- "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
- " T="I64_FORMAT,
+ "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
+ " T=%"PRId64,
casename,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T));
+ (G), (M), (E),
+ (D), (T));
return 1;
}
@@ -1739,9 +1758,9 @@ networkstatus_compute_consensus(smartlist_t *votes,
/* Build the flag indexes. Note that no vote can have more than 64 members
* for known_flags, so no value will be greater than 63, so it's safe to
- * do U64_LITERAL(1) << index on these values. But note also that
+ * do UINT64_C(1) << index on these values. But note also that
* named_flag and unnamed_flag are initialized to -1, so we need to check
- * that they're actually set before doing U64_LITERAL(1) << index with
+ * that they're actually set before doing UINT64_C(1) << index with
* them.*/
SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) {
flag_map[v_sl_idx] = tor_calloc(smartlist_len(v->known_flags),
@@ -1770,7 +1789,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
uint64_t nf;
if (named_flag[v_sl_idx]<0)
continue;
- nf = U64_LITERAL(1) << named_flag[v_sl_idx];
+ nf = UINT64_C(1) << named_flag[v_sl_idx];
SMARTLIST_FOREACH_BEGIN(v->routerstatus_list,
vote_routerstatus_t *, rs) {
@@ -1795,7 +1814,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
uint64_t uf;
if (unnamed_flag[v_sl_idx]<0)
continue;
- uf = U64_LITERAL(1) << unnamed_flag[v_sl_idx];
+ uf = UINT64_C(1) << unnamed_flag[v_sl_idx];
SMARTLIST_FOREACH_BEGIN(v->routerstatus_list,
vote_routerstatus_t *, rs) {
if ((rs->flags & uf) != 0) {
@@ -1885,11 +1904,11 @@ networkstatus_compute_consensus(smartlist_t *votes,
/* Tally up all the flags. */
for (int flag = 0; flag < n_voter_flags[voter_idx]; ++flag) {
- if (rs->flags & (U64_LITERAL(1) << flag))
+ if (rs->flags & (UINT64_C(1) << flag))
++flag_counts[flag_map[voter_idx][flag]];
}
if (named_flag[voter_idx] >= 0 &&
- (rs->flags & (U64_LITERAL(1) << named_flag[voter_idx]))) {
+ (rs->flags & (UINT64_C(1) << named_flag[voter_idx]))) {
if (chosen_name && strcmp(chosen_name, rs->status.nickname)) {
log_notice(LD_DIR, "Conflict on naming for router: %s vs %s",
chosen_name, rs->status.nickname);
@@ -4220,7 +4239,7 @@ routers_make_ed_keys_unique(smartlist_t *routers)
if (ri2_pub < ri_pub ||
(ri2_pub == ri_pub &&
fast_memcmp(ri->cache_info.signed_descriptor_digest,
- ri2->cache_info.signed_descriptor_digest,DIGEST_LEN)<0)) {
+ ri2->cache_info.signed_descriptor_digest,DIGEST_LEN)<0)) {
digest256map_set(by_ed_key, pk, ri);
ri2->omit_from_vote = 1;
} else {
@@ -4393,10 +4412,10 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
vrs->protocols = tor_strdup(ri->protocol_list);
} else {
vrs->protocols = tor_strdup(
- protover_compute_for_old_tor(vrs->version));
+ protover_compute_for_old_tor(vrs->version));
}
vrs->microdesc = dirvote_format_all_microdesc_vote_lines(ri, now,
- microdescriptors);
+ microdescriptors);
smartlist_add(routerstatuses, vrs);
}
@@ -4489,9 +4508,9 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
/* We should not recommend anything we don't have. */
tor_assert_nonfatal(protover_all_supported(
- v3_out->recommended_relay_protocols, NULL));
+ v3_out->recommended_relay_protocols, NULL));
tor_assert_nonfatal(protover_all_supported(
- v3_out->recommended_client_protocols, NULL));
+ v3_out->recommended_client_protocols, NULL));
v3_out->package_lines = smartlist_new();
{
@@ -4547,4 +4566,3 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
return v3_out;
}
-
diff --git a/src/or/dirauth/dirvote.h b/src/feature/dirauth/dirvote.h
index b69bbbf5d9..7ce8e4a699 100644
--- a/src/or/dirauth/dirvote.h
+++ b/src/feature/dirauth/dirvote.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -164,7 +164,8 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out)
}
static inline int
-dirvote_add_signatures(const char *detached_signatures_body, const char *source,
+dirvote_add_signatures(const char *detached_signatures_body,
+ const char *source,
const char **msg_out)
{
(void) detached_signatures_body;
@@ -244,4 +245,3 @@ STATIC microdesc_t *dirvote_create_microdescriptor(const routerinfo_t *ri,
#endif /* defined(DIRVOTE_PRIVATE) */
#endif /* !defined(TOR_DIRVOTE_H) */
-
diff --git a/src/or/keypin.c b/src/feature/dirauth/keypin.c
index 97e16c1f78..44e19985fa 100644
--- a/src/or/keypin.c
+++ b/src/feature/dirauth/keypin.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -11,17 +11,28 @@
#define KEYPIN_PRIVATE
#include "orconfig.h"
-#include "compat.h"
-#include "crypto_digest.h"
-#include "crypto_format.h"
-#include "di_ops.h"
+
+#include "lib/cc/torint.h"
+#include "lib/crypt_ops/crypto_digest.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/encoding/binascii.h"
+#include "lib/encoding/time_fmt.h"
+#include "lib/fdio/fdio.h"
+#include "lib/fs/files.h"
+#include "lib/fs/mmap.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/string/compat_ctype.h"
+#include "lib/string/printf.h"
+#include "lib/wallclock/approx_time.h"
+
#include "ht.h"
-#include "keypin.h"
+#include "feature/dirauth/keypin.h"
+
#include "siphash.h"
-#include "torint.h"
-#include "torlog.h"
-#include "util.h"
-#include "util_format.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -34,6 +45,10 @@
#include <io.h>
#endif
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
/**
* @file keypin.c
* @brief Key-pinning for RSA and Ed25519 identity keys at directory
@@ -308,7 +323,7 @@ keypin_open_journal(const char *fname)
char tbuf[ISO_TIME_LEN+1];
format_iso_time(tbuf, approx_time());
tor_snprintf(buf, sizeof(buf), "@opened-at %s\n", tbuf);
- if (write_all(fd, buf, strlen(buf), 0) < 0)
+ if (write_all_to_fd(fd, buf, strlen(buf)) < 0)
goto err;
keypin_journal_fd = fd;
@@ -347,7 +362,7 @@ keypin_journal_append_entry(const uint8_t *rsa_id_digest,
(const char*)ed25519_id_key);
line[BASE64_DIGEST_LEN+1+BASE64_DIGEST256_LEN] = '\n';
- if (write_all(keypin_journal_fd, line, JOURNAL_LINE_LEN, 0)<0) {
+ if (write_all_to_fd(keypin_journal_fd, line, JOURNAL_LINE_LEN)<0) {
log_warn(LD_DIRSERV, "Error while adding a line to the key-pinning "
"journal: %s", strerror(errno));
keypin_close_journal();
@@ -498,4 +513,3 @@ keypin_clear(void)
bad_entries);
}
}
-
diff --git a/src/or/keypin.h b/src/feature/dirauth/keypin.h
index fbb77e5c35..73a76be563 100644
--- a/src/or/keypin.h
+++ b/src/feature/dirauth/keypin.h
@@ -1,10 +1,10 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_KEYPIN_H
#define TOR_KEYPIN_H
-#include "testsupport.h"
+#include "lib/testsupport/testsupport.h"
int keypin_check_and_add(const uint8_t *rsa_id_digest,
const uint8_t *ed25519_id_key,
diff --git a/src/or/dirauth/mode.h b/src/feature/dirauth/mode.h
index 8a0d3142f1..8bb961dffb 100644
--- a/src/or/dirauth/mode.h
+++ b/src/feature/dirauth/mode.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -11,7 +11,7 @@
#ifdef HAVE_MODULE_DIRAUTH
-#include "router.h"
+#include "feature/relay/router.h"
/* Return true iff we believe ourselves to be a v3 authoritative directory
* server. */
diff --git a/src/feature/dirauth/ns_detached_signatures_st.h b/src/feature/dirauth/ns_detached_signatures_st.h
new file mode 100644
index 0000000000..26ceec84b9
--- /dev/null
+++ b/src/feature/dirauth/ns_detached_signatures_st.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef NS_DETACHED_SIGNATURES_ST_H
+#define NS_DETACHED_SIGNATURES_ST_H
+
+/** A set of signatures for a networkstatus consensus. Unless otherwise
+ * noted, all fields are as for networkstatus_t. */
+struct ns_detached_signatures_t {
+ time_t valid_after;
+ time_t fresh_until;
+ time_t valid_until;
+ strmap_t *digests; /**< Map from flavor name to digestset_t */
+ strmap_t *signatures; /**< Map from flavor name to list of
+ * document_signature_t */
+};
+
+#endif
+
diff --git a/src/or/dirauth/shared_random.c b/src/feature/dirauth/shared_random.c
index 6dd1f330e0..8ae2679779 100644
--- a/src/or/dirauth/shared_random.c
+++ b/src/feature/dirauth/shared_random.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -87,23 +87,25 @@
#define SHARED_RANDOM_PRIVATE
-#include "or.h"
-#include "shared_random.h"
-#include "config.h"
-#include "confparse.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "networkstatus.h"
-#include "router.h"
-#include "routerkeys.h"
-#include "routerlist.h"
-#include "shared_random_client.h"
-#include "shared_random_state.h"
-#include "util.h"
-#include "voting_schedule.h"
-
-#include "dirauth/dirvote.h"
-#include "dirauth/mode.h"
+#include "core/or/or.h"
+#include "feature/dirauth/shared_random.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routerkeys.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/hs_common/shared_random_client.h"
+#include "feature/dirauth/shared_random_state.h"
+#include "feature/dircommon/voting_schedule.h"
+
+#include "feature/dirauth/dirvote.h"
+#include "feature/dirauth/mode.h"
+
+#include "feature/nodelist/authority_cert_st.h"
+#include "feature/nodelist/networkstatus_st.h"
/* String prefix of shared random values in votes/consensuses. */
static const char previous_srv_str[] = "shared-rand-previous-value";
diff --git a/src/or/dirauth/shared_random.h b/src/feature/dirauth/shared_random.h
index 1778ce8f09..68ece9aec0 100644
--- a/src/or/dirauth/shared_random.h
+++ b/src/feature/dirauth/shared_random.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_SHARED_RANDOM_H
@@ -10,7 +10,7 @@
* with "sr_" which stands for shared random.
*/
-#include "or.h"
+#include "core/or/or.h"
/* Protocol version */
#define SR_PROTO_VERSION 1
diff --git a/src/or/dirauth/shared_random_state.c b/src/feature/dirauth/shared_random_state.c
index fc0e4e5630..55936a7367 100644
--- a/src/or/dirauth/shared_random_state.c
+++ b/src/feature/dirauth/shared_random_state.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,17 +10,20 @@
#define SHARED_RANDOM_STATE_PRIVATE
-#include "or.h"
-#include "config.h"
-#include "confparse.h"
-#include "crypto_util.h"
-#include "dirauth/dirvote.h"
-#include "networkstatus.h"
-#include "router.h"
-#include "shared_random.h"
-#include "shared_random_client.h"
-#include "shared_random_state.h"
-#include "voting_schedule.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/relay/router.h"
+#include "feature/dirauth/shared_random.h"
+#include "feature/hs_common/shared_random_client.h"
+#include "feature/dirauth/shared_random_state.h"
+#include "feature/dircommon/voting_schedule.h"
+#include "lib/encoding/confline.h"
+
+#include "app/config/or_state_st.h"
/* Default filename of the shared random state on disk. */
static const char default_fname[] = "sr-state";
@@ -1321,4 +1324,3 @@ get_sr_state(void)
}
#endif /* defined(TOR_UNIT_TESTS) */
-
diff --git a/src/or/dirauth/shared_random_state.h b/src/feature/dirauth/shared_random_state.h
index 60a326f86c..83edfaf103 100644
--- a/src/or/dirauth/shared_random_state.h
+++ b/src/feature/dirauth/shared_random_state.h
@@ -1,10 +1,10 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_SHARED_RANDOM_STATE_H
#define TOR_SHARED_RANDOM_STATE_H
-#include "shared_random.h"
+#include "feature/dirauth/shared_random.h"
/* Action that can be performed on the state for any objects. */
typedef enum {
@@ -85,11 +85,11 @@ typedef struct sr_disk_state_t {
/* State valid until? */
time_t ValidUntil;
/* All commits seen that are valid. */
- config_line_t *Commit;
+ struct config_line_t *Commit;
/* Previous and current shared random value. */
- config_line_t *SharedRandValues;
+ struct config_line_t *SharedRandValues;
/* Extra Lines for configuration we might not know. */
- config_line_t *ExtraLines;
+ struct config_line_t *ExtraLines;
} sr_disk_state_t;
/* API */
@@ -144,4 +144,3 @@ STATIC sr_state_t *get_sr_state(void);
#endif /* defined(TOR_UNIT_TESTS) */
#endif /* !defined(TOR_SHARED_RANDOM_STATE_H) */
-
diff --git a/src/feature/dirauth/vote_microdesc_hash_st.h b/src/feature/dirauth/vote_microdesc_hash_st.h
new file mode 100644
index 0000000000..31fc98040e
--- /dev/null
+++ b/src/feature/dirauth/vote_microdesc_hash_st.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef VOTE_MICRODESC_HASH_ST_H
+#define VOTE_MICRODESC_HASH_ST_H
+
+/** Linked list of microdesc hash lines for a single router in a directory
+ * vote.
+ */
+struct vote_microdesc_hash_t {
+ /** Next element in the list, or NULL. */
+ struct vote_microdesc_hash_t *next;
+ /** The raw contents of the microdesc hash line, from the "m" through the
+ * newline. */
+ char *microdesc_hash_line;
+};
+
+#endif
+
diff --git a/src/feature/dircache/cached_dir_st.h b/src/feature/dircache/cached_dir_st.h
new file mode 100644
index 0000000000..38ae86d975
--- /dev/null
+++ b/src/feature/dircache/cached_dir_st.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-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef CACHED_DIR_ST_H
+#define CACHED_DIR_ST_H
+
+/** A cached_dir_t represents a cacheable directory object, along with its
+ * compressed form. */
+struct cached_dir_t {
+ char *dir; /**< Contents of this object, NUL-terminated. */
+ char *dir_compressed; /**< Compressed contents of this object. */
+ size_t dir_len; /**< Length of <b>dir</b> (not counting its NUL). */
+ size_t dir_compressed_len; /**< Length of <b>dir_compressed</b>. */
+ time_t published; /**< When was this object published. */
+ common_digests_t digests; /**< Digests of this object (networkstatus only) */
+ /** Sha3 digest (also ns only) */
+ uint8_t digest_sha3_as_signed[DIGEST256_LEN];
+ int refcnt; /**< Reference count for this cached_dir_t. */
+};
+
+#endif
+
diff --git a/src/or/conscache.c b/src/feature/dircache/conscache.c
index 51dc9d621f..e9bf58a180 100644
--- a/src/or/conscache.c
+++ b/src/feature/dircache/conscache.c
@@ -1,12 +1,13 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
+#include "core/or/or.h"
-#include "config.h"
-#include "conscache.h"
-#include "crypto_util.h"
-#include "storagedir.h"
+#include "app/config/config.h"
+#include "feature/dircache/conscache.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/fs/storagedir.h"
+#include "lib/encoding/confline.h"
#define CCE_MAGIC 0x17162253
@@ -624,4 +625,3 @@ consensus_cache_entry_is_mapped(consensus_cache_entry_t *ent)
}
}
#endif /* defined(TOR_UNIT_TESTS) */
-
diff --git a/src/or/conscache.h b/src/feature/dircache/conscache.h
index 08a5c5a37b..c274a60393 100644
--- a/src/or/conscache.h
+++ b/src/feature/dircache/conscache.h
@@ -1,10 +1,10 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_CONSCACHE_H
#define TOR_CONSCACHE_H
-#include "handles.h"
+#include "lib/container/handles.h"
typedef struct consensus_cache_entry_t consensus_cache_entry_t;
typedef struct consensus_cache_t consensus_cache_t;
@@ -27,9 +27,9 @@ void consensus_cache_delete_pending(consensus_cache_t *cache,
int force);
int consensus_cache_get_n_filenames_available(consensus_cache_t *cache);
consensus_cache_entry_t *consensus_cache_add(consensus_cache_t *cache,
- const config_line_t *labels,
- const uint8_t *data,
- size_t datalen);
+ const struct config_line_t *labels,
+ const uint8_t *data,
+ size_t datalen);
consensus_cache_entry_t *consensus_cache_find_first(
consensus_cache_t *cache,
@@ -46,7 +46,7 @@ void consensus_cache_filter_list(smartlist_t *lst,
const char *consensus_cache_entry_get_value(const consensus_cache_entry_t *ent,
const char *key);
-const config_line_t *consensus_cache_entry_get_labels(
+const struct config_line_t *consensus_cache_entry_get_labels(
const consensus_cache_entry_t *ent);
void consensus_cache_entry_incref(consensus_cache_entry_t *ent);
@@ -64,4 +64,3 @@ int consensus_cache_entry_is_mapped(consensus_cache_entry_t *ent);
#endif
#endif /* !defined(TOR_CONSCACHE_H) */
-
diff --git a/src/or/consdiffmgr.c b/src/feature/dircache/consdiffmgr.c
index 323f4f9ca0..304b64f3b6 100644
--- a/src/or/consdiffmgr.c
+++ b/src/feature/dircache/consdiffmgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,15 +13,21 @@
#define CONSDIFFMGR_PRIVATE
-#include "or.h"
-#include "config.h"
-#include "conscache.h"
-#include "consdiff.h"
-#include "consdiffmgr.h"
-#include "cpuworker.h"
-#include "networkstatus.h"
-#include "routerparse.h"
-#include "workqueue.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "feature/dircache/conscache.h"
+#include "feature/dircommon/consdiff.h"
+#include "feature/dircache/consdiffmgr.h"
+#include "core/mainloop/cpuworker.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/routerparse.h"
+#include "lib/evloop/compat_libevent.h"
+#include "lib/evloop/workqueue.h"
+#include "lib/compress/compress.h"
+#include "lib/encoding/confline.h"
+
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/networkstatus_voter_info_st.h"
/**
* Labels to apply to items in the conscache object.
@@ -1937,4 +1943,3 @@ consensus_cache_entry_get_valid_after(const consensus_cache_entry_t *ent,
else
return 0;
}
-
diff --git a/src/or/consdiffmgr.h b/src/feature/dircache/consdiffmgr.h
index df569c8e23..66c3d65002 100644
--- a/src/or/consdiffmgr.h
+++ b/src/feature/dircache/consdiffmgr.h
@@ -1,9 +1,11 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_CONSDIFFMGR_H
#define TOR_CONSDIFFMGR_H
+enum compress_method_t;
+
/**
* Possible outcomes from trying to look up a given consensus diff.
*/
@@ -25,7 +27,7 @@ int consdiffmgr_add_consensus(const char *consensus,
consdiff_status_t consdiffmgr_find_consensus(
struct consensus_cache_entry_t **entry_out,
consensus_flavor_t flavor,
- compress_method_t method);
+ enum compress_method_t method);
consdiff_status_t consdiffmgr_find_diff_from(
struct consensus_cache_entry_t **entry_out,
@@ -33,7 +35,7 @@ consdiff_status_t consdiffmgr_find_diff_from(
int digest_type,
const uint8_t *digest,
size_t digestlen,
- compress_method_t method);
+ enum compress_method_t method);
int consensus_cache_entry_get_voter_id_digests(
const struct consensus_cache_entry_t *ent,
@@ -71,4 +73,3 @@ STATIC int uncompress_or_copy(char **out, size_t *outlen,
#endif /* defined(CONSDIFFMGR_PRIVATE) */
#endif /* !defined(TOR_CONSDIFFMGR_H) */
-
diff --git a/src/or/directory.c b/src/feature/dircache/directory.c
index e763de268f..a723176185 100644
--- a/src/or/directory.c
+++ b/src/feature/dircache/directory.c
@@ -1,47 +1,50 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define DIRECTORY_PRIVATE
-#include "or.h"
-#include "backtrace.h"
-#include "bridges.h"
-#include "buffers.h"
-#include "circuitbuild.h"
-#include "config.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "conscache.h"
-#include "consdiff.h"
-#include "consdiffmgr.h"
-#include "control.h"
-#include "compat.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "directory.h"
-#include "dirserv.h"
-#include "entrynodes.h"
-#include "geoip.h"
-#include "hs_cache.h"
-#include "hs_common.h"
-#include "hs_control.h"
-#include "hs_client.h"
-#include "main.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "policies.h"
-#include "relay.h"
-#include "rendclient.h"
-#include "rendcommon.h"
-#include "rendservice.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "routerset.h"
+#include "core/or/or.h"
+#include "lib/err/backtrace.h"
+#include "feature/client/bridges.h"
+#include "lib/container/buffers.h"
+#include "core/or/circuitbuild.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "feature/dircache/conscache.h"
+#include "feature/dircommon/consdiff.h"
+#include "feature/dircache/consdiffmgr.h"
+#include "feature/control/control.h"
+#include "lib/compress/compress.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/dircache/directory.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/client/entrynodes.h"
+#include "feature/dircommon/fp_pair.h"
+#include "feature/stats/geoip.h"
+#include "feature/hs/hs_cache.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_control.h"
+#include "feature/hs/hs_client.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "core/or/relay.h"
+#include "feature/rend/rendclient.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/rend/rendservice.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/routerset.h"
+#include "lib/encoding/confline.h"
+#include "lib/crypt_ops/crypto_format.h"
#if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
#if !defined(OpenBSD)
@@ -49,9 +52,19 @@
#endif
#endif
-#include "dirauth/dirvote.h"
-#include "dirauth/mode.h"
-#include "dirauth/shared_random.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/dirauth/mode.h"
+#include "feature/dirauth/shared_random.h"
+
+#include "feature/nodelist/authority_cert_st.h"
+#include "feature/dircache/cached_dir_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "feature/dirclient/dir_server_st.h"
+#include "core/or/entry_connection_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/node_st.h"
+#include "feature/rend/rend_service_descriptor_st.h"
+#include "feature/nodelist/routerinfo_st.h"
/**
* \file directory.c
@@ -131,6 +144,15 @@ static void connection_dir_close_consensus_fetches(
/********* START VARIABLES **********/
+/** Maximum size, in bytes, for resized buffers. */
+#define MAX_BUF_SIZE ((1<<24)-1) /* 16MB-1 */
+/** Maximum size, in bytes, for any directory object that we've downloaded. */
+#define MAX_DIR_DL_SIZE MAX_BUF_SIZE
+
+/** Maximum size, in bytes, for any directory object that we're accepting
+ * as an upload. */
+#define MAX_DIR_UL_SIZE MAX_BUF_SIZE
+
/** How far in the future do we allow a directory server to tell us it is
* before deciding that one of us has the wrong time? */
#define ALLOW_DIRECTORY_TIME_SKEW (30*60)
@@ -151,6 +173,15 @@ static void connection_dir_close_consensus_fetches(
/********* END VARIABLES ************/
+/** Convert a connection_t* to a dir_connection_t*; assert if the cast is
+ * invalid. */
+dir_connection_t *
+TO_DIR_CONN(connection_t *c)
+{
+ tor_assert(c->magic == DIR_CONNECTION_MAGIC);
+ return DOWNCAST(dir_connection_t, c);
+}
+
/** Return false if the directory purpose <b>dir_purpose</b>
* does not require an anonymous (three-hop) connection.
*
@@ -1910,12 +1941,12 @@ directory_send_command(dir_connection_t *conn,
log_debug(LD_DIR,
"Sent request to directory server '%s:%d': "
- "(purpose: %d, request size: " U64_FORMAT ", "
- "payload size: " U64_FORMAT ")",
+ "(purpose: %d, request size: %"TOR_PRIuSZ", "
+ "payload size: %"TOR_PRIuSZ")",
conn->base_.address, conn->base_.port,
conn->base_.purpose,
- U64_PRINTF_ARG(total_request_len),
- U64_PRINTF_ARG(payload ? payload_len : 0));
+ (total_request_len),
+ (payload ? payload_len : 0));
}
/** Parse an HTTP request string <b>headers</b> of the form
@@ -2401,14 +2432,14 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
tor_log(LOG_DEBUG, LD_DIR,
"Received response from directory server '%s:%d': %d %s "
- "(purpose: %d, response size: " U64_FORMAT
+ "(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,
escaped(reason), conn->base_.purpose,
- U64_PRINTF_ARG(received_bytes),
+ (received_bytes),
#ifdef MEASUREMENTS_21206
conn->data_cells_received, conn->data_cells_sent,
#endif
@@ -5614,6 +5645,27 @@ download_status_reset(download_status_t *dls)
/* Don't reset dls->want_authority or dls->increment_on */
}
+/** Return true iff, as of <b>now</b>, the resource tracked by <b>dls</b> is
+ * ready to get its download reattempted. */
+int
+download_status_is_ready(download_status_t *dls, time_t now)
+{
+ /* dls wasn't reset before it was used */
+ if (dls->next_attempt_at == 0) {
+ download_status_reset(dls);
+ }
+
+ return download_status_get_next_attempt_at(dls) <= now;
+}
+
+/** Mark <b>dl</b> as never downloadable. */
+void
+download_status_mark_impossible(download_status_t *dl)
+{
+ dl->n_download_failures = IMPOSSIBLE_TO_DOWNLOAD;
+ dl->n_download_attempts = IMPOSSIBLE_TO_DOWNLOAD;
+}
+
/** Return the number of failures on <b>dls</b> since the last success (if
* any). */
int
@@ -5912,4 +5964,3 @@ dir_split_resource_into_spoolable(const char *resource,
smartlist_free(fingerprints);
return r;
}
-
diff --git a/src/or/directory.h b/src/feature/dircache/directory.h
index 5f5ff7eca6..54ea0c584d 100644
--- a/src/or/directory.h
+++ b/src/feature/dircache/directory.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,82 @@
#ifndef TOR_DIRECTORY_H
#define TOR_DIRECTORY_H
-#include "hs_ident.h"
+#include "feature/hs/hs_ident.h"
+enum compress_method_t;
+
+dir_connection_t *TO_DIR_CONN(connection_t *c);
+
+#define DIR_CONN_STATE_MIN_ 1
+/** State for connection to directory server: waiting for connect(). */
+#define DIR_CONN_STATE_CONNECTING 1
+/** State for connection to directory server: sending HTTP request. */
+#define DIR_CONN_STATE_CLIENT_SENDING 2
+/** State for connection to directory server: reading HTTP response. */
+#define DIR_CONN_STATE_CLIENT_READING 3
+/** State for connection to directory server: happy and finished. */
+#define DIR_CONN_STATE_CLIENT_FINISHED 4
+/** State for connection at directory server: waiting for HTTP request. */
+#define DIR_CONN_STATE_SERVER_COMMAND_WAIT 5
+/** State for connection at directory server: sending HTTP response. */
+#define DIR_CONN_STATE_SERVER_WRITING 6
+#define DIR_CONN_STATE_MAX_ 6
+
+#define DIR_PURPOSE_MIN_ 4
+/** A connection to a directory server: set after a v2 rendezvous
+ * descriptor is downloaded. */
+#define DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2 4
+/** A connection to a directory server: download one or more server
+ * descriptors. */
+#define DIR_PURPOSE_FETCH_SERVERDESC 6
+/** A connection to a directory server: download one or more extra-info
+ * documents. */
+#define DIR_PURPOSE_FETCH_EXTRAINFO 7
+/** A connection to a directory server: upload a server descriptor. */
+#define DIR_PURPOSE_UPLOAD_DIR 8
+/** A connection to a directory server: upload a v3 networkstatus vote. */
+#define DIR_PURPOSE_UPLOAD_VOTE 10
+/** A connection to a directory server: upload a v3 consensus signature */
+#define DIR_PURPOSE_UPLOAD_SIGNATURES 11
+/** A connection to a directory server: download one or more v3 networkstatus
+ * votes. */
+#define DIR_PURPOSE_FETCH_STATUS_VOTE 12
+/** A connection to a directory server: download a v3 detached signatures
+ * object for a consensus. */
+#define DIR_PURPOSE_FETCH_DETACHED_SIGNATURES 13
+/** A connection to a directory server: download a v3 networkstatus
+ * consensus. */
+#define DIR_PURPOSE_FETCH_CONSENSUS 14
+/** A connection to a directory server: download one or more directory
+ * authority certificates. */
+#define DIR_PURPOSE_FETCH_CERTIFICATE 15
+
+/** Purpose for connection at a directory server. */
+#define DIR_PURPOSE_SERVER 16
+/** A connection to a hidden service directory server: upload a v2 rendezvous
+ * descriptor. */
+#define DIR_PURPOSE_UPLOAD_RENDDESC_V2 17
+/** A connection to a hidden service directory server: download a v2 rendezvous
+ * descriptor. */
+#define DIR_PURPOSE_FETCH_RENDDESC_V2 18
+/** A connection to a directory server: download a microdescriptor. */
+#define DIR_PURPOSE_FETCH_MICRODESC 19
+/** A connection to a hidden service directory: upload a v3 descriptor. */
+#define DIR_PURPOSE_UPLOAD_HSDESC 20
+/** A connection to a hidden service directory: fetch a v3 descriptor. */
+#define DIR_PURPOSE_FETCH_HSDESC 21
+/** A connection to a directory server: set after a hidden service descriptor
+ * is downloaded. */
+#define DIR_PURPOSE_HAS_FETCHED_HSDESC 22
+#define DIR_PURPOSE_MAX_ 22
+
+/** True iff <b>p</b> is a purpose corresponding to uploading
+ * data to a directory server. */
+#define DIR_PURPOSE_IS_UPLOAD(p) \
+ ((p)==DIR_PURPOSE_UPLOAD_DIR || \
+ (p)==DIR_PURPOSE_UPLOAD_VOTE || \
+ (p)==DIR_PURPOSE_UPLOAD_SIGNATURES || \
+ (p)==DIR_PURPOSE_UPLOAD_RENDDESC_V2 || \
+ (p)==DIR_PURPOSE_UPLOAD_HSDESC)
int directories_have_accepted_server_descriptor(void);
void directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
@@ -60,6 +135,7 @@ void directory_request_set_dir_addr_port(directory_request_t *req,
const tor_addr_port_t *p);
void directory_request_set_directory_id_digest(directory_request_t *req,
const char *digest);
+struct circuit_guard_state_t;
void directory_request_set_guard_state(directory_request_t *req,
struct circuit_guard_state_t *state);
void directory_request_set_router_purpose(directory_request_t *req,
@@ -88,7 +164,7 @@ void directory_request_add_header(directory_request_t *req,
MOCK_DECL(void, directory_initiate_request, (directory_request_t *request));
int parse_http_response(const char *headers, int *code, time_t *date,
- compress_method_t *compression, char **response);
+ enum compress_method_t *compression, char **response);
int parse_http_command(const char *headers,
char **command_out, char **url_out);
char *http_get_header(const char *headers, const char *which);
@@ -132,30 +208,9 @@ time_t download_status_increment_attempt(download_status_t *dls,
time(NULL))
void download_status_reset(download_status_t *dls);
-static int download_status_is_ready(download_status_t *dls, time_t now);
+int download_status_is_ready(download_status_t *dls, time_t now);
time_t download_status_get_next_attempt_at(const download_status_t *dls);
-
-/** Return true iff, as of <b>now</b>, the resource tracked by <b>dls</b> is
- * ready to get its download reattempted. */
-static inline int
-download_status_is_ready(download_status_t *dls, time_t now)
-{
- /* dls wasn't reset before it was used */
- if (dls->next_attempt_at == 0) {
- download_status_reset(dls);
- }
-
- return download_status_get_next_attempt_at(dls) <= now;
-}
-
-static void download_status_mark_impossible(download_status_t *dl);
-/** Mark <b>dl</b> as never downloadable. */
-static inline void
-download_status_mark_impossible(download_status_t *dl)
-{
- dl->n_download_failures = IMPOSSIBLE_TO_DOWNLOAD;
- dl->n_download_attempts = IMPOSSIBLE_TO_DOWNLOAD;
-}
+void download_status_mark_impossible(download_status_t *dl);
int download_status_get_n_failures(const download_status_t *dls);
int download_status_get_n_attempts(const download_status_t *dls);
@@ -208,7 +263,7 @@ struct directory_request_t {
/** Hidden-service-specific information v2. */
const rend_data_t *rend_query;
/** Extra headers to append to the request */
- config_line_t *additional_headers;
+ struct config_line_t *additional_headers;
/** Hidden-service-specific information for v3+. */
const hs_ident_dir_conn_t *hs_ident;
/** Used internally to directory.c: gets informed when the attempt to
@@ -222,8 +277,10 @@ STATIC int handle_get_hs_descriptor_v3(dir_connection_t *conn,
const struct get_handler_args_t *args);
STATIC int directory_handle_command(dir_connection_t *conn);
STATIC char *accept_encoding_header(void);
-STATIC int allowed_anonymous_connection_compression_method(compress_method_t);
-STATIC void warn_disallowed_anonymous_compression_method(compress_method_t);
+STATIC int allowed_anonymous_connection_compression_method(
+ enum compress_method_t);
+STATIC void warn_disallowed_anonymous_compression_method(
+ enum compress_method_t);
STATIC int handle_response_fetch_hsdesc_v3(dir_connection_t *conn,
const response_handler_args_t *args);
@@ -258,7 +315,8 @@ STATIC int handle_post_hs_descriptor(const char *url, const char *body);
STATIC char* authdir_type_to_string(dirinfo_type_t auth);
STATIC const char * dir_conn_purpose_to_string(int purpose);
STATIC int should_use_directory_guards(const or_options_t *options);
-STATIC compression_level_t choose_compression_level(ssize_t n_bytes);
+enum compression_level_t;
+STATIC enum compression_level_t choose_compression_level(ssize_t n_bytes);
STATIC int find_dl_min_delay(const download_status_t *dls,
const or_options_t *options);
@@ -287,4 +345,3 @@ STATIC unsigned parse_accept_encoding_header(const char *h);
#endif /* defined(TOR_UNIT_TESTS) || defined(DIRECTORY_PRIVATE) */
#endif /* !defined(TOR_DIRECTORY_H) */
-
diff --git a/src/or/dirserv.c b/src/feature/dircache/dirserv.c
index 2362089d32..c5286b0cbf 100644
--- a/src/or/dirserv.c
+++ b/src/feature/dircache/dirserv.c
@@ -1,45 +1,60 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define DIRSERV_PRIVATE
-#include "or.h"
-#include "buffers.h"
-#include "config.h"
-#include "confparse.h"
-#include "channel.h"
-#include "channeltls.h"
-#include "command.h"
-#include "connection.h"
-#include "connection_or.h"
-#include "conscache.h"
-#include "consdiffmgr.h"
-#include "control.h"
-#include "directory.h"
-#include "dirserv.h"
-#include "hibernate.h"
-#include "keypin.h"
-#include "main.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "policies.h"
-#include "protover.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "routerset.h"
-#include "torcert.h"
-#include "voting_schedule.h"
-
-#include "dirauth/dirvote.h"
+#include "core/or/or.h"
+#include "lib/container/buffers.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "core/or/channel.h"
+#include "core/or/channeltls.h"
+#include "core/or/command.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_or.h"
+#include "feature/dircache/conscache.h"
+#include "feature/dircache/consdiffmgr.h"
+#include "feature/control/control.h"
+#include "feature/dircache/directory.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/hibernate/hibernate.h"
+#include "feature/dirauth/keypin.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "core/or/protover.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/routerset.h"
+#include "feature/nodelist/torcert.h"
+#include "feature/dircommon/voting_schedule.h"
+
+#include "feature/dirauth/dirvote.h"
+
+#include "feature/dircache/cached_dir_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "feature/nodelist/extrainfo_st.h"
+#include "feature/nodelist/microdesc_st.h"
+#include "feature/nodelist/node_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerlist_st.h"
+#include "core/or/tor_version_st.h"
+#include "feature/nodelist/vote_routerstatus_st.h"
+
+#include "lib/compress/compress.h"
+#include "lib/container/order.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/encoding/confline.h"
/**
* \file dirserv.c
* \brief Directory server core implementation. Manages directory
- * contents and generates directories.
+ * contents and generates directory documents.
*
* This module implements most of directory cache functionality, and some of
* the directory authority functionality. The directory.c module delegates
@@ -3581,4 +3596,3 @@ dirserv_free_all(void)
dirserv_clear_measured_bw_cache();
}
-
diff --git a/src/or/dirserv.h b/src/feature/dircache/dirserv.h
index 9026f332bc..3b4a646094 100644
--- a/src/or/dirserv.h
+++ b/src/feature/dircache/dirserv.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,24 @@
#ifndef TOR_DIRSERV_H
#define TOR_DIRSERV_H
-#include "testsupport.h"
+struct ed25519_public_key_t;
+
+#include "lib/testsupport/testsupport.h"
+
+/** An enum to describe what format we're generating a routerstatus line in.
+ */
+typedef enum {
+ /** For use in a v2 opinion */
+ NS_V2,
+ /** For use in a consensus networkstatus document (ns flavor) */
+ NS_V3_CONSENSUS,
+ /** For use in a vote networkstatus document */
+ NS_V3_VOTE,
+ /** For passing to the controlport in response to a GETINFO request */
+ NS_CONTROL_PORT,
+ /** For use in a consensus networkstatus document (microdesc flavor) */
+ NS_V3_CONSENSUS_MICRODESC
+} routerstatus_format_type_t;
/** What fraction (1 over this number) of the relay ID space do we
* (as a directory authority) launch connections to at each reachability
@@ -87,6 +104,14 @@ typedef struct spooled_resource_t {
off_t cached_dir_offset;
} spooled_resource_t;
+#ifdef DIRSERV_PRIVATE
+typedef struct measured_bw_line_t {
+ char node_id[DIGEST_LEN];
+ char node_hex[MAX_HEX_NICKNAME_LEN+1];
+ long int bw_kb;
+} measured_bw_line_t;
+#endif /* defined(DIRSERV_PRIVATE) */
+
int connection_dirserv_flushed_some(dir_connection_t *conn);
int dirserv_add_own_fingerprint(crypto_pk_t *pk);
@@ -130,7 +155,7 @@ int dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
void dirserv_orconn_tls_done(const tor_addr_t *addr,
uint16_t or_port,
const char *digest_rcvd,
- const ed25519_public_key_t *ed_id_rcvd);
+ const struct ed25519_public_key_t *ed_id_rcvd);
int dirserv_should_launch_reachability_test(const routerinfo_t *ri,
const routerinfo_t *ri_old);
void dirserv_single_reachability_test(time_t now, routerinfo_t *router);
@@ -212,4 +237,3 @@ void dirserv_spool_sort(dir_connection_t *conn);
void dir_conn_clear_spool(dir_connection_t *conn);
#endif /* !defined(TOR_DIRSERV_H) */
-
diff --git a/src/feature/dirclient/dir_server_st.h b/src/feature/dirclient/dir_server_st.h
new file mode 100644
index 0000000000..0a6d8155ae
--- /dev/null
+++ b/src/feature/dirclient/dir_server_st.h
@@ -0,0 +1,54 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef DIR_SERVER_ST_H
+#define DIR_SERVER_ST_H
+
+#include "lib/cc/torint.h"
+#include "core/or/or.h"
+#include "feature/nodelist/routerstatus_st.h"
+
+/** Represents information about a single trusted or fallback directory
+ * server. */
+struct dir_server_t {
+ char *description;
+ char *nickname;
+ 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 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. */
+ char v3_identity_digest[DIGEST_LEN]; /**< Digest of v3 (authority only,
+ * high-security) identity key. */
+
+ unsigned int is_running:1; /**< True iff we think this server is running. */
+ unsigned int is_authority:1; /**< True iff this is a directory authority
+ * of some kind. */
+
+ /** True iff this server has accepted the most recent server descriptor
+ * we tried to upload to it. */
+ unsigned int has_accepted_serverdesc:1;
+
+ /** What kind of authority is this? (Bitfield.) */
+ dirinfo_type_t type;
+
+ time_t addr_current_at; /**< When was the document that we derived the
+ * address information from published? */
+
+ routerstatus_t fake_status; /**< Used when we need to pass this trusted
+ * dir_server_t to
+ * directory_request_set_routerstatus.
+ * as a routerstatus_t. Not updated by the
+ * router-status management code!
+ **/
+};
+
+#endif
diff --git a/src/feature/dirclient/download_status_st.h b/src/feature/dirclient/download_status_st.h
new file mode 100644
index 0000000000..3f18f754a1
--- /dev/null
+++ b/src/feature/dirclient/download_status_st.h
@@ -0,0 +1,65 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef DOWNLOAD_STATUS_ST_H
+#define DOWNLOAD_STATUS_ST_H
+
+/** Information about our plans for retrying downloads for a downloadable
+ * directory object.
+ * Each type of downloadable directory object has a corresponding retry
+ * <b>schedule</b>, which can be different depending on whether the object is
+ * being downloaded from an authority or a mirror (<b>want_authority</b>).
+ * <b>next_attempt_at</b> contains the next time we will attempt to download
+ * the object.
+ * For schedules that <b>increment_on</b> failure, <b>n_download_failures</b>
+ * is used to determine the position in the schedule. (Each schedule is a
+ * smartlist of integer delays, parsed from a CSV option.) Every time a
+ * connection attempt fails, <b>n_download_failures</b> is incremented,
+ * the new delay value is looked up from the schedule, and
+ * <b>next_attempt_at</b> is set delay seconds from the time the previous
+ * connection failed. Therefore, at most one failure-based connection can be
+ * in progress for each download_status_t.
+ * For schedules that <b>increment_on</b> attempt, <b>n_download_attempts</b>
+ * is used to determine the position in the schedule. Every time a
+ * connection attempt is made, <b>n_download_attempts</b> is incremented,
+ * the new delay value is looked up from the schedule, and
+ * <b>next_attempt_at</b> is set delay seconds from the time the previous
+ * connection was attempted. Therefore, multiple concurrent attempted-based
+ * connections can be in progress for each download_status_t.
+ * After an object is successfully downloaded, any other concurrent connections
+ * are terminated. A new schedule which starts at position 0 is used for
+ * subsequent downloads of the same object.
+ */
+struct download_status_t {
+ time_t next_attempt_at; /**< When should we try downloading this object
+ * again? */
+ uint8_t n_download_failures; /**< Number of failed downloads of the most
+ * recent object, since the last success. */
+ uint8_t n_download_attempts; /**< Number of (potentially concurrent) attempts
+ * to download the most recent object, since
+ * the last success. */
+ download_schedule_bitfield_t schedule : 8; /**< What kind of object is being
+ * downloaded? This determines the
+ * schedule used for the download.
+ */
+ download_want_authority_bitfield_t want_authority : 1; /**< Is the download
+ * happening from an authority
+ * or a mirror? This determines
+ * the schedule used for the
+ * download. */
+ download_schedule_increment_bitfield_t increment_on : 1; /**< does this
+ * schedule increment on each attempt,
+ * or after each failure? */
+ uint8_t last_backoff_position; /**< number of attempts/failures, depending
+ * on increment_on, when we last recalculated
+ * the delay. Only updated if backoff
+ * == 1. */
+ int last_delay_used; /**< last delay used for random exponential backoff;
+ * only updated if backoff == 1 */
+};
+
+#endif
+
diff --git a/src/or/consdiff.c b/src/feature/dircommon/consdiff.c
index deaf465fe7..1823dc07fb 100644
--- a/src/or/consdiff.c
+++ b/src/feature/dircommon/consdiff.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2014, Daniel Martí
- * Copyright (c) 2014, The Tor Project, Inc. */
+ * Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -38,10 +38,10 @@
#define CONSDIFF_PRIVATE
-#include "or.h"
-#include "consdiff.h"
-#include "memarea.h"
-#include "routerparse.h"
+#include "core/or/or.h"
+#include "feature/dircommon/consdiff.h"
+#include "lib/memarea/memarea.h"
+#include "feature/nodelist/routerparse.h"
static const char* ns_diff_version = "network-status-diff-version 1";
static const char* hash_token = "hash";
@@ -1412,4 +1412,3 @@ looks_like_a_consensus_diff(const char *document, size_t len)
return (len >= strlen(ns_diff_version) &&
fast_memeq(document, ns_diff_version, strlen(ns_diff_version)));
}
-
diff --git a/src/or/consdiff.h b/src/feature/dircommon/consdiff.h
index eb772c0b2b..a5e4ba5cbf 100644
--- a/src/or/consdiff.h
+++ b/src/feature/dircommon/consdiff.h
@@ -1,11 +1,11 @@
/* Copyright (c) 2014, Daniel Martí
- * Copyright (c) 2014, The Tor Project, Inc. */
+ * Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_CONSDIFF_H
#define TOR_CONSDIFF_H
-#include "or.h"
+#include "core/or/or.h"
char *consensus_diff_generate(const char *cons1,
const char *cons2);
@@ -15,6 +15,8 @@ char *consensus_diff_apply(const char *consensus,
int looks_like_a_consensus_diff(const char *document, size_t len);
#ifdef CONSDIFF_PRIVATE
+#include "lib/container/bitarray.h"
+
struct memarea_t;
/** Line type used for constructing consensus diffs. Each of these lines
@@ -95,4 +97,3 @@ MOCK_DECL(STATIC int,
#endif /* defined(CONSDIFF_PRIVATE) */
#endif /* !defined(TOR_CONSDIFF_H) */
-
diff --git a/src/feature/dircommon/dir_connection_st.h b/src/feature/dircommon/dir_connection_st.h
new file mode 100644
index 0000000000..768f6ba81e
--- /dev/null
+++ b/src/feature/dircommon/dir_connection_st.h
@@ -0,0 +1,67 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef DIR_CONNECTION_ST_H
+#define DIR_CONNECTION_ST_H
+
+#include "core/or/connection_st.h"
+
+struct tor_compress_state_t;
+
+/** Subtype of connection_t for an "directory connection" -- that is, an HTTP
+ * connection to retrieve or serve directory material. */
+struct dir_connection_t {
+ connection_t base_;
+
+ /** Which 'resource' did we ask the directory for? This is typically the part
+ * of the URL string that defines, relative to the directory conn purpose,
+ * what thing we want. For example, in router descriptor downloads by
+ * descriptor digest, it contains "d/", then one or more +-separated
+ * fingerprints.
+ **/
+ char *requested_resource;
+ unsigned int dirconn_direct:1; /**< Is this dirconn direct, or via Tor? */
+
+ /** If we're fetching descriptors, what router purpose shall we assign
+ * to them? */
+ uint8_t router_purpose;
+
+ /** List of spooled_resource_t for objects that we're spooling. We use
+ * it from back to front. */
+ smartlist_t *spool;
+ /** The compression object doing on-the-fly compression for spooled data. */
+ struct tor_compress_state_t *compress_state;
+
+ /** What rendezvous service are we querying for? */
+ rend_data_t *rend_data;
+
+ /* Hidden service connection identifier for dir connections: Used by HS
+ client-side code to fetch HS descriptors, and by the service-side code to
+ upload descriptors. */
+ struct hs_ident_dir_conn_t *hs_ident;
+
+ /** If this is a one-hop connection, tracks the state of the directory guard
+ * for this connection (if any). */
+ struct circuit_guard_state_t *guard_state;
+
+ char identity_digest[DIGEST_LEN]; /**< Hash of the public RSA key for
+ * the directory server's signing key. */
+
+ /** Unique ID for directory requests; this used to be in connection_t, but
+ * that's going away and being used on channels instead. The dirserver still
+ * needs this for the incoming side, so it's moved here. */
+ uint64_t dirreq_id;
+
+#ifdef MEASUREMENTS_21206
+ /** Number of RELAY_DATA cells received. */
+ uint32_t data_cells_received;
+
+ /** Number of RELAY_DATA cells sent. */
+ uint32_t data_cells_sent;
+#endif /* defined(MEASUREMENTS_21206) */
+};
+
+#endif
diff --git a/src/or/fp_pair.c b/src/feature/dircommon/fp_pair.c
index c938e76678..0544145284 100644
--- a/src/or/fp_pair.c
+++ b/src/feature/dircommon/fp_pair.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
+/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,8 +17,8 @@
* certificate for any (ID key, signing key) pair.
**/
-#include "or.h"
-#include "fp_pair.h"
+#include "core/or/or.h"
+#include "feature/dircommon/fp_pair.h"
/* Define fp_pair_map_t structures */
diff --git a/src/or/fp_pair.h b/src/feature/dircommon/fp_pair.h
index 4498a16101..500c7c9928 100644
--- a/src/or/fp_pair.h
+++ b/src/feature/dircommon/fp_pair.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
+/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,6 +9,12 @@
#ifndef _TOR_FP_PAIR_H
#define _TOR_FP_PAIR_H
+/** A pair of digests created by dir_split_resource_info_fingerprint_pairs() */
+typedef struct {
+ char first[DIGEST_LEN];
+ char second[DIGEST_LEN];
+} fp_pair_t;
+
/*
* Declare fp_pair_map_t functions and structs
*/
diff --git a/src/feature/dircommon/vote_timing_st.h b/src/feature/dircommon/vote_timing_st.h
new file mode 100644
index 0000000000..14c13eed28
--- /dev/null
+++ b/src/feature/dircommon/vote_timing_st.h
@@ -0,0 +1,24 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef VOTE_TIMING_ST_H
+#define VOTE_TIMING_ST_H
+
+/** Describes the schedule by which votes should be generated. */
+struct vote_timing_t {
+ /** Length in seconds between one consensus becoming valid and the next
+ * becoming valid. */
+ int vote_interval;
+ /** For how many intervals is a consensus valid? */
+ int n_intervals_valid;
+ /** Time in seconds allowed to propagate votes */
+ int vote_delay;
+ /** Time in seconds allowed to propagate signatures */
+ int dist_delay;
+};
+
+#endif
+
diff --git a/src/or/voting_schedule.c b/src/feature/dircommon/voting_schedule.c
index d230a6dbcd..84c016c2b9 100644
--- a/src/or/voting_schedule.c
+++ b/src/feature/dircommon/voting_schedule.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,11 +9,13 @@
**/
#define VOTING_SCHEDULE_PRIVATE
-#include "voting_schedule.h"
+#include "feature/dircommon/voting_schedule.h"
-#include "or.h"
-#include "config.h"
-#include "networkstatus.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "feature/nodelist/networkstatus.h"
+
+#include "feature/nodelist/networkstatus_st.h"
/* =====
* Vote scheduling
diff --git a/src/or/voting_schedule.h b/src/feature/dircommon/voting_schedule.h
index 087701408e..0e0b0cc988 100644
--- a/src/or/voting_schedule.h
+++ b/src/feature/dircommon/voting_schedule.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,7 +9,7 @@
#ifndef TOR_VOTING_SCHEDULE_H
#define TOR_VOTING_SCHEDULE_H
-#include "or.h"
+#include "core/or/or.h"
/** Scheduling information for a voting interval. */
typedef struct {
diff --git a/src/or/hibernate.c b/src/feature/hibernate/hibernate.c
index d7d259470f..d37ba5b8b1 100644
--- a/src/or/hibernate.c
+++ b/src/feature/hibernate/hibernate.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -28,19 +28,27 @@ hibernating, phase 2:
*/
#define HIBERNATE_PRIVATE
-#include "or.h"
-#include "channel.h"
-#include "channeltls.h"
-#include "config.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "connection_or.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "hibernate.h"
-#include "main.h"
-#include "router.h"
-#include "statefile.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "core/or/channeltls.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "core/or/connection_or.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/hibernate/hibernate.h"
+#include "core/mainloop/main.h"
+#include "feature/relay/router.h"
+#include "app/config/statefile.h"
+#include "lib/evloop/compat_libevent.h"
+
+#include "core/or/or_connection_st.h"
+#include "app/config/or_state_st.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
/** Are we currently awake, asleep, running out of bandwidth, or shutting
* down? */
@@ -759,13 +767,13 @@ read_bandwidth_usage(void)
"Successfully read bandwidth accounting info from state written at %s "
"for interval starting at %s. We have been active for %lu seconds in "
"this interval. At the start of the interval, we expected to use "
- "about %lu KB per second. ("U64_FORMAT" bytes read so far, "
- U64_FORMAT" bytes written so far)",
+ "about %lu KB per second. (%"PRIu64" bytes read so far, "
+ "%"PRIu64" bytes written so far)",
tbuf1, tbuf2,
(unsigned long)n_seconds_active_in_interval,
(unsigned long)(expected_bandwidth_usage*1024/60),
- U64_PRINTF_ARG(n_bytes_read_in_interval),
- U64_PRINTF_ARG(n_bytes_written_in_interval));
+ (n_bytes_read_in_interval),
+ (n_bytes_written_in_interval));
}
return 0;
@@ -797,7 +805,7 @@ hibernate_soft_limit_reached(void)
* - We have used up 95% of our bytes.
* - We have less than 500MB of bytes left.
*/
- uint64_t soft_limit = DBL_TO_U64(U64_TO_DBL(acct_max) * SOFT_LIM_PCT);
+ uint64_t soft_limit = (uint64_t) (acct_max * SOFT_LIM_PCT);
if (acct_max > SOFT_LIM_BYTES && acct_max - SOFT_LIM_BYTES > soft_limit) {
soft_limit = acct_max - SOFT_LIM_BYTES;
}
@@ -1132,9 +1140,9 @@ getinfo_helper_accounting(control_connection_t *conn,
*answer = tor_strdup(hibernate_state_to_string(hibernate_state));
tor_strlower(*answer);
} else if (!strcmp(question, "accounting/bytes")) {
- tor_asprintf(answer, U64_FORMAT" "U64_FORMAT,
- U64_PRINTF_ARG(n_bytes_read_in_interval),
- U64_PRINTF_ARG(n_bytes_written_in_interval));
+ tor_asprintf(answer, "%"PRIu64" %"PRIu64,
+ (n_bytes_read_in_interval),
+ (n_bytes_written_in_interval));
} else if (!strcmp(question, "accounting/bytes-left")) {
uint64_t limit = get_options()->AccountingMax;
if (get_options()->AccountingRule == ACCT_SUM) {
@@ -1142,28 +1150,28 @@ getinfo_helper_accounting(control_connection_t *conn,
uint64_t total_bytes = get_accounting_bytes();
if (total_bytes < limit)
total_left = limit - total_bytes;
- tor_asprintf(answer, U64_FORMAT" "U64_FORMAT,
- U64_PRINTF_ARG(total_left), U64_PRINTF_ARG(total_left));
+ tor_asprintf(answer, "%"PRIu64" %"PRIu64,
+ (total_left), (total_left));
} else if (get_options()->AccountingRule == ACCT_IN) {
uint64_t read_left = 0;
if (n_bytes_read_in_interval < limit)
read_left = limit - n_bytes_read_in_interval;
- tor_asprintf(answer, U64_FORMAT" "U64_FORMAT,
- U64_PRINTF_ARG(read_left), U64_PRINTF_ARG(limit));
+ tor_asprintf(answer, "%"PRIu64" %"PRIu64,
+ (read_left), (limit));
} else if (get_options()->AccountingRule == ACCT_OUT) {
uint64_t write_left = 0;
if (n_bytes_written_in_interval < limit)
write_left = limit - n_bytes_written_in_interval;
- tor_asprintf(answer, U64_FORMAT" "U64_FORMAT,
- U64_PRINTF_ARG(limit), U64_PRINTF_ARG(write_left));
+ tor_asprintf(answer, "%"PRIu64" %"PRIu64,
+ (limit), (write_left));
} else {
uint64_t read_left = 0, write_left = 0;
if (n_bytes_read_in_interval < limit)
read_left = limit - n_bytes_read_in_interval;
if (n_bytes_written_in_interval < limit)
write_left = limit - n_bytes_written_in_interval;
- tor_asprintf(answer, U64_FORMAT" "U64_FORMAT,
- U64_PRINTF_ARG(read_left), U64_PRINTF_ARG(write_left));
+ tor_asprintf(answer, "%"PRIu64" %"PRIu64,
+ (read_left), (write_left));
}
} else if (!strcmp(question, "accounting/interval-start")) {
*answer = tor_malloc(ISO_TIME_LEN+1);
@@ -1225,4 +1233,3 @@ hibernate_set_state_for_testing_(hibernate_state_t newstate)
hibernate_state = newstate;
}
#endif /* defined(TOR_UNIT_TESTS) */
-
diff --git a/src/or/hibernate.h b/src/feature/hibernate/hibernate.h
index 453969d052..bfd8571cd6 100644
--- a/src/or/hibernate.h
+++ b/src/feature/hibernate/hibernate.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,7 @@
#ifndef TOR_HIBERNATE_H
#define TOR_HIBERNATE_H
-#include "testsupport.h"
+#include "lib/testsupport/testsupport.h"
int accounting_parse_options(const or_options_t *options, int validate_only);
MOCK_DECL(int, accounting_is_enabled, (const or_options_t *options));
diff --git a/src/or/hs_cache.c b/src/feature/hs/hs_cache.c
index ecc845d17f..58bb10b194 100644
--- a/src/or/hs_cache.c
+++ b/src/feature/hs/hs_cache.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,17 +9,20 @@
/* For unit tests.*/
#define HS_CACHE_PRIVATE
-#include "or.h"
-#include "config.h"
-#include "crypto_util.h"
-#include "hs_ident.h"
-#include "hs_common.h"
-#include "hs_client.h"
-#include "hs_descriptor.h"
-#include "networkstatus.h"
-#include "rendcache.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/hs/hs_ident.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_client.h"
+#include "feature/hs/hs_descriptor.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/rend/rendcache.h"
-#include "hs_cache.h"
+#include "feature/hs/hs_cache.h"
+
+#include "feature/nodelist/networkstatus_st.h"
static int cached_client_descriptor_has_expired(time_t now,
const hs_cache_client_descriptor_t *cached_desc);
@@ -974,4 +977,3 @@ hs_cache_free_all(void)
cache_client_intro_state_free_void);
hs_cache_client_intro_state = NULL;
}
-
diff --git a/src/or/hs_cache.h b/src/feature/hs/hs_cache.h
index 0d0085ffdc..7cd4995d2c 100644
--- a/src/or/hs_cache.h
+++ b/src/feature/hs/hs_cache.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -11,11 +11,12 @@
#include <stdint.h>
-#include "crypto_ed25519.h"
-#include "hs_common.h"
-#include "hs_descriptor.h"
-#include "rendcommon.h"
-#include "torcert.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_descriptor.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/nodelist/torcert.h"
+
+struct ed25519_public_key_t;
/* This is the maximum time an introduction point state object can stay in the
* client cache in seconds (2 mins or 120 seconds). */
@@ -79,30 +80,32 @@ int hs_cache_lookup_as_dir(uint32_t version, const char *query,
const char **desc_out);
const hs_descriptor_t *
-hs_cache_lookup_as_client(const ed25519_public_key_t *key);
+hs_cache_lookup_as_client(const struct ed25519_public_key_t *key);
const char *
-hs_cache_lookup_encoded_as_client(const ed25519_public_key_t *key);
+hs_cache_lookup_encoded_as_client(const struct ed25519_public_key_t *key);
int hs_cache_store_as_client(const char *desc_str,
- const ed25519_public_key_t *identity_pk);
+ const struct ed25519_public_key_t *identity_pk);
void hs_cache_clean_as_client(time_t now);
void hs_cache_purge_as_client(void);
/* Client failure cache. */
-void hs_cache_client_intro_state_note(const ed25519_public_key_t *service_pk,
- const ed25519_public_key_t *auth_key,
- rend_intro_point_failure_t failure);
+void hs_cache_client_intro_state_note(
+ const struct ed25519_public_key_t *service_pk,
+ const struct ed25519_public_key_t *auth_key,
+ rend_intro_point_failure_t failure);
const hs_cache_intro_state_t *hs_cache_client_intro_state_find(
- const ed25519_public_key_t *service_pk,
- const ed25519_public_key_t *auth_key);
+ const struct ed25519_public_key_t *service_pk,
+ const struct ed25519_public_key_t *auth_key);
void hs_cache_client_intro_state_clean(time_t now);
void hs_cache_client_intro_state_purge(void);
#ifdef HS_CACHE_PRIVATE
+#include "lib/crypt_ops/crypto_ed25519.h"
/** Represents a locally cached HS descriptor on a hidden service client. */
typedef struct hs_cache_client_descriptor_t {
/* This object is indexed using the service identity public key */
- ed25519_public_key_t key;
+ struct ed25519_public_key_t key;
/* When will this entry expire? We expire cached client descriptors in the
* start of the next time period, since that's when clients need to start
@@ -125,4 +128,3 @@ lookup_v3_desc_as_client(const uint8_t *key);
#endif /* defined(HS_CACHE_PRIVATE) */
#endif /* !defined(TOR_HS_CACHE_H) */
-
diff --git a/src/or/hs_cell.c b/src/feature/hs/hs_cell.c
index 03273a44f9..c6ca6746bc 100644
--- a/src/or/hs_cell.c
+++ b/src/feature/hs/hs_cell.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -6,22 +6,23 @@
* \brief Hidden service API for cell creation and handling.
**/
-#include "or.h"
-#include "config.h"
-#include "crypto_util.h"
-#include "rendservice.h"
-#include "replaycache.h"
-#include "util.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/rend/rendservice.h"
+#include "feature/hs_common/replaycache.h"
-#include "hs_cell.h"
-#include "hs_ntor.h"
+#include "feature/hs/hs_cell.h"
+#include "core/crypto/hs_ntor.h"
+
+#include "core/or/origin_circuit_st.h"
/* Trunnel. */
-#include "ed25519_cert.h"
-#include "hs/cell_common.h"
-#include "hs/cell_establish_intro.h"
-#include "hs/cell_introduce1.h"
-#include "hs/cell_rendezvous.h"
+#include "trunnel/ed25519_cert.h"
+#include "trunnel/hs/cell_common.h"
+#include "trunnel/hs/cell_establish_intro.h"
+#include "trunnel/hs/cell_introduce1.h"
+#include "trunnel/hs/cell_rendezvous.h"
/* Compute the MAC of an INTRODUCE cell in mac_out. The encoded_cell param is
* the cell content up to the ENCRYPTED section of length encoded_cell_len.
diff --git a/src/or/hs_cell.h b/src/feature/hs/hs_cell.h
index 958dde4ffc..7b9d7e5792 100644
--- a/src/or/hs_cell.h
+++ b/src/feature/hs/hs_cell.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,8 +9,8 @@
#ifndef TOR_HS_CELL_H
#define TOR_HS_CELL_H
-#include "or.h"
-#include "hs_service.h"
+#include "core/or/or.h"
+#include "feature/hs/hs_service.h"
/* An INTRODUCE1 cell requires at least this amount of bytes (see section
* 3.2.2 of the specification). Below this value, the cell must be padded. */
diff --git a/src/or/hs_circuit.c b/src/feature/hs/hs_circuit.c
index a35d2af8ba..cd312e98be 100644
--- a/src/or/hs_circuit.c
+++ b/src/feature/hs/hs_circuit.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -7,31 +7,38 @@
#define HS_CIRCUIT_PRIVATE
-#include "or.h"
-#include "circpathbias.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "config.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "nodelist.h"
-#include "policies.h"
-#include "relay.h"
-#include "rendservice.h"
-#include "rephist.h"
-#include "router.h"
-
-#include "hs_cell.h"
-#include "hs_ident.h"
-#include "hs_ntor.h"
-#include "hs_service.h"
-#include "hs_circuit.h"
+#include "core/or/or.h"
+#include "feature/client/circpathbias.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "core/or/relay.h"
+#include "feature/rend/rendservice.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+
+#include "feature/hs/hs_cell.h"
+#include "feature/hs/hs_circuitmap.h"
+#include "feature/hs/hs_ident.h"
+#include "core/crypto/hs_ntor.h"
+#include "feature/hs/hs_service.h"
+#include "feature/hs/hs_circuit.h"
/* Trunnel. */
-#include "ed25519_cert.h"
-#include "hs/cell_common.h"
-#include "hs/cell_establish_intro.h"
+#include "trunnel/ed25519_cert.h"
+#include "trunnel/hs/cell_common.h"
+#include "trunnel/hs/cell_establish_intro.h"
+
+#include "core/or/cpath_build_state_st.h"
+#include "core/or/crypt_path_st.h"
+#include "feature/nodelist/node_st.h"
+#include "core/or/origin_circuit_st.h"
/* A circuit is about to become an e2e rendezvous circuit. Check
* <b>circ_purpose</b> and ensure that it's properly set. Return true iff
@@ -97,7 +104,8 @@ create_rend_cpath(const uint8_t *ntor_key_seed, size_t seed_len,
/* We are a v2 legacy HS client: Create and return a crypt path for the hidden
* service on the other side of the rendezvous circuit <b>circ</b>. Initialize
* the crypt path crypto using the body of the RENDEZVOUS1 cell at
- * <b>rend_cell_body</b> (which must be at least DH_KEY_LEN+DIGEST_LEN bytes).
+ * <b>rend_cell_body</b> (which must be at least DH1024_KEY_LEN+DIGEST_LEN
+ * bytes).
*/
static crypt_path_t *
create_rend_cpath_legacy(origin_circuit_t *circ, const uint8_t *rend_cell_body)
@@ -105,7 +113,7 @@ create_rend_cpath_legacy(origin_circuit_t *circ, const uint8_t *rend_cell_body)
crypt_path_t *hop = NULL;
char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN];
- /* first DH_KEY_LEN bytes are g^y from the service. Finish the dh
+ /* first DH1024_KEY_LEN bytes are g^y from the service. Finish the dh
* handshake...*/
tor_assert(circ->build_state);
tor_assert(circ->build_state->pending_final_cpath);
@@ -113,7 +121,7 @@ create_rend_cpath_legacy(origin_circuit_t *circ, const uint8_t *rend_cell_body)
tor_assert(hop->rend_dh_handshake_state);
if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN, hop->rend_dh_handshake_state,
- (char*)rend_cell_body, DH_KEY_LEN,
+ (char*)rend_cell_body, DH1024_KEY_LEN,
keys, DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) {
log_warn(LD_GENERAL, "Couldn't complete DH handshake.");
goto err;
@@ -125,7 +133,7 @@ create_rend_cpath_legacy(origin_circuit_t *circ, const uint8_t *rend_cell_body)
goto err;
/* Check whether the digest is right... */
- if (tor_memneq(keys, rend_cell_body+DH_KEY_LEN, DIGEST_LEN)) {
+ if (tor_memneq(keys, rend_cell_body+DH1024_KEY_LEN, DIGEST_LEN)) {
log_warn(LD_PROTOCOL, "Incorrect digest of key material.");
goto err;
}
@@ -1239,4 +1247,3 @@ hs_circ_cleanup(circuit_t *circ)
hs_circuitmap_remove_circuit(circ);
}
}
-
diff --git a/src/or/hs_circuit.h b/src/feature/hs/hs_circuit.h
index f69137e1d5..54f28a39ab 100644
--- a/src/or/hs_circuit.h
+++ b/src/feature/hs/hs_circuit.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,10 +9,10 @@
#ifndef TOR_HS_CIRCUIT_H
#define TOR_HS_CIRCUIT_H
-#include "or.h"
-#include "crypto_ed25519.h"
+#include "core/or/or.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
-#include "hs_service.h"
+#include "feature/hs/hs_service.h"
/* Cleanup function when the circuit is closed or/and freed. */
void hs_circ_cleanup(circuit_t *circ);
diff --git a/src/or/hs_circuitmap.c b/src/feature/hs/hs_circuitmap.c
index 112c8bdced..962a421a00 100644
--- a/src/or/hs_circuitmap.c
+++ b/src/feature/hs/hs_circuitmap.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,10 +13,13 @@
#define HS_CIRCUITMAP_PRIVATE
-#include "or.h"
-#include "config.h"
-#include "circuitlist.h"
-#include "hs_circuitmap.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "core/or/circuitlist.h"
+#include "feature/hs/hs_circuitmap.h"
+
+#include "core/or/or_circuit_st.h"
+#include "core/or/origin_circuit_st.h"
/************************** HS circuitmap code *******************************/
@@ -580,4 +583,3 @@ hs_circuitmap_free_all(void)
tor_free(the_hs_circuitmap);
}
}
-
diff --git a/src/or/hs_circuitmap.h b/src/feature/hs/hs_circuitmap.h
index 9e653480b5..c39a37c052 100644
--- a/src/or/hs_circuitmap.h
+++ b/src/feature/hs/hs_circuitmap.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -11,7 +11,7 @@
typedef HT_HEAD(hs_circuitmap_ht, circuit_t) hs_circuitmap_ht;
-typedef struct hs_token_s hs_token_t;
+typedef struct hs_token_t hs_token_t;
struct or_circuit_t;
struct origin_circuit_t;
@@ -90,7 +90,7 @@ typedef enum {
/** Represents a token used in the HS protocol. Each such token maps to a
* specific introduction or rendezvous circuit. */
-struct hs_token_s {
+struct hs_token_t {
/* Type of HS token. */
hs_token_type_t type;
@@ -110,4 +110,3 @@ hs_circuitmap_ht *get_hs_circuitmap(void);
#endif /* TOR_UNIT_TESTS */
#endif /* !defined(TOR_HS_CIRCUITMAP_H) */
-
diff --git a/src/or/hs_client.c b/src/feature/hs/hs_client.c
index b39bb2cad0..1f9218e15a 100644
--- a/src/or/hs_client.c
+++ b/src/feature/hs/hs_client.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -8,32 +8,39 @@
#define HS_CLIENT_PRIVATE
-#include "or.h"
-#include "circpathbias.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "config.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "container.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "directory.h"
-#include "hs_cache.h"
-#include "hs_cell.h"
-#include "hs_circuit.h"
-#include "hs_client.h"
-#include "hs_control.h"
-#include "hs_descriptor.h"
-#include "hs_ident.h"
-#include "hs_ntor.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "reasons.h"
-#include "rendclient.h"
-#include "router.h"
-#include "routerset.h"
+#include "core/or/or.h"
+#include "feature/client/circpathbias.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/dircache/directory.h"
+#include "feature/hs/hs_cache.h"
+#include "feature/hs/hs_cell.h"
+#include "feature/hs/hs_circuit.h"
+#include "feature/hs/hs_circuitmap.h"
+#include "feature/hs/hs_client.h"
+#include "feature/hs/hs_control.h"
+#include "feature/hs/hs_descriptor.h"
+#include "feature/hs/hs_ident.h"
+#include "core/crypto/hs_ntor.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/reasons.h"
+#include "feature/rend/rendclient.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerset.h"
+
+#include "core/or/cpath_build_state_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "core/or/entry_connection_st.h"
+#include "core/or/extend_info_st.h"
+#include "core/or/origin_circuit_st.h"
/* Return a human-readable string for the client fetch status code. */
static const char *
@@ -1614,4 +1621,3 @@ hs_client_dir_info_changed(void)
* AP_CONN_STATE_RENDDESC_WAIT state in order to fetch the descriptor. */
retry_all_socks_conn_waiting_for_desc();
}
-
diff --git a/src/or/hs_client.h b/src/feature/hs/hs_client.h
index 2523568ad1..6ee9f40c00 100644
--- a/src/or/hs_client.h
+++ b/src/feature/hs/hs_client.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,9 +9,9 @@
#ifndef TOR_HS_CLIENT_H
#define TOR_HS_CLIENT_H
-#include "crypto_ed25519.h"
-#include "hs_descriptor.h"
-#include "hs_ident.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "feature/hs/hs_descriptor.h"
+#include "feature/hs/hs_ident.h"
/* Status code of a descriptor fetch request. */
typedef enum {
diff --git a/src/or/hs_common.c b/src/feature/hs/hs_common.c
index 5354055bb0..723cfa6ea8 100644
--- a/src/or/hs_common.c
+++ b/src/feature/hs/hs_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -11,30 +11,36 @@
#define HS_COMMON_PRIVATE
-#include "or.h"
-
-#include "config.h"
-#include "circuitbuild.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "hs_cache.h"
-#include "hs_common.h"
-#include "hs_client.h"
-#include "hs_ident.h"
-#include "hs_service.h"
-#include "hs_circuitmap.h"
-#include "policies.h"
-#include "rendcommon.h"
-#include "rendservice.h"
-#include "routerset.h"
-#include "router.h"
-#include "shared_random_client.h"
-#include "dirauth/shared_random_state.h"
+#include "core/or/or.h"
+
+#include "app/config/config.h"
+#include "core/or/circuitbuild.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/hs/hs_cache.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_client.h"
+#include "feature/hs/hs_ident.h"
+#include "feature/hs/hs_service.h"
+#include "feature/hs/hs_circuitmap.h"
+#include "core/or/policies.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/rend/rendservice.h"
+#include "feature/nodelist/routerset.h"
+#include "feature/relay/router.h"
+#include "feature/hs_common/shared_random_client.h"
+#include "feature/dirauth/shared_random_state.h"
+
+#include "core/or/edge_connection_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/node_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "feature/nodelist/routerstatus_st.h"
/* Trunnel */
-#include "ed25519_cert.h"
+#include "trunnel/ed25519_cert.h"
/* Ed25519 Basepoint value. Taken from section 5 of
* https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03 */
@@ -1817,4 +1823,3 @@ hs_inc_rdv_stream_counter(origin_circuit_t *circ)
tor_assert_nonfatal_unreached();
}
}
-
diff --git a/src/or/hs_common.h b/src/feature/hs/hs_common.h
index ef7d5dca2b..888eb0a4ec 100644
--- a/src/or/hs_common.h
+++ b/src/feature/hs/hs_common.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,10 +9,15 @@
#ifndef TOR_HS_COMMON_H
#define TOR_HS_COMMON_H
-#include "or.h"
+#include "core/or/or.h"
+#include "lib/defs/x25519_sizes.h"
+
+struct curve25519_public_key_t;
+struct ed25519_public_key_t;
+struct ed25519_keypair_t;
/* Trunnel */
-#include "ed25519_cert.h"
+#include "trunnel/ed25519_cert.h"
/* Protocol version 2. Use this instead of hardcoding "2" in the code base,
* this adds a clearer semantic to the value when used. */
@@ -122,7 +127,7 @@
* bigger than the 84 bytes needed for version 3 so we need to pad up to that
* length so it is indistinguishable between versions. */
#define HS_LEGACY_RENDEZVOUS_CELL_SIZE \
- (REND_COOKIE_LEN + DH_KEY_LEN + DIGEST_LEN)
+ (REND_COOKIE_LEN + DH1024_KEY_LEN + DIGEST_LEN)
/* Type of authentication key used by an introduction point. */
typedef enum {
@@ -167,20 +172,20 @@ int hs_check_service_private_dir(const char *username, const char *path,
int hs_get_service_max_rend_failures(void);
char *hs_path_from_filename(const char *directory, const char *filename);
-void hs_build_address(const ed25519_public_key_t *key, uint8_t version,
+void hs_build_address(const struct ed25519_public_key_t *key, uint8_t version,
char *addr_out);
int hs_address_is_valid(const char *address);
-int hs_parse_address(const char *address, ed25519_public_key_t *key_out,
+int hs_parse_address(const char *address, struct ed25519_public_key_t *key_out,
uint8_t *checksum_out, uint8_t *version_out);
-void hs_build_blinded_pubkey(const ed25519_public_key_t *pubkey,
+void hs_build_blinded_pubkey(const struct ed25519_public_key_t *pubkey,
const uint8_t *secret, size_t secret_len,
uint64_t time_period_num,
- ed25519_public_key_t *pubkey_out);
-void hs_build_blinded_keypair(const ed25519_keypair_t *kp,
+ struct ed25519_public_key_t *pubkey_out);
+void hs_build_blinded_keypair(const struct ed25519_keypair_t *kp,
const uint8_t *secret, size_t secret_len,
uint64_t time_period_num,
- ed25519_keypair_t *kp_out);
+ struct ed25519_keypair_t *kp_out);
int hs_service_requires_uptime_circ(const smartlist_t *ports);
void rend_data_free_(rend_data_t *data);
@@ -203,8 +208,8 @@ const uint8_t *rend_data_get_pk_digest(const rend_data_t *rend_data,
routerstatus_t *pick_hsdir(const char *desc_id, const char *desc_id_base32);
-void hs_get_subcredential(const ed25519_public_key_t *identity_pk,
- const ed25519_public_key_t *blinded_pk,
+void hs_get_subcredential(const struct ed25519_public_key_t *identity_pk,
+ const struct ed25519_public_key_t *blinded_pk,
uint8_t *subcred_out);
uint64_t hs_get_previous_time_period_num(time_t now);
@@ -222,18 +227,18 @@ uint8_t *hs_get_current_srv(uint64_t time_period_num,
uint8_t *hs_get_previous_srv(uint64_t time_period_num,
const networkstatus_t *ns);
-void hs_build_hsdir_index(const ed25519_public_key_t *identity_pk,
+void hs_build_hsdir_index(const struct ed25519_public_key_t *identity_pk,
const uint8_t *srv, uint64_t period_num,
uint8_t *hsdir_index_out);
void hs_build_hs_index(uint64_t replica,
- const ed25519_public_key_t *blinded_pk,
+ const struct ed25519_public_key_t *blinded_pk,
uint64_t period_num, uint8_t *hs_index_out);
int32_t hs_get_hsdir_n_replicas(void);
int32_t hs_get_hsdir_spread_fetch(void);
int32_t hs_get_hsdir_spread_store(void);
-void hs_get_responsible_hsdirs(const ed25519_public_key_t *blinded_pk,
+void hs_get_responsible_hsdirs(const struct ed25519_public_key_t *blinded_pk,
uint64_t time_period_num,
int use_second_hsdir_index,
int for_fetching, smartlist_t *responsible_dirs);
@@ -254,8 +259,8 @@ void hs_inc_rdv_stream_counter(origin_circuit_t *circ);
void hs_dec_rdv_stream_counter(origin_circuit_t *circ);
extend_info_t *hs_get_extend_info_from_lspecs(const smartlist_t *lspecs,
- const curve25519_public_key_t *onion_key,
- int direct_conn);
+ const struct curve25519_public_key_t *onion_key,
+ int direct_conn);
#ifdef HS_COMMON_PRIVATE
@@ -281,4 +286,3 @@ STATIC uint8_t *get_second_cached_disaster_srv(void);
#endif /* defined(HS_COMMON_PRIVATE) */
#endif /* !defined(TOR_HS_COMMON_H) */
-
diff --git a/src/or/hs_config.c b/src/feature/hs/hs_config.c
index be223503a0..2c25a168a2 100644
--- a/src/or/hs_config.c
+++ b/src/feature/hs/hs_config.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -25,10 +25,12 @@
#define HS_CONFIG_PRIVATE
-#include "hs_common.h"
-#include "hs_config.h"
-#include "hs_service.h"
-#include "rendservice.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_config.h"
+#include "feature/hs/hs_service.h"
+#include "feature/rend/rendservice.h"
+#include "lib/encoding/confline.h"
+#include "app/config/or_options_st.h"
/* Using the given list of services, stage them into our global state. Every
* service version are handled. This function can remove entries in the given
@@ -587,4 +589,3 @@ hs_config_service_all(const or_options_t *options, int validate_only)
/* Tor main should call the free all function on error. */
return ret;
}
-
diff --git a/src/or/hs_config.h b/src/feature/hs/hs_config.h
index 6cd7aed460..96eb19ee70 100644
--- a/src/or/hs_config.h
+++ b/src/feature/hs/hs_config.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,7 +9,7 @@
#ifndef TOR_HS_CONFIG_H
#define TOR_HS_CONFIG_H
-#include "or.h"
+#include "core/or/or.h"
/* Max value for HiddenServiceMaxStreams */
#define HS_CONFIG_MAX_STREAMS_PER_RDV_CIRCUIT 65535
diff --git a/src/or/hs_control.c b/src/feature/hs/hs_control.c
index 6b9b95c6d8..a21788ecd7 100644
--- a/src/or/hs_control.c
+++ b/src/feature/hs/hs_control.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -6,14 +6,18 @@
* \brief Contains control port event related code.
**/
-#include "or.h"
-#include "control.h"
-#include "crypto_util.h"
-#include "hs_common.h"
-#include "hs_control.h"
-#include "hs_descriptor.h"
-#include "hs_service.h"
-#include "nodelist.h"
+#include "core/or/or.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_control.h"
+#include "feature/hs/hs_descriptor.h"
+#include "feature/hs/hs_service.h"
+#include "feature/nodelist/nodelist.h"
+
+#include "feature/nodelist/node_st.h"
+#include "feature/nodelist/routerstatus_st.h"
/* Send on the control port the "HS_DESC REQUESTED [...]" event.
*
@@ -255,4 +259,3 @@ hs_control_hspost_command(const char *body, const char *onion_address,
smartlist_free(hsdirs);
return ret;
}
-
diff --git a/src/or/hs_control.h b/src/feature/hs/hs_control.h
index 95c46e655e..63e3fe13d6 100644
--- a/src/or/hs_control.h
+++ b/src/feature/hs/hs_control.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,7 +9,7 @@
#ifndef TOR_HS_CONTROL_H
#define TOR_HS_CONTROL_H
-#include "hs_ident.h"
+#include "feature/hs/hs_ident.h"
/* Event "HS_DESC REQUESTED [...]" */
void hs_control_desc_event_requested(const ed25519_public_key_t *onion_pk,
diff --git a/src/or/hs_descriptor.c b/src/feature/hs/hs_descriptor.c
index 7ffa885ca8..3928000164 100644
--- a/src/or/hs_descriptor.c
+++ b/src/feature/hs/hs_descriptor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -55,17 +55,21 @@
/* For unit tests.*/
#define HS_DESCRIPTOR_PRIVATE
-#include "or.h"
-#include "ed25519_cert.h" /* Trunnel interface. */
-#include "hs_descriptor.h"
-#include "circuitbuild.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "parsecommon.h"
-#include "rendcache.h"
-#include "hs_cache.h"
-#include "hs_config.h"
-#include "torcert.h" /* tor_cert_encode_ed22519() */
+#include "core/or/or.h"
+#include "trunnel/ed25519_cert.h" /* Trunnel interface. */
+#include "feature/hs/hs_descriptor.h"
+#include "core/or/circuitbuild.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/nodelist/parsecommon.h"
+#include "feature/rend/rendcache.h"
+#include "feature/hs/hs_cache.h"
+#include "feature/hs/hs_config.h"
+#include "feature/nodelist/torcert.h" /* tor_cert_encode_ed22519() */
+#include "lib/memarea/memarea.h"
+#include "lib/crypt_ops/crypto_format.h"
+
+#include "core/or/extend_info_st.h"
/* Constant string value used for the descriptor format. */
#define str_hs_desc "hs-descriptor"
@@ -2605,4 +2609,3 @@ hs_desc_lspec_to_trunnel(const hs_desc_link_specifier_t *spec)
return ls;
}
-
diff --git a/src/or/hs_descriptor.h b/src/feature/hs/hs_descriptor.h
index 8195c6efbc..bfdf7559c6 100644
--- a/src/or/hs_descriptor.h
+++ b/src/feature/hs/hs_descriptor.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -11,13 +11,9 @@
#include <stdint.h>
-#include "or.h"
-#include "address.h"
-#include "container.h"
-#include "crypto.h"
-#include "crypto_ed25519.h"
-#include "ed25519_cert.h" /* needed for trunnel */
-#include "torcert.h"
+#include "core/or/or.h"
+#include "trunnel/ed25519_cert.h" /* needed for trunnel */
+#include "feature/nodelist/torcert.h"
/* Trunnel */
struct link_specifier_t;
@@ -282,4 +278,3 @@ MOCK_DECL(STATIC size_t, decrypt_desc_layer,(const hs_descriptor_t *desc,
#endif /* defined(HS_DESCRIPTOR_PRIVATE) */
#endif /* !defined(TOR_HS_DESCRIPTOR_H) */
-
diff --git a/src/or/hs_ident.c b/src/feature/hs/hs_ident.c
index 3603e329d4..c6ef8c2ce3 100644
--- a/src/or/hs_ident.c
+++ b/src/feature/hs/hs_ident.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -7,8 +7,8 @@
* subsytem.
**/
-#include "crypto_util.h"
-#include "hs_ident.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/hs/hs_ident.h"
/* Return a newly allocated circuit identifier. The given public key is copied
* identity_pk into the identifier. */
diff --git a/src/or/hs_ident.h b/src/feature/hs/hs_ident.h
index 8f9da30c35..92d15b0523 100644
--- a/src/or/hs_ident.h
+++ b/src/feature/hs/hs_ident.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -21,9 +21,9 @@
#ifndef TOR_HS_IDENT_H
#define TOR_HS_IDENT_H
-#include "crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
-#include "hs_common.h"
+#include "feature/hs/hs_common.h"
/* Length of the rendezvous cookie that is used to connect circuits at the
* rendezvous point. */
diff --git a/src/or/hs_intropoint.c b/src/feature/hs/hs_intropoint.c
index 3274e8e9c0..42092e22b1 100644
--- a/src/or/hs_intropoint.c
+++ b/src/feature/hs/hs_intropoint.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -8,24 +8,27 @@
#define HS_INTROPOINT_PRIVATE
-#include "or.h"
-#include "config.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "relay.h"
-#include "rendmid.h"
-#include "rephist.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "core/or/relay.h"
+#include "feature/rend/rendmid.h"
+#include "feature/stats/rephist.h"
+#include "lib/crypt_ops/crypto_format.h"
/* Trunnel */
-#include "ed25519_cert.h"
-#include "hs/cell_common.h"
-#include "hs/cell_establish_intro.h"
-#include "hs/cell_introduce1.h"
+#include "trunnel/ed25519_cert.h"
+#include "trunnel/hs/cell_common.h"
+#include "trunnel/hs/cell_establish_intro.h"
+#include "trunnel/hs/cell_introduce1.h"
-#include "hs_circuitmap.h"
-#include "hs_descriptor.h"
-#include "hs_intropoint.h"
-#include "hs_common.h"
+#include "feature/hs/hs_circuitmap.h"
+#include "feature/hs/hs_descriptor.h"
+#include "feature/hs/hs_intropoint.h"
+#include "feature/hs/hs_common.h"
+
+#include "core/or/or_circuit_st.h"
/** Extract the authentication key from an ESTABLISH_INTRO or INTRODUCE1 using
* the given <b>cell_type</b> from <b>cell</b> and place it in
@@ -609,4 +612,3 @@ hs_intropoint_clear(hs_intropoint_t *ip)
smartlist_free(ip->link_specifiers);
memset(ip, 0, sizeof(hs_intropoint_t));
}
-
diff --git a/src/or/hs_intropoint.h b/src/feature/hs/hs_intropoint.h
index 749d1530e1..562836fb07 100644
--- a/src/or/hs_intropoint.h
+++ b/src/feature/hs/hs_intropoint.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,8 +9,8 @@
#ifndef TOR_HS_INTRO_H
#define TOR_HS_INTRO_H
-#include "crypto_curve25519.h"
-#include "torcert.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "feature/nodelist/torcert.h"
/* Authentication key type in an ESTABLISH_INTRO cell. */
typedef enum {
@@ -55,8 +55,8 @@ void hs_intropoint_clear(hs_intropoint_t *ip);
#ifdef HS_INTROPOINT_PRIVATE
-#include "hs/cell_establish_intro.h"
-#include "hs/cell_introduce1.h"
+#include "trunnel/hs/cell_establish_intro.h"
+#include "trunnel/hs/cell_introduce1.h"
STATIC int
verify_establish_intro_cell(const trn_cell_establish_intro_t *out,
diff --git a/src/or/hs_service.c b/src/feature/hs/hs_service.c
index f1f26954ae..8b4de21387 100644
--- a/src/or/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -8,41 +8,60 @@
#define HS_SERVICE_PRIVATE
-#include "or.h"
-#include "circpathbias.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "config.h"
-#include "connection.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "directory.h"
-#include "main.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "relay.h"
-#include "rendservice.h"
-#include "router.h"
-#include "routerkeys.h"
-#include "routerlist.h"
-#include "shared_random_client.h"
-#include "statefile.h"
-
-#include "hs_circuit.h"
-#include "hs_common.h"
-#include "hs_config.h"
-#include "hs_control.h"
-#include "hs_descriptor.h"
-#include "hs_ident.h"
-#include "hs_intropoint.h"
-#include "hs_service.h"
-#include "hs_stats.h"
+#include "core/or/or.h"
+#include "feature/client/circpathbias.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/dircache/directory.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/relay.h"
+#include "feature/rend/rendservice.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routerkeys.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/hs_common/shared_random_client.h"
+#include "app/config/statefile.h"
+
+#include "feature/hs/hs_circuit.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_config.h"
+#include "feature/hs/hs_control.h"
+#include "feature/hs/hs_descriptor.h"
+#include "feature/hs/hs_ident.h"
+#include "feature/hs/hs_intropoint.h"
+#include "feature/hs/hs_service.h"
+#include "feature/hs/hs_stats.h"
+
+#include "feature/dircommon/dir_connection_st.h"
+#include "core/or/edge_connection_st.h"
+#include "core/or/extend_info_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/node_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "app/config/or_state_st.h"
+#include "feature/nodelist/routerstatus_st.h"
+
+#include "lib/encoding/confline.h"
+#include "lib/crypt_ops/crypto_format.h"
/* Trunnel */
-#include "ed25519_cert.h"
-#include "hs/cell_common.h"
-#include "hs/cell_establish_intro.h"
+#include "trunnel/ed25519_cert.h"
+#include "trunnel/hs/cell_common.h"
+#include "trunnel/hs/cell_establish_intro.h"
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
/* Helper macro. Iterate over every service in the global map. The var is the
* name of the service pointer. */
@@ -3623,4 +3642,3 @@ get_first_service(void)
}
#endif /* defined(TOR_UNIT_TESTS) */
-
diff --git a/src/or/hs_service.h b/src/feature/hs/hs_service.h
index 5494b6f5fa..22bfcacc26 100644
--- a/src/or/hs_service.h
+++ b/src/feature/hs/hs_service.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,17 +9,17 @@
#ifndef TOR_HS_SERVICE_H
#define TOR_HS_SERVICE_H
-#include "crypto_curve25519.h"
-#include "crypto_ed25519.h"
-#include "replaycache.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "feature/hs_common/replaycache.h"
-#include "hs_common.h"
-#include "hs_descriptor.h"
-#include "hs_ident.h"
-#include "hs_intropoint.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"
/* Trunnel */
-#include "hs/cell_establish_intro.h"
+#include "trunnel/hs/cell_establish_intro.h"
/* When loading and configuring a service, this is the default version it will
* be configured for as it is possible that no HiddenServiceVersion is
diff --git a/src/or/hs_stats.c b/src/feature/hs/hs_stats.c
index 1e2a96945b..b109a37cc1 100644
--- a/src/or/hs_stats.c
+++ b/src/feature/hs/hs_stats.c
@@ -6,9 +6,9 @@
* \brief Keeps stats about the activity of our onion service(s).
**/
-#include "or.h"
-#include "hs_stats.h"
-#include "hs_service.h"
+#include "core/or/or.h"
+#include "feature/hs/hs_stats.h"
+#include "feature/hs/hs_service.h"
/** Number of v3 INTRODUCE2 cells received */
static uint32_t n_introduce2_v3 = 0;
diff --git a/src/or/hs_stats.h b/src/feature/hs/hs_stats.h
index a946ad75e5..a946ad75e5 100644
--- a/src/or/hs_stats.h
+++ b/src/feature/hs/hs_stats.h
diff --git a/src/feature/hs/hsdir_index_st.h b/src/feature/hs/hsdir_index_st.h
new file mode 100644
index 0000000000..de5cc9bd16
--- /dev/null
+++ b/src/feature/hs/hsdir_index_st.h
@@ -0,0 +1,24 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef HSDIR_INDEX_ST_H
+#define HSDIR_INDEX_ST_H
+
+/* Hidden service directory index used in a node_t which is set once we set
+ * the consensus. */
+struct hsdir_index_t {
+ /* HSDir index to use when fetching a descriptor. */
+ uint8_t fetch[DIGEST256_LEN];
+
+ /* HSDir index used by services to store their first and second
+ * descriptor. The first descriptor is chronologically older than the second
+ * one and uses older TP and SRV values. */
+ uint8_t store_first[DIGEST256_LEN];
+ uint8_t store_second[DIGEST256_LEN];
+};
+
+#endif
+
diff --git a/src/or/replaycache.c b/src/feature/hs_common/replaycache.c
index a9a6709937..1d3f20e819 100644
--- a/src/or/replaycache.c
+++ b/src/feature/hs_common/replaycache.c
@@ -1,4 +1,4 @@
- /* Copyright (c) 2012-2017, The Tor Project, Inc. */
+ /* Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -21,8 +21,8 @@
#define REPLAYCACHE_PRIVATE
-#include "or.h"
-#include "replaycache.h"
+#include "core/or/or.h"
+#include "feature/hs_common/replaycache.h"
/** Free the replaycache r and all of its entries.
*/
diff --git a/src/or/replaycache.h b/src/feature/hs_common/replaycache.h
index 81a8d907fd..3118a88a1a 100644
--- a/src/or/replaycache.h
+++ b/src/feature/hs_common/replaycache.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,11 +9,11 @@
#ifndef TOR_REPLAYCACHE_H
#define TOR_REPLAYCACHE_H
-typedef struct replaycache_s replaycache_t;
+typedef struct replaycache_t replaycache_t;
#ifdef REPLAYCACHE_PRIVATE
-struct replaycache_s {
+struct replaycache_t {
/* Scrub interval */
time_t scrub_interval;
/* Last scrubbed */
@@ -65,4 +65,3 @@ int replaycache_add_test_and_elapsed(
void replaycache_scrub_if_needed(replaycache_t *r);
#endif /* !defined(TOR_REPLAYCACHE_H) */
-
diff --git a/src/or/shared_random_client.c b/src/feature/hs_common/shared_random_client.c
index 3aef83cef4..329f053d3b 100644
--- a/src/or/shared_random_client.c
+++ b/src/feature/hs_common/shared_random_client.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,13 +9,14 @@
**/
#define SHARED_RANDOM_CLIENT_PRIVATE
-#include "shared_random_client.h"
+#include "feature/hs_common/shared_random_client.h"
-#include "config.h"
-#include "voting_schedule.h"
-#include "networkstatus.h"
-#include "util.h"
-#include "util_format.h"
+#include "app/config/config.h"
+#include "feature/dircommon/voting_schedule.h"
+#include "feature/nodelist/networkstatus.h"
+#include "lib/encoding/binascii.h"
+
+#include "feature/nodelist/networkstatus_st.h"
/* Convert a given srv object to a string for the control port. This doesn't
* fail and the srv object MUST be valid. */
diff --git a/src/or/shared_random_client.h b/src/feature/hs_common/shared_random_client.h
index 89c608d45f..497a015c18 100644
--- a/src/or/shared_random_client.h
+++ b/src/feature/hs_common/shared_random_client.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,7 +10,7 @@
#define TOR_SHARED_RANDOM_CLIENT_H
/* Dirauth module. */
-#include "dirauth/shared_random.h"
+#include "feature/dirauth/shared_random.h"
/* Helper functions. */
void sr_srv_encode(char *dst, size_t dst_len, const sr_srv_t *srv);
diff --git a/src/feature/nodelist/authority_cert_st.h b/src/feature/nodelist/authority_cert_st.h
new file mode 100644
index 0000000000..c2846548c4
--- /dev/null
+++ b/src/feature/nodelist/authority_cert_st.h
@@ -0,0 +1,32 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef AUTHORITY_CERT_ST_H
+#define AUTHORITY_CERT_ST_H
+
+#include "feature/nodelist/signed_descriptor_st.h"
+
+/** Certificate for v3 directory protocol: binds long-term authority identity
+ * keys to medium-term authority signing keys. */
+struct authority_cert_t {
+ /** Information relating to caching this cert on disk and looking it up. */
+ signed_descriptor_t cache_info;
+ /** This authority's long-term authority identity key. */
+ crypto_pk_t *identity_key;
+ /** This authority's medium-term signing key. */
+ crypto_pk_t *signing_key;
+ /** The digest of <b>signing_key</b> */
+ 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 directory port. */
+ uint16_t dir_port;
+};
+
+#endif
+
diff --git a/src/feature/nodelist/desc_store_st.h b/src/feature/nodelist/desc_store_st.h
new file mode 100644
index 0000000000..168a83b230
--- /dev/null
+++ b/src/feature/nodelist/desc_store_st.h
@@ -0,0 +1,39 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef DESC_STORE_ST_H
+#define DESC_STORE_ST_H
+
+/** Allowable types of desc_store_t. */
+typedef enum store_type_t {
+ ROUTER_STORE = 0,
+ EXTRAINFO_STORE = 1
+} store_type_t;
+
+/** A 'store' is a set of descriptors saved on disk, with accompanying
+ * journal, mmaped as needed, rebuilt as needed. */
+struct desc_store_t {
+ /** Filename (within DataDir) for the store. We append .tmp to this
+ * filename for a temporary file when rebuilding the store, and .new to this
+ * filename for the journal. */
+ const char *fname_base;
+ /** Human-readable description of what this store contains. */
+ const char *description;
+
+ tor_mmap_t *mmap; /**< A mmap for the main file in the store. */
+
+ store_type_t type; /**< What's stored in this store? */
+
+ /** The size of the router log, in bytes. */
+ size_t journal_len;
+ /** The size of the router store, in bytes. */
+ size_t store_len;
+ /** Total bytes dropped since last rebuild: this is space currently
+ * used in the cache and the journal that could be freed by a rebuild. */
+ size_t bytes_dropped;
+};
+
+#endif
diff --git a/src/feature/nodelist/document_signature_st.h b/src/feature/nodelist/document_signature_st.h
new file mode 100644
index 0000000000..0291e099bf
--- /dev/null
+++ b/src/feature/nodelist/document_signature_st.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef DOCUMENT_SIGNATURE_ST_H
+#define DOCUMENT_SIGNATURE_ST_H
+
+/** A signature of some document by an authority. */
+struct document_signature_t {
+ /** Declared SHA-1 digest of this voter's identity key */
+ char identity_digest[DIGEST_LEN];
+ /** Declared SHA-1 digest of signing key used by this voter. */
+ char signing_key_digest[DIGEST_LEN];
+ /** Algorithm used to compute the digest of the document. */
+ digest_algorithm_t alg;
+ /** Signature of the signed thing. */
+ char *signature;
+ /** Length of <b>signature</b> */
+ int signature_len;
+ unsigned int bad_signature : 1; /**< Set to true if we've tried to verify
+ * the sig, and we know it's bad. */
+ unsigned int good_signature : 1; /**< Set to true if we've verified the sig
+ * as good. */
+};
+
+#endif
+
diff --git a/src/feature/nodelist/extrainfo_st.h b/src/feature/nodelist/extrainfo_st.h
new file mode 100644
index 0000000000..f5d977e751
--- /dev/null
+++ b/src/feature/nodelist/extrainfo_st.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef EXTRAINFO_ST_H
+#define EXTRAINFO_ST_H
+
+#include "feature/nodelist/signed_descriptor_st.h"
+
+/** Information needed to keep and cache a signed extra-info document. */
+struct extrainfo_t {
+ signed_descriptor_t cache_info;
+ /** SHA256 digest of this document */
+ uint8_t digest256[DIGEST256_LEN];
+ /** The router's nickname. */
+ char nickname[MAX_NICKNAME_LEN+1];
+ /** True iff we found the right key for this extra-info, verified the
+ * signature, and found it to be bad. */
+ unsigned int bad_sig : 1;
+ /** If present, we didn't have the right key to verify this extra-info,
+ * so this is a copy of the signature in the document. */
+ char *pending_sig;
+ /** Length of pending_sig. */
+ size_t pending_sig_len;
+};
+
+#endif
+
diff --git a/src/or/microdesc.c b/src/feature/nodelist/microdesc.c
index b4a934e095..4d6285d6cf 100644
--- a/src/or/microdesc.c
+++ b/src/feature/nodelist/microdesc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2017, The Tor Project, Inc. */
+/* Copyright (c) 2009-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -8,19 +8,34 @@
* less-frequently-changing router information.
*/
-#include "or.h"
-#include "circuitbuild.h"
-#include "config.h"
-#include "directory.h"
-#include "dirserv.h"
-#include "entrynodes.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "policies.h"
-#include "router.h"
-#include "routerlist.h"
-#include "routerparse.h"
+#include "core/or/or.h"
+
+#include "lib/fdio/fdio.h"
+
+#include "core/or/circuitbuild.h"
+#include "app/config/config.h"
+#include "feature/dircache/directory.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/client/entrynodes.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+
+#include "feature/nodelist/microdesc_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/node_st.h"
+#include "feature/nodelist/routerstatus_st.h"
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
/** A data structure to hold a bunch of cached microdescriptors. There are
* two active files in the cache: a "cache file" that we mmap, and a "journal
@@ -189,7 +204,7 @@ dump_microdescriptor(int fd, microdesc_t *md, size_t *annotation_len_out)
char annotation[ISO_TIME_LEN+32];
format_iso_time(buf, md->last_listed);
tor_snprintf(annotation, sizeof(annotation), "@last-listed %s\n", buf);
- if (write_all(fd, annotation, strlen(annotation), 0) < 0) {
+ if (write_all_to_fd(fd, annotation, strlen(annotation)) < 0) {
log_warn(LD_DIR,
"Couldn't write microdescriptor annotation: %s",
strerror(errno));
@@ -202,7 +217,7 @@ dump_microdescriptor(int fd, microdesc_t *md, size_t *annotation_len_out)
}
md->off = tor_fd_getpos(fd);
- written = write_all(fd, md->body, md->bodylen, 0);
+ written = write_all_to_fd(fd, md->body, md->bodylen);
if (written != (ssize_t)md->bodylen) {
written = written < 0 ? 0 : written;
log_warn(LD_DIR,
@@ -706,9 +721,9 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
off_real = tor_fd_getpos(fd);
if (off_real != off) {
log_warn(LD_BUG, "Discontinuity in position in microdescriptor cache."
- "By my count, I'm at "I64_FORMAT
- ", but I should be at "I64_FORMAT,
- I64_PRINTF_ARG(off), I64_PRINTF_ARG(off_real));
+ "By my count, I'm at %"PRId64
+ ", but I should be at %"PRId64,
+ (off), (off_real));
if (off_real >= 0)
off = off_real;
}
@@ -1042,4 +1057,3 @@ usable_consensus_flavor,(void))
return FLAV_NS;
}
}
-
diff --git a/src/or/microdesc.h b/src/feature/nodelist/microdesc.h
index 83a90bd8ff..f11b841cf1 100644
--- a/src/or/microdesc.h
+++ b/src/feature/nodelist/microdesc.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/microdesc_st.h b/src/feature/nodelist/microdesc_st.h
new file mode 100644
index 0000000000..e9dc3e0174
--- /dev/null
+++ b/src/feature/nodelist/microdesc_st.h
@@ -0,0 +1,74 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef MICRODESC_ST_H
+#define MICRODESC_ST_H
+
+struct curve25519_public_key_t;
+struct ed25519_public_key_t;
+struct short_policy_t;
+
+/** A microdescriptor is the smallest amount of information needed to build a
+ * circuit through a router. They are generated by the directory authorities,
+ * using information from the uploaded routerinfo documents. They are not
+ * self-signed, but are rather authenticated by having their hash in a signed
+ * networkstatus document. */
+struct microdesc_t {
+ /** Hashtable node, used to look up the microdesc by its digest. */
+ HT_ENTRY(microdesc_t) node;
+
+ /* Cache information */
+
+ /** When was this microdescriptor last listed in a consensus document?
+ * Once a microdesc has been unlisted long enough, we can drop it.
+ */
+ time_t last_listed;
+ /** Where is this microdescriptor currently stored? */
+ saved_location_bitfield_t saved_location : 3;
+ /** If true, do not attempt to cache this microdescriptor on disk. */
+ unsigned int no_save : 1;
+ /** If true, this microdesc has an entry in the microdesc_map */
+ unsigned int held_in_map : 1;
+ /** Reference count: how many node_ts have a reference to this microdesc? */
+ unsigned int held_by_nodes;
+
+ /** If saved_location == SAVED_IN_CACHE, this field holds the offset of the
+ * microdescriptor in the cache. */
+ off_t off;
+
+ /* The string containing the microdesc. */
+
+ /** A pointer to the encoded body of the microdescriptor. If the
+ * saved_location is SAVED_IN_CACHE, then the body is a pointer into an
+ * mmap'd region. Otherwise, it is a malloc'd string. The string might not
+ * be NUL-terminated; take the length from <b>bodylen</b>. */
+ char *body;
+ /** The length of the microdescriptor in <b>body</b>. */
+ size_t bodylen;
+ /** A SHA256-digest of the microdescriptor. */
+ char digest[DIGEST256_LEN];
+
+ /* Fields in the microdescriptor. */
+
+ /** As routerinfo_t.onion_pkey */
+ crypto_pk_t *onion_pkey;
+ /** As routerinfo_t.onion_curve25519_pkey */
+ struct curve25519_public_key_t *onion_curve25519_pkey;
+ /** Ed25519 identity key, if included. */
+ struct ed25519_public_key_t *ed25519_identity_pkey;
+ /** As routerinfo_t.ipv6_addr */
+ tor_addr_t ipv6_addr;
+ /** As routerinfo_t.ipv6_orport */
+ uint16_t ipv6_orport;
+ /** As routerinfo_t.family */
+ smartlist_t *family;
+ /** IPv4 exit policy summary */
+ struct short_policy_t *exit_policy;
+ /** IPv6 exit policy summary */
+ struct short_policy_t *ipv6_exit_policy;
+};
+
+#endif
diff --git a/src/or/networkstatus.c b/src/feature/nodelist/networkstatus.c
index 998eaf74e6..e9d36cbdcb 100644
--- a/src/or/networkstatus.c
+++ b/src/feature/nodelist/networkstatus.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -37,42 +37,60 @@
*/
#define NETWORKSTATUS_PRIVATE
-#include "or.h"
-#include "bridges.h"
-#include "channel.h"
-#include "circuitmux.h"
-#include "circuitmux_ewma.h"
-#include "circuitstats.h"
-#include "config.h"
-#include "connection.h"
-#include "connection_or.h"
-#include "consdiffmgr.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "directory.h"
-#include "dirserv.h"
-#include "dos.h"
-#include "entrynodes.h"
-#include "hibernate.h"
-#include "main.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "protover.h"
-#include "relay.h"
-#include "router.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "scheduler.h"
-#include "transports.h"
-#include "torcert.h"
-#include "channelpadding.h"
-#include "voting_schedule.h"
-
-#include "dirauth/dirvote.h"
-#include "dirauth/mode.h"
-#include "dirauth/shared_random.h"
+#include "core/or/or.h"
+#include "feature/client/bridges.h"
+#include "core/or/channel.h"
+#include "core/or/circuitmux.h"
+#include "core/or/circuitmux_ewma.h"
+#include "core/or/circuitstats.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "core/or/connection_or.h"
+#include "feature/dircache/consdiffmgr.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/dircache/directory.h"
+#include "feature/dircache/dirserv.h"
+#include "core/or/dos.h"
+#include "feature/client/entrynodes.h"
+#include "feature/hibernate/hibernate.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/protover.h"
+#include "core/or/relay.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "core/or/scheduler.h"
+#include "feature/client/transports.h"
+#include "feature/nodelist/torcert.h"
+#include "core/or/channelpadding.h"
+#include "feature/dircommon/voting_schedule.h"
+
+#include "feature/dirauth/dirvote.h"
+#include "feature/dirauth/mode.h"
+#include "feature/dirauth/shared_random.h"
+
+#include "feature/nodelist/authority_cert_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "feature/dirclient/dir_server_st.h"
+#include "feature/nodelist/document_signature_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/networkstatus_voter_info_st.h"
+#include "feature/dirauth/ns_detached_signatures_st.h"
+#include "feature/nodelist/node_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerlist_st.h"
+#include "feature/dirauth/vote_microdesc_hash_st.h"
+#include "feature/nodelist/vote_routerstatus_st.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
/** Most recently received and validated v3 "ns"-flavored consensus network
* status. */
@@ -593,8 +611,11 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus,
char *tmp = smartlist_join_strings(list_good, " ", 0, NULL);
smartlist_add_asprintf(sl,
"A consensus needs %d good signatures from recognized "
- "authorities for us to accept it. This one has %d (%s).",
- n_required, n_good, tmp);
+ "authorities for us to accept it. "
+ "This %s one has %d (%s).",
+ n_required,
+ networkstatus_get_flavor_name(consensus->flavor),
+ n_good, tmp);
tor_free(tmp);
if (n_no_signature) {
tmp = smartlist_join_strings(list_no_signature, " ", 0, NULL);
@@ -2703,4 +2724,3 @@ networkstatus_free_all(void)
tor_free(waiting->body);
}
}
-
diff --git a/src/or/networkstatus.h b/src/feature/nodelist/networkstatus.h
index 94f85c3c29..cc6badf0b2 100644
--- a/src/or/networkstatus.h
+++ b/src/feature/nodelist/networkstatus.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,7 @@
#ifndef TOR_NETWORKSTATUS_H
#define TOR_NETWORKSTATUS_H
-#include "testsupport.h"
+#include "lib/testsupport/testsupport.h"
void networkstatus_reset_warnings(void);
void networkstatus_reset_download_failures(void);
diff --git a/src/feature/nodelist/networkstatus_sr_info_st.h b/src/feature/nodelist/networkstatus_sr_info_st.h
new file mode 100644
index 0000000000..6c937a75f5
--- /dev/null
+++ b/src/feature/nodelist/networkstatus_sr_info_st.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef NETWORKSTATUS_SR_INFO_ST_H
+#define NETWORKSTATUS_SR_INFO_ST_H
+
+struct networkstatus_sr_info_t {
+ /* Indicate if the dirauth partitipates in the SR protocol with its vote.
+ * This is tied to the SR flag in the vote. */
+ unsigned int participate:1;
+ /* Both vote and consensus: Current and previous SRV. If list is empty,
+ * this means none were found in either the consensus or vote. */
+ struct sr_srv_t *previous_srv;
+ struct sr_srv_t *current_srv;
+ /* Vote only: List of commitments. */
+ smartlist_t *commits;
+};
+
+#endif
+
diff --git a/src/feature/nodelist/networkstatus_st.h b/src/feature/nodelist/networkstatus_st.h
new file mode 100644
index 0000000000..46b0f53c0b
--- /dev/null
+++ b/src/feature/nodelist/networkstatus_st.h
@@ -0,0 +1,101 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef NETWORKSTATUS_ST_H
+#define NETWORKSTATUS_ST_H
+
+#include "feature/nodelist/networkstatus_sr_info_st.h"
+
+/** Enumerates the possible seriousness values of a networkstatus document. */
+typedef enum networkstatus_type_t {
+ NS_TYPE_VOTE,
+ NS_TYPE_CONSENSUS,
+ NS_TYPE_OPINION,
+} networkstatus_type_t;
+
+/** A common structure to hold a v3 network status vote, or a v3 network
+ * status consensus. */
+struct networkstatus_t {
+ networkstatus_type_t type; /**< Vote, consensus, or opinion? */
+ consensus_flavor_t flavor; /**< If a consensus, what kind? */
+ unsigned int has_measured_bws : 1;/**< True iff this networkstatus contains
+ * measured= bandwidth values. */
+
+ time_t published; /**< Vote only: Time when vote was written. */
+ time_t valid_after; /**< Time after which this vote or consensus applies. */
+ time_t fresh_until; /**< Time before which this is the most recent vote or
+ * consensus. */
+ time_t valid_until; /**< Time after which this vote or consensus should not
+ * be used. */
+
+ /** Consensus only: what method was used to produce this consensus? */
+ int consensus_method;
+ /** Vote only: what methods is this voter willing to use? */
+ smartlist_t *supported_methods;
+
+ /** List of 'package' lines describing hashes of downloadable packages */
+ smartlist_t *package_lines;
+
+ /** How long does this vote/consensus claim that authorities take to
+ * distribute their votes to one another? */
+ int vote_seconds;
+ /** How long does this vote/consensus claim that authorities take to
+ * distribute their consensus signatures to one another? */
+ int dist_seconds;
+
+ /** Comma-separated list of recommended client software, or NULL if this
+ * voter has no opinion. */
+ char *client_versions;
+ char *server_versions;
+
+ /** Lists of subprotocol versions which are _recommended_ for relays and
+ * clients, or which are _require_ for relays and clients. Tor shouldn't
+ * make any more network connections if a required protocol is missing.
+ */
+ char *recommended_relay_protocols;
+ char *recommended_client_protocols;
+ char *required_relay_protocols;
+ char *required_client_protocols;
+
+ /** List of flags that this vote/consensus applies to routers. If a flag is
+ * not listed here, the voter has no opinion on what its value should be. */
+ smartlist_t *known_flags;
+
+ /** List of key=value strings for the parameters in this vote or
+ * consensus, sorted by key. */
+ smartlist_t *net_params;
+
+ /** List of key=value strings for the bw weight parameters in the
+ * consensus. */
+ smartlist_t *weight_params;
+
+ /** List of networkstatus_voter_info_t. For a vote, only one element
+ * is included. For a consensus, one element is included for every voter
+ * whose vote contributed to the consensus. */
+ smartlist_t *voters;
+
+ struct authority_cert_t *cert; /**< Vote only: the voter's certificate. */
+
+ /** Digests of this document, as signed. */
+ common_digests_t digests;
+ /** A SHA3-256 digest of the document, not including signatures: used for
+ * consensus diffs */
+ uint8_t digest_sha3_as_signed[DIGEST256_LEN];
+
+ /** List of router statuses, sorted by identity digest. For a vote,
+ * the elements are vote_routerstatus_t; for a consensus, the elements
+ * are routerstatus_t. */
+ smartlist_t *routerstatus_list;
+
+ /** If present, a map from descriptor digest to elements of
+ * routerstatus_list. */
+ digestmap_t *desc_digest_map;
+
+ /** Contains the shared random protocol data from a vote or consensus. */
+ networkstatus_sr_info_t sr_info;
+};
+
+#endif
diff --git a/src/feature/nodelist/networkstatus_voter_info_st.h b/src/feature/nodelist/networkstatus_voter_info_st.h
new file mode 100644
index 0000000000..93ff3cd418
--- /dev/null
+++ b/src/feature/nodelist/networkstatus_voter_info_st.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef NETWORKSTATUS_VOTER_INFO_ST_H
+#define NETWORKSTATUS_VOTER_INFO_ST_H
+
+/** Information about a single voter in a vote or a consensus. */
+struct networkstatus_voter_info_t {
+ /** Declared SHA-1 digest of this voter's identity key */
+ char identity_digest[DIGEST_LEN];
+ char *nickname; /**< Nickname of this voter */
+ /** Digest of this voter's "legacy" identity key, if any. In vote only; for
+ * 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 */
+ char *contact; /**< Contact information for this voter. */
+ char vote_digest[DIGEST_LEN]; /**< Digest of this voter's vote, as signed. */
+
+ /* Nothing from here on is signed. */
+ /** The signature of the document and the signature's status. */
+ smartlist_t *sigs;
+};
+
+#endif
diff --git a/src/feature/nodelist/node_st.h b/src/feature/nodelist/node_st.h
new file mode 100644
index 0000000000..8d182050ac
--- /dev/null
+++ b/src/feature/nodelist/node_st.h
@@ -0,0 +1,102 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef NODE_ST_H
+#define NODE_ST_H
+
+#include "feature/hs/hsdir_index_st.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+
+/** A node_t represents a Tor router.
+ *
+ * Specifically, a node_t is a Tor router as we are using it: a router that
+ * we are considering for circuits, connections, and so on. A node_t is a
+ * thin wrapper around the routerstatus, routerinfo, and microdesc for a
+ * single router, and provides a consistent interface for all of them.
+ *
+ * Also, a node_t has mutable state. While a routerinfo, a routerstatus,
+ * and a microdesc have[*] only the information read from a router
+ * descriptor, a consensus entry, and a microdescriptor (respectively)...
+ * a node_t has flags based on *our own current opinion* of the node.
+ *
+ * [*] Actually, there is some leftover information in each that is mutable.
+ * We should try to excise that.
+ */
+struct node_t {
+ /* Indexing information */
+
+ /** Used to look up the node_t by its identity digest. */
+ HT_ENTRY(node_t) ht_ent;
+ /** Used to look up the node_t by its ed25519 identity digest. */
+ HT_ENTRY(node_t) ed_ht_ent;
+ /** Position of the node within the list of nodes */
+ int nodelist_idx;
+
+ /** The identity digest of this node_t. No more than one node_t per
+ * identity may exist at a time. */
+ char identity[DIGEST_LEN];
+
+ /** The ed25519 identity of this node_t. This field is nonzero iff we
+ * currently have an ed25519 identity for this node in either md or ri,
+ * _and_ this node has been inserted to the ed25519-to-node map in the
+ * nodelist.
+ */
+ ed25519_public_key_t ed25519_id;
+
+ microdesc_t *md;
+ routerinfo_t *ri;
+ routerstatus_t *rs;
+
+ /* local info: copied from routerstatus, then possibly frobbed based
+ * on experience. Authorities set this stuff directly. Note that
+ * these reflect knowledge of the primary (IPv4) OR port only. */
+
+ unsigned int is_running:1; /**< As far as we know, is this OR currently
+ * running? */
+ unsigned int is_valid:1; /**< Has a trusted dirserver validated this OR?
+ * (For Authdir: Have we validated this OR?) */
+ unsigned int is_fast:1; /** Do we think this is a fast OR? */
+ unsigned int is_stable:1; /** Do we think this is a stable OR? */
+ unsigned int is_possible_guard:1; /**< Do we think this is an OK guard? */
+ unsigned int is_exit:1; /**< Do we think this is an OK exit? */
+ unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked,
+ * or otherwise nasty? */
+ unsigned int is_hs_dir:1; /**< True iff this router is a hidden service
+ * directory according to the authorities. */
+
+ /* Local info: warning state. */
+
+ unsigned int name_lookup_warned:1; /**< Have we warned the user for referring
+ * to this (unnamed) router by nickname?
+ */
+
+ /** Local info: we treat this node as if it rejects everything */
+ unsigned int rejects_all:1;
+
+ /* 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? */
+ 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? */
+ country_t country;
+
+ /* The below items are used only by authdirservers for
+ * reachability testing. */
+
+ /** When was the last time we could reach this OR? */
+ time_t last_reachable; /* IPv4. */
+ time_t last_reachable6; /* IPv6. */
+
+ /* Hidden service directory index data. This is used by a service or client
+ * in order to know what's the hs directory index for this node at the time
+ * the consensus is set. */
+ struct hsdir_index_t hsdir_index;
+};
+
+#endif
diff --git a/src/or/nodelist.c b/src/feature/nodelist/nodelist.c
index ce1830083f..03122ba0f7 100644
--- a/src/or/nodelist.c
+++ b/src/feature/nodelist/nodelist.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -40,33 +40,41 @@
#define NODELIST_PRIVATE
-#include "or.h"
-#include "address.h"
-#include "address_set.h"
-#include "bridges.h"
-#include "config.h"
-#include "control.h"
-#include "dirserv.h"
-#include "entrynodes.h"
-#include "geoip.h"
-#include "hs_common.h"
-#include "hs_client.h"
-#include "main.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "policies.h"
-#include "protover.h"
-#include "rendservice.h"
-#include "router.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "routerset.h"
-#include "torcert.h"
+#include "core/or/or.h"
+#include "lib/net/address.h"
+#include "core/or/address_set.h"
+#include "feature/client/bridges.h"
+#include "app/config/config.h"
+#include "feature/control/control.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/client/entrynodes.h"
+#include "feature/stats/geoip.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_client.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "core/or/protover.h"
+#include "feature/rend/rendservice.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/routerset.h"
+#include "feature/nodelist/torcert.h"
#include <string.h>
-#include "dirauth/mode.h"
+#include "feature/dirauth/mode.h"
+
+#include "feature/dirclient/dir_server_st.h"
+#include "feature/nodelist/microdesc_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/node_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerlist_st.h"
+#include "feature/nodelist/routerstatus_st.h"
static void nodelist_drop_node(node_t *node, int remove_from_ht);
#define node_free(val) \
@@ -643,6 +651,15 @@ nodelist_set_consensus(networkstatus_t *ns)
}
}
+/** Return 1 iff <b>node</b> has Exit flag and no BadExit flag.
+ * Otherwise, return 0.
+ */
+int
+node_is_good_exit(const node_t *node)
+{
+ return node->is_exit && ! node->is_bad_exit;
+}
+
/** Helper: return true iff a node has a usable amount of information*/
static inline int
node_is_usable(const node_t *node)
@@ -2243,9 +2260,14 @@ compute_frac_paths_available(const networkstatus_t *consensus,
* browsing (as distinct from hidden service web browsing). */
}
- f_guard = frac_nodes_with_descriptors(guards, WEIGHT_FOR_GUARD);
- f_mid = frac_nodes_with_descriptors(mid, WEIGHT_FOR_MID);
- f_exit = frac_nodes_with_descriptors(exits, WEIGHT_FOR_EXIT);
+ f_guard = frac_nodes_with_descriptors(guards, WEIGHT_FOR_GUARD, 1);
+ f_mid = frac_nodes_with_descriptors(mid, WEIGHT_FOR_MID, 0);
+ f_exit = frac_nodes_with_descriptors(exits, WEIGHT_FOR_EXIT, 0);
+
+ /* If we are using bridges and have at least one bridge with a full
+ * descriptor, assume f_guard is 1.0. */
+ if (options->UseBridges && num_bridges_usable(0) > 0)
+ f_guard = 1.0;
log_debug(LD_NET,
"f_guard: %.2f, f_mid: %.2f, f_exit: %.2f",
@@ -2299,9 +2321,10 @@ compute_frac_paths_available(const networkstatus_t *consensus,
np,
nu);
- f_myexit= frac_nodes_with_descriptors(myexits,WEIGHT_FOR_EXIT);
+ f_myexit= frac_nodes_with_descriptors(myexits, WEIGHT_FOR_EXIT, 0);
f_myexit_unflagged=
- frac_nodes_with_descriptors(myexits_unflagged,WEIGHT_FOR_EXIT);
+ frac_nodes_with_descriptors(myexits_unflagged,
+ WEIGHT_FOR_EXIT, 0);
log_debug(LD_NET,
"f_exit: %.2f, f_myexit: %.2f, f_myexit_unflagged: %.2f",
diff --git a/src/or/nodelist.h b/src/feature/nodelist/nodelist.h
index dbe9ad18ff..ed3a542971 100644
--- a/src/or/nodelist.h
+++ b/src/feature/nodelist/nodelist.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,15 +12,19 @@
#ifndef TOR_NODELIST_H
#define TOR_NODELIST_H
+struct ed25519_public_key_t;
+struct curve25519_public_key_t;
+
#define node_assert_ok(n) STMT_BEGIN { \
tor_assert((n)->ri || (n)->rs); \
} STMT_END
MOCK_DECL(node_t *, node_get_mutable_by_id,(const char *identity_digest));
MOCK_DECL(const node_t *, node_get_by_id, (const char *identity_digest));
-node_t *node_get_mutable_by_ed25519_id(const ed25519_public_key_t *ed_id);
+node_t *node_get_mutable_by_ed25519_id(
+ const struct ed25519_public_key_t *ed_id);
MOCK_DECL(const node_t *, node_get_by_ed25519_id,
- (const ed25519_public_key_t *ed_id));
+ (const struct ed25519_public_key_t *ed_id));
#define NNF_NO_WARN_UNNAMED (1u<<0)
@@ -47,6 +51,7 @@ void node_get_verbose_nickname(const node_t *node,
void node_get_verbose_nickname_by_id(const char *id_digest,
char *verbose_name_out);
int node_is_dir(const node_t *node);
+int node_is_good_exit(const node_t *node);
int node_has_any_descriptor(const node_t *node);
int node_has_preferred_descriptor(const node_t *node,
int for_direct_connect);
@@ -64,9 +69,9 @@ 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);
const smartlist_t *node_get_declared_family(const node_t *node);
-const ed25519_public_key_t *node_get_ed25519_id(const node_t *node);
+const struct ed25519_public_key_t *node_get_ed25519_id(const node_t *node);
int node_ed25519_id_matches(const node_t *node,
- const ed25519_public_key_t *id);
+ const struct ed25519_public_key_t *id);
int node_supports_ed25519_link_authentication(const node_t *node,
int compatible_with_us);
int node_supports_v3_hsdir(const node_t *node);
@@ -88,7 +93,7 @@ void node_get_prim_dirport(const node_t *node, tor_addr_port_t *ap_out);
void node_get_pref_dirport(const node_t *node, tor_addr_port_t *ap_out);
void node_get_pref_ipv6_dirport(const node_t *node, tor_addr_port_t *ap_out);
int node_has_curve25519_onion_key(const node_t *node);
-const curve25519_public_key_t *node_get_curve25519_onion_key(
+const struct curve25519_public_key_t *node_get_curve25519_onion_key(
const node_t *node);
MOCK_DECL(smartlist_t *, nodelist_get_list, (void));
@@ -161,4 +166,3 @@ node_set_hsdir_index(node_t *node, const networkstatus_t *ns);
MOCK_DECL(int, get_estimated_address_per_node, (void));
#endif /* !defined(TOR_NODELIST_H) */
-
diff --git a/src/or/parsecommon.c b/src/feature/nodelist/parsecommon.c
index 9bd00e17ce..4f1c3fd421 100644
--- a/src/or/parsecommon.c
+++ b/src/feature/nodelist/parsecommon.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -6,9 +6,17 @@
* \brief Common code to parse and validate various type of descriptors.
**/
-#include "parsecommon.h"
-#include "torlog.h"
-#include "util_format.h"
+#include "feature/nodelist/parsecommon.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/encoding/binascii.h"
+#include "lib/container/smartlist.h"
+#include "lib/string/util_string.h"
+#include "lib/string/printf.h"
+#include "lib/memarea/memarea.h"
+#include "lib/crypt_ops/crypto.h"
+
+#include <string.h>
#define MIN_ANNOTATION A_PURPOSE
#define MAX_ANNOTATION A_UNKNOWN_
@@ -448,4 +456,3 @@ find_all_by_keyword(const smartlist_t *s, directory_keyword k)
});
return out;
}
-
diff --git a/src/or/parsecommon.h b/src/feature/nodelist/parsecommon.h
index d33faf8ec7..d0f3810c0b 100644
--- a/src/or/parsecommon.h
+++ b/src/feature/nodelist/parsecommon.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,9 +9,11 @@
#ifndef TOR_PARSECOMMON_H
#define TOR_PARSECOMMON_H
-#include "container.h"
-#include "crypto.h"
-#include "memarea.h"
+#include <stddef.h>
+
+struct smartlist_t;
+struct crypto_pk_t;
+struct memarea_t;
/** Enumeration of possible token types. The ones starting with K_ correspond
* to directory 'keywords'. A_ is for an annotation, R or C is related to
@@ -205,7 +207,7 @@ typedef struct directory_token_t {
size_t object_size; /**< Bytes in object_body */
char *object_body; /**< Contents of object, base64-decoded. */
- crypto_pk_t *key; /**< For public keys only. Heap-allocated. */
+ struct crypto_pk_t *key; /**< For public keys only. Heap-allocated. */
char *error; /**< For ERR_ tokens only. */
} directory_token_t;
@@ -297,26 +299,26 @@ typedef struct token_rule_t {
void token_clear(directory_token_t *tok);
-int tokenize_string(memarea_t *area,
+int tokenize_string(struct memarea_t *area,
const char *start, const char *end,
- smartlist_t *out,
+ struct smartlist_t *out,
token_rule_t *table,
int flags);
-directory_token_t *get_next_token(memarea_t *area,
+directory_token_t *get_next_token(struct memarea_t *area,
const char **s,
const char *eos,
token_rule_t *table);
-directory_token_t *find_by_keyword_(smartlist_t *s,
+directory_token_t *find_by_keyword_(struct smartlist_t *s,
directory_keyword keyword,
const char *keyword_str);
#define find_by_keyword(s, keyword) \
find_by_keyword_((s), (keyword), #keyword)
-directory_token_t *find_opt_by_keyword(const smartlist_t *s,
+directory_token_t *find_opt_by_keyword(const struct smartlist_t *s,
directory_keyword keyword);
-smartlist_t * find_all_by_keyword(const smartlist_t *s, directory_keyword k);
+struct smartlist_t * find_all_by_keyword(const struct smartlist_t *s,
+ directory_keyword k);
#endif /* !defined(TOR_PARSECOMMON_H) */
-
diff --git a/src/feature/nodelist/routerinfo_st.h b/src/feature/nodelist/routerinfo_st.h
new file mode 100644
index 0000000000..ca8fd40e3b
--- /dev/null
+++ b/src/feature/nodelist/routerinfo_st.h
@@ -0,0 +1,108 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef ROUTERINFO_ST_H
+#define ROUTERINFO_ST_H
+
+#include "feature/nodelist/signed_descriptor_st.h"
+
+struct curve25519_public_key_t;
+
+/** Information about another onion router in the network. */
+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 IPv6 address, if it has one. */
+ /* XXXXX187 Actually these should probably be part of a list of addresses,
+ * not just a special case. Use abstractions to access these; don't do it
+ * directly. */
+ tor_addr_t ipv6_addr;
+ uint16_t ipv6_orport;
+
+ crypto_pk_t *onion_pkey; /**< Public RSA key for onions. */
+ crypto_pk_t *identity_pkey; /**< Public RSA key for signing. */
+ /** Public curve25519 key for onions */
+ struct curve25519_public_key_t *onion_curve25519_pkey;
+ /** What's the earliest expiration time on all the certs in this
+ * routerinfo? */
+ time_t cert_expiration_time;
+
+ char *platform; /**< What software/operating system is this OR using? */
+
+ char *protocol_list; /**< Encoded list of subprotocol versions supported
+ * by this OR */
+
+ /* link info */
+ uint32_t bandwidthrate; /**< How many bytes does this OR add to its token
+ * bucket per second? */
+ uint32_t bandwidthburst; /**< How large is this OR's token bucket? */
+ /** How many bytes/s is this router known to handle? */
+ uint32_t bandwidthcapacity;
+ smartlist_t *exit_policy; /**< What streams will this OR permit
+ * to exit on IPv4? NULL for 'reject *:*'. */
+ /** What streams will this OR permit to exit on IPv6?
+ * NULL for 'reject *:*' */
+ struct short_policy_t *ipv6_exit_policy;
+ long uptime; /**< How many seconds the router claims to have been up */
+ smartlist_t *declared_family; /**< Nicknames of router which this router
+ * claims are its family. */
+ char *contact_info; /**< Declared contact info for this router. */
+ unsigned int is_hibernating:1; /**< Whether the router claims to be
+ * hibernating */
+ unsigned int caches_extra_info:1; /**< Whether the router says it caches and
+ * serves extrainfo documents. */
+ unsigned int allow_single_hop_exits:1; /**< Whether the router says
+ * it allows single hop exits. */
+
+ unsigned int wants_to_be_hs_dir:1; /**< True iff this router claims to be
+ * a hidden service directory. */
+ unsigned int policy_is_reject_star:1; /**< True iff the exit policy for this
+ * router rejects everything. */
+ /** True if, after we have added this router, we should re-launch
+ * tests for it. */
+ unsigned int needs_retest_if_added:1;
+
+ /** True iff this router included "tunnelled-dir-server" in its descriptor,
+ * implying it accepts tunnelled directory requests, or it advertised
+ * dir_port > 0. */
+ unsigned int supports_tunnelled_dir_requests:1;
+
+ /** Used during voting to indicate that we should not include an entry for
+ * this routerinfo. Used only during voting. */
+ unsigned int omit_from_vote:1;
+
+ /** Flags to summarize the protocol versions for this routerinfo_t. */
+ protover_summary_flags_t pv;
+
+/** Tor can use this router for general positions in circuits; we got it
+ * from a directory server as usual, or we're an authority and a server
+ * uploaded it. */
+#define ROUTER_PURPOSE_GENERAL 0
+/** Tor should avoid using this router for circuit-building: we got it
+ * from a controller. If the controller wants to use it, it'll have to
+ * ask for it by identity. */
+#define ROUTER_PURPOSE_CONTROLLER 1
+/** Tor should use this router only for bridge positions in circuits: we got
+ * it via a directory request from the bridge itself, or a bridge
+ * authority. */
+#define ROUTER_PURPOSE_BRIDGE 2
+/** Tor should not use this router; it was marked in cached-descriptors with
+ * a purpose we didn't recognize. */
+#define ROUTER_PURPOSE_UNKNOWN 255
+
+ /** In what way did we find out about this router? One of ROUTER_PURPOSE_*.
+ * Routers of different purposes are kept segregated and used for different
+ * things; see notes on ROUTER_PURPOSE_* macros above.
+ */
+ uint8_t purpose;
+};
+
+#endif
diff --git a/src/or/routerlist.c b/src/feature/nodelist/routerlist.c
index 2f27af7f06..12226fee64 100644
--- a/src/or/routerlist.c
+++ b/src/feature/nodelist/routerlist.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -91,39 +91,59 @@
**/
#define ROUTERLIST_PRIVATE
-#include "or.h"
-#include "backtrace.h"
-#include "bridges.h"
-#include "crypto_ed25519.h"
-#include "circuitstats.h"
-#include "config.h"
-#include "connection.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "directory.h"
-#include "dirserv.h"
-#include "entrynodes.h"
-#include "fp_pair.h"
-#include "geoip.h"
-#include "hibernate.h"
-#include "main.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "policies.h"
-#include "reasons.h"
-#include "rendcommon.h"
-#include "rendservice.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "routerset.h"
-#include "sandbox.h"
-#include "torcert.h"
-
-#include "dirauth/dirvote.h"
-#include "dirauth/mode.h"
+#include "core/or/or.h"
+#include "lib/err/backtrace.h"
+#include "feature/client/bridges.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "core/or/circuitstats.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/dircache/directory.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/client/entrynodes.h"
+#include "feature/dircommon/fp_pair.h"
+#include "feature/stats/geoip.h"
+#include "feature/hibernate/hibernate.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "core/or/reasons.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/rend/rendservice.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/routerset.h"
+#include "lib/sandbox/sandbox.h"
+#include "feature/nodelist/torcert.h"
+#include "lib/math/fp.h"
+
+#include "feature/dirauth/dirvote.h"
+#include "feature/dirauth/mode.h"
+
+#include "feature/nodelist/authority_cert_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "feature/dirclient/dir_server_st.h"
+#include "feature/nodelist/document_signature_st.h"
+#include "feature/nodelist/extrainfo_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/networkstatus_voter_info_st.h"
+#include "feature/nodelist/node_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerlist_st.h"
+#include "feature/nodelist/vote_routerstatus_st.h"
+
+#include "lib/crypt_ops/digestset.h"
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
// #define DEBUG_ROUTERLIST
@@ -1786,6 +1806,12 @@ router_pick_dirserver_generic(smartlist_t *sourcelist,
const routerstatus_t *choice;
int busy = 0;
+ if (smartlist_len(sourcelist) == 1) {
+ /* If there's only one choice, then we should disable the logic that
+ * would otherwise prevent us from choosing ourself. */
+ flags |= PDS_ALLOW_SELF;
+ }
+
choice = router_pick_trusteddirserver_impl(sourcelist, type, flags, &busy);
if (choice || !(flags & PDS_RETRY_IF_NO_SERVERS))
return choice;
@@ -2746,10 +2772,15 @@ compute_weighted_bandwidths(const smartlist_t *sl,
/** For all nodes in <b>sl</b>, return the fraction of those nodes, weighted
* by their weighted bandwidths with rule <b>rule</b>, for which we have
- * descriptors. */
+ * descriptors.
+ *
+ * If <b>for_direct_connect</b> is true, we intend to connect to the node
+ * directly, as the first hop of a circuit; otherwise, we intend to connect
+ * to it indirectly, or use it as if we were connecting to it indirectly. */
double
frac_nodes_with_descriptors(const smartlist_t *sl,
- bandwidth_weight_rule_t rule)
+ bandwidth_weight_rule_t rule,
+ int for_direct_conn)
{
double *bandwidths = NULL;
double total, present;
@@ -2761,7 +2792,7 @@ frac_nodes_with_descriptors(const smartlist_t *sl,
total <= 0.0) {
int n_with_descs = 0;
SMARTLIST_FOREACH(sl, const node_t *, node, {
- if (node_has_any_descriptor(node))
+ if (node_has_preferred_descriptor(node, for_direct_conn))
n_with_descs++;
});
tor_free(bandwidths);
@@ -2770,7 +2801,7 @@ frac_nodes_with_descriptors(const smartlist_t *sl,
present = 0.0;
SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) {
- if (node_has_any_descriptor(node))
+ if (node_has_preferred_descriptor(node, for_direct_conn))
present += bandwidths[node_sl_idx];
} SMARTLIST_FOREACH_END(node);
@@ -3328,10 +3359,10 @@ dump_routerlist_mem_usage(int severity)
olddescs += sd->signed_descriptor_len);
tor_log(severity, LD_DIR,
- "In %d live descriptors: "U64_FORMAT" bytes. "
- "In %d old descriptors: "U64_FORMAT" bytes.",
- smartlist_len(routerlist->routers), U64_PRINTF_ARG(livedescs),
- smartlist_len(routerlist->old_routers), U64_PRINTF_ARG(olddescs));
+ "In %d live descriptors: %"PRIu64" bytes. "
+ "In %d old descriptors: %"PRIu64" bytes.",
+ smartlist_len(routerlist->routers), (livedescs),
+ smartlist_len(routerlist->old_routers), (olddescs));
}
/** Debugging helper: If <b>idx</b> is nonnegative, assert that <b>ri</b> is
@@ -4098,7 +4129,8 @@ routerlist_remove_old_cached_routers_with_id(time_t now,
signed_descriptor_t *r_next;
lifespans[i-lo].idx = i;
if (r->last_listed_as_valid_until >= now ||
- (retain && digestset_contains(retain, r->signed_descriptor_digest))) {
+ (retain && digestset_probably_contains(retain,
+ r->signed_descriptor_digest))) {
must_keep[i-lo] = 1;
}
if (i < hi) {
@@ -4193,7 +4225,7 @@ routerlist_remove_old_routers(void)
router = smartlist_get(routerlist->routers, i);
if (router->cache_info.published_on <= cutoff &&
router->cache_info.last_listed_as_valid_until < now &&
- !digestset_contains(retain,
+ !digestset_probably_contains(retain,
router->cache_info.signed_descriptor_digest)) {
/* Too old: remove it. (If we're a cache, just move it into
* old_routers.) */
@@ -4214,7 +4246,7 @@ routerlist_remove_old_routers(void)
sd = smartlist_get(routerlist->old_routers, i);
if (sd->published_on <= cutoff &&
sd->last_listed_as_valid_until < now &&
- !digestset_contains(retain, sd->signed_descriptor_digest)) {
+ !digestset_probably_contains(retain, sd->signed_descriptor_digest)) {
/* Too old. Remove it. */
routerlist_remove_old(routerlist, sd, i--);
}
@@ -5820,4 +5852,3 @@ refresh_all_country_info(void)
nodelist_refresh_countries();
}
-
diff --git a/src/or/routerlist.h b/src/feature/nodelist/routerlist.h
index 83f4d1002f..4b7406364f 100644
--- a/src/or/routerlist.h
+++ b/src/feature/nodelist/routerlist.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -11,7 +11,91 @@
#ifndef TOR_ROUTERLIST_H
#define TOR_ROUTERLIST_H
-#include "testsupport.h"
+#include "lib/testsupport/testsupport.h"
+
+/** Return value for router_add_to_routerlist() and dirserv_add_descriptor() */
+typedef enum was_router_added_t {
+ /* Router was added successfully. */
+ ROUTER_ADDED_SUCCESSFULLY = 1,
+ /* Extrainfo document was rejected because no corresponding router
+ * descriptor was found OR router descriptor was rejected because
+ * it was incompatible with its extrainfo document. */
+ ROUTER_BAD_EI = -1,
+ /* Router descriptor was rejected because it is already known. */
+ ROUTER_IS_ALREADY_KNOWN = -2,
+ /* General purpose router was rejected, because it was not listed
+ * in consensus. */
+ ROUTER_NOT_IN_CONSENSUS = -3,
+ /* Router was neither in directory consensus nor in any of
+ * networkstatus documents. Caching it to access later.
+ * (Applies to fetched descriptors only.) */
+ ROUTER_NOT_IN_CONSENSUS_OR_NETWORKSTATUS = -4,
+ /* Router was rejected by directory authority. */
+ ROUTER_AUTHDIR_REJECTS = -5,
+ /* Bridge descriptor was rejected because such bridge was not one
+ * of the bridges we have listed in our configuration. */
+ ROUTER_WAS_NOT_WANTED = -6,
+ /* Router descriptor was rejected because it was older than
+ * OLD_ROUTER_DESC_MAX_AGE. */
+ ROUTER_WAS_TOO_OLD = -7, /* note contrast with 'NOT_NEW' */
+ /* DOCDOC */
+ ROUTER_CERTS_EXPIRED = -8
+} was_router_added_t;
+
+/** 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 {
+ CRN_NEED_UPTIME = 1<<0,
+ 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,
+ /* 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,
+} router_crn_flags_t;
+
+/** Possible ways to weight routers when choosing one randomly. See
+ * routerlist_sl_choose_by_bandwidth() for more information.*/
+typedef enum bandwidth_weight_rule_t {
+ NO_WEIGHTING, WEIGHT_FOR_EXIT, WEIGHT_FOR_MID, WEIGHT_FOR_GUARD,
+ WEIGHT_FOR_DIR
+} bandwidth_weight_rule_t;
+
+/* Flags for pick_directory_server() and pick_trusteddirserver(). */
+/** Flag to indicate that we should not automatically be willing to use
+ * ourself to answer a directory request.
+ * Passed to router_pick_directory_server (et al).*/
+#define PDS_ALLOW_SELF (1<<0)
+/** Flag to indicate that if no servers seem to be up, we should mark all
+ * directory servers as up and try again.
+ * Passed to router_pick_directory_server (et al).*/
+#define PDS_RETRY_IF_NO_SERVERS (1<<1)
+/** Flag to indicate that we should not exclude directory servers that
+ * our ReachableAddress settings would exclude. This usually means that
+ * we're going to connect to the server over Tor, and so we don't need to
+ * worry about our firewall telling us we can't.
+ * Passed to router_pick_directory_server (et al).*/
+#define PDS_IGNORE_FASCISTFIREWALL (1<<2)
+/** Flag to indicate that we should not use any directory authority to which
+ * we have an existing directory connection for downloading server descriptors
+ * or extrainfo documents.
+ *
+ * Passed to router_pick_directory_server (et al)
+ */
+#define PDS_NO_EXISTING_SERVERDESC_FETCH (1<<3)
+/** Flag to indicate that we should not use any directory authority to which
+ * we have an existing directory connection for downloading microdescs.
+ *
+ * Passed to router_pick_directory_server (et al)
+ */
+#define PDS_NO_EXISTING_MICRODESC_FETCH (1<<4)
int get_n_authorities(dirinfo_type_t type);
int trusted_dirs_reload_certs(void);
@@ -74,7 +158,8 @@ uint32_t router_get_advertised_bandwidth_capped(const routerinfo_t *router);
const node_t *node_sl_choose_by_bandwidth(const smartlist_t *sl,
bandwidth_weight_rule_t rule);
double frac_nodes_with_descriptors(const smartlist_t *sl,
- bandwidth_weight_rule_t rule);
+ bandwidth_weight_rule_t rule,
+ int for_direct_conn);
const node_t *router_choose_random_node(smartlist_t *excludedsmartlist,
struct routerset_t *excludedset,
@@ -260,4 +345,3 @@ STATIC int router_is_already_dir_fetching(const tor_addr_port_t *ap,
#endif /* defined(ROUTERLIST_PRIVATE) */
#endif /* !defined(TOR_ROUTERLIST_H) */
-
diff --git a/src/feature/nodelist/routerlist_st.h b/src/feature/nodelist/routerlist_st.h
new file mode 100644
index 0000000000..26cc66138c
--- /dev/null
+++ b/src/feature/nodelist/routerlist_st.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-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef ROUTERLIST_ST_H
+#define ROUTERLIST_ST_H
+
+#include "feature/nodelist/desc_store_st.h"
+
+/** Contents of a directory of onion routers. */
+struct routerlist_t {
+ /** Map from server identity digest to a member of routers. */
+ struct digest_ri_map_t *identity_map;
+ /** Map from server descriptor digest to a signed_descriptor_t from
+ * routers or old_routers. */
+ struct digest_sd_map_t *desc_digest_map;
+ /** Map from extra-info digest to an extrainfo_t. Only exists for
+ * routers in routers or old_routers. */
+ struct digest_ei_map_t *extra_info_map;
+ /** Map from extra-info digests to a signed_descriptor_t for a router
+ * descriptor having that extra-info digest. Only exists for
+ * routers in routers or old_routers. */
+ struct digest_sd_map_t *desc_by_eid_map;
+ /** List of routerinfo_t for all currently live routers we know. */
+ smartlist_t *routers;
+ /** List of signed_descriptor_t for older router descriptors we're
+ * caching. */
+ smartlist_t *old_routers;
+ /** Store holding server descriptors. If present, any router whose
+ * cache_info.saved_location == SAVED_IN_CACHE is stored in this file
+ * starting at cache_info.saved_offset */
+ desc_store_t desc_store;
+ /** Store holding extra-info documents. */
+ desc_store_t extrainfo_store;
+};
+
+#endif
+
diff --git a/src/or/routerparse.c b/src/feature/nodelist/routerparse.c
index 7af41c3baf..166806e9c1 100644
--- a/src/or/routerparse.c
+++ b/src/feature/nodelist/routerparse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -55,34 +55,58 @@
#define ROUTERPARSE_PRIVATE
-#include "or.h"
-#include "circuitstats.h"
-#include "config.h"
-#include "crypto_util.h"
-#include "dirauth/shared_random.h"
-#include "dirserv.h"
-#include "entrynodes.h"
-#include "memarea.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "parsecommon.h"
-#include "policies.h"
-#include "protover.h"
-#include "rendcommon.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerkeys.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "sandbox.h"
-#include "shared_random_client.h"
-#include "torcert.h"
-#include "voting_schedule.h"
+#include "core/or/or.h"
+#include "core/or/circuitstats.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/dirauth/shared_random.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/client/entrynodes.h"
+#include "lib/memarea/memarea.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/parsecommon.h"
+#include "core/or/policies.h"
+#include "core/or/protover.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routerkeys.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "lib/sandbox/sandbox.h"
+#include "feature/hs_common/shared_random_client.h"
+#include "feature/nodelist/torcert.h"
+#include "feature/dircommon/voting_schedule.h"
+
+#include "feature/dirauth/dirvote.h"
+
+#include "core/or/addr_policy_st.h"
+#include "feature/nodelist/authority_cert_st.h"
+#include "feature/nodelist/document_signature_st.h"
+#include "core/or/extend_info_st.h"
+#include "feature/nodelist/extrainfo_st.h"
+#include "feature/nodelist/microdesc_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/networkstatus_voter_info_st.h"
+#include "feature/dirauth/ns_detached_signatures_st.h"
+#include "feature/rend/rend_authorized_client_st.h"
+#include "feature/rend/rend_intro_point_st.h"
+#include "feature/rend/rend_service_descriptor_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerlist_st.h"
+#include "core/or/tor_version_st.h"
+#include "feature/dirauth/vote_microdesc_hash_st.h"
+#include "feature/nodelist/vote_routerstatus_st.h"
+
+#include "lib/container/bloomfilt.h"
#undef log
#include <math.h>
-
-#include "dirauth/dirvote.h"
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
/****************************************************************************/
@@ -855,8 +879,8 @@ dump_desc_populate_fifo_from_directory(const char *dirname)
/* Log some stats */
log_info(LD_DIR,
"Reloaded unparseable descriptor dump FIFO with %d dump(s) "
- "totaling " U64_FORMAT " bytes",
- smartlist_len(descs_dumped), U64_PRINTF_ARG(len_descs_dumped));
+ "totaling %"PRIu64 " bytes",
+ smartlist_len(descs_dumped), (len_descs_dumped));
}
/* Free the original list */
@@ -2705,7 +2729,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
for (i=0; i < tok->n_args; ++i) {
int p = smartlist_string_pos(vote->known_flags, tok->args[i]);
if (p >= 0) {
- vote_rs->flags |= (U64_LITERAL(1)<<p);
+ vote_rs->flags |= (UINT64_C(1)<<p);
} else {
log_warn(LD_DIR, "Flags line had a flag %s not listed in known_flags.",
escaped(tok->args[i]));
@@ -2928,8 +2952,8 @@ networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
// We use > 1 as the check for these because they are computed as integers.
// Sometimes there are rounding errors.
if (fabs(Wmm - weight_scale) > 1) {
- log_warn(LD_BUG, "Wmm=%f != "I64_FORMAT,
- Wmm, I64_PRINTF_ARG(weight_scale));
+ log_warn(LD_BUG, "Wmm=%f != %"PRId64,
+ Wmm, (weight_scale));
valid = 0;
}
@@ -2949,20 +2973,20 @@ networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
}
if (fabs(Wgg + Wmg - weight_scale) > 0.001*weight_scale) {
- log_warn(LD_BUG, "Wgg=%f != "I64_FORMAT" - Wmg=%f", Wgg,
- I64_PRINTF_ARG(weight_scale), Wmg);
+ log_warn(LD_BUG, "Wgg=%f != %"PRId64" - Wmg=%f", Wgg,
+ (weight_scale), Wmg);
valid = 0;
}
if (fabs(Wee + Wme - weight_scale) > 0.001*weight_scale) {
- log_warn(LD_BUG, "Wee=%f != "I64_FORMAT" - Wme=%f", Wee,
- I64_PRINTF_ARG(weight_scale), Wme);
+ log_warn(LD_BUG, "Wee=%f != %"PRId64" - Wme=%f", Wee,
+ (weight_scale), Wme);
valid = 0;
}
if (fabs(Wgd + Wmd + Wed - weight_scale) > 0.001*weight_scale) {
- log_warn(LD_BUG, "Wgd=%f + Wmd=%f + Wed=%f != "I64_FORMAT,
- Wgd, Wmd, Wed, I64_PRINTF_ARG(weight_scale));
+ log_warn(LD_BUG, "Wgd=%f + Wmd=%f + Wed=%f != %"PRId64,
+ Wgd, Wmd, Wed, (weight_scale));
valid = 0;
}
@@ -3020,36 +3044,36 @@ networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
log_warn(LD_DIR,
"Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
- "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
- " T="I64_FORMAT". "
+ "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
+ " T=%"PRId64". "
"Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Etotal, Mtotal,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ (G), (M), (E),
+ (D), (T),
Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
valid = 0;
}
if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
log_warn(LD_DIR,
"Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
- "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
- " T="I64_FORMAT". "
+ "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
+ " T=%"PRId64". "
"Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Etotal, Gtotal,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ (G), (M), (E),
+ (D), (T),
Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
valid = 0;
}
if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
log_warn(LD_DIR,
"Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
- "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
- " T="I64_FORMAT". "
+ "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
+ " T=%"PRId64". "
"Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Mtotal, Gtotal,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ (G), (M), (E),
+ (D), (T),
Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
valid = 0;
}
@@ -3076,12 +3100,12 @@ networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
if (Rtotal > Stotal) {
log_warn(LD_DIR,
"Bw Weight Failure for %s: Rtotal %f > Stotal %f. "
- "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
- " T="I64_FORMAT". "
+ "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
+ " T=%"PRId64". "
"Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Rtotal, Stotal,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ (G), (M), (E),
+ (D), (T),
Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
valid = 0;
}
@@ -3089,12 +3113,12 @@ networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
if (3*Rtotal > T) {
log_warn(LD_DIR,
"Bw Weight Failure for %s: 3*Rtotal %f > T "
- I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
- " D="I64_FORMAT" T="I64_FORMAT". "
+ "%"PRId64". G=%"PRId64" M=%"PRId64" E=%"PRId64
+ " D=%"PRId64" T=%"PRId64". "
"Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
- casename, Rtotal*3, I64_PRINTF_ARG(T),
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ casename, Rtotal*3, (T),
+ (G), (M), (E),
+ (D), (T),
Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
valid = 0;
}
@@ -3102,12 +3126,12 @@ networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
if (3*Stotal > T) {
log_warn(LD_DIR,
"Bw Weight Failure for %s: 3*Stotal %f > T "
- I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
- " D="I64_FORMAT" T="I64_FORMAT". "
+ "%"PRId64". G=%"PRId64" M=%"PRId64" E=%"PRId64
+ " D=%"PRId64" T=%"PRId64". "
"Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
- casename, Stotal*3, I64_PRINTF_ARG(T),
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ casename, Stotal*3, (T),
+ (G), (M), (E),
+ (D), (T),
Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
valid = 0;
}
@@ -3115,13 +3139,13 @@ networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
if (3*Mtotal < T) {
log_warn(LD_DIR,
"Bw Weight Failure for %s: 3*Mtotal %f < T "
- I64_FORMAT". "
- "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
- " T="I64_FORMAT". "
+ "%"PRId64". "
+ "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
+ " T=%"PRId64". "
"Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
- casename, Mtotal*3, I64_PRINTF_ARG(T),
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ casename, Mtotal*3, (T),
+ (G), (M), (E),
+ (D), (T),
Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
valid = 0;
}
@@ -3134,36 +3158,36 @@ networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
log_warn(LD_DIR,
"Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
- "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
- " T="I64_FORMAT". "
+ "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
+ " T=%"PRId64". "
"Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Etotal, Mtotal,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ (G), (M), (E),
+ (D), (T),
Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
valid = 0;
}
if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
log_warn(LD_DIR,
"Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
- "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
- " T="I64_FORMAT". "
+ "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
+ " T=%"PRId64". "
"Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Etotal, Gtotal,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ (G), (M), (E),
+ (D), (T),
Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
valid = 0;
}
if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
log_warn(LD_DIR,
"Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
- "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
- " T="I64_FORMAT". "
+ "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
+ " T=%"PRId64". "
"Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Mtotal, Gtotal,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ (G), (M), (E),
+ (D), (T),
Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
valid = 0;
}
@@ -3171,12 +3195,12 @@ networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
log_warn(LD_DIR,
"Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
- "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
- " T="I64_FORMAT". "
+ "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
+ " T=%"PRId64". "
"Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Etotal, Gtotal,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ (G), (M), (E),
+ (D), (T),
Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
valid = 0;
}
@@ -3201,12 +3225,12 @@ networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
if (3*Stotal > T) {
log_warn(LD_DIR,
"Bw Weight Failure for %s: 3*Stotal %f > T "
- I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
- " D="I64_FORMAT" T="I64_FORMAT". "
+ "%"PRId64". G=%"PRId64" M=%"PRId64" E=%"PRId64
+ " D=%"PRId64" T=%"PRId64". "
"Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
- casename, Stotal*3, I64_PRINTF_ARG(T),
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ casename, Stotal*3, (T),
+ (G), (M), (E),
+ (D), (T),
Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
valid = 0;
}
@@ -3214,12 +3238,12 @@ networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
if (fabs(NStotal-Mtotal) > 0.01*MAX(NStotal,Mtotal)) {
log_warn(LD_DIR,
"Bw Weight Failure for %s: NStotal %f != Mtotal %f. "
- "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
- " T="I64_FORMAT". "
+ "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
+ " T=%"PRId64". "
"Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, NStotal, Mtotal,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ (G), (M), (E),
+ (D), (T),
Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
valid = 0;
}
@@ -3228,12 +3252,12 @@ networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
if (3*NStotal < T) {
log_warn(LD_DIR,
"Bw Weight Failure for %s: 3*NStotal %f < T "
- I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT
- " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT". "
+ "%"PRId64". G=%"PRId64" M=%"PRId64
+ " E=%"PRId64" D=%"PRId64" T=%"PRId64". "
"Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
- casename, NStotal*3, I64_PRINTF_ARG(T),
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ casename, NStotal*3, (T),
+ (G), (M), (E),
+ (D), (T),
Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
valid = 0;
}
@@ -3243,36 +3267,36 @@ networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
log_warn(LD_DIR,
"Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
- "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
- " T="I64_FORMAT". "
+ "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
+ " T=%"PRId64". "
"Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Etotal, Mtotal,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ (G), (M), (E),
+ (D), (T),
Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
valid = 0;
}
if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
log_warn(LD_DIR,
"Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
- "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
- " T="I64_FORMAT". "
+ "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
+ " T=%"PRId64". "
"Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Etotal, Gtotal,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ (G), (M), (E),
+ (D), (T),
Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
valid = 0;
}
if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
log_warn(LD_DIR,
"Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
- "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
- " T="I64_FORMAT". "
+ "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
+ " T=%"PRId64". "
"Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Mtotal, Gtotal,
- I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
- I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
+ (G), (M), (E),
+ (D), (T),
Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
valid = 0;
}
@@ -5667,4 +5691,3 @@ routerparse_free_all(void)
{
dump_desc_fifo_cleanup();
}
-
diff --git a/src/or/routerparse.h b/src/feature/nodelist/routerparse.h
index 418fd3acdb..87c2a75aa5 100644
--- a/src/or/routerparse.h
+++ b/src/feature/nodelist/routerparse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,6 +12,22 @@
#ifndef TOR_ROUTERPARSE_H
#define TOR_ROUTERPARSE_H
+/** Possible statuses of a version of Tor, given opinions from the directory
+ * servers. */
+typedef enum version_status_t {
+ VS_RECOMMENDED=0, /**< This version is listed as recommended. */
+ VS_OLD=1, /**< This version is older than any recommended version. */
+ VS_NEW=2, /**< This version is newer than any recommended version. */
+ VS_NEW_IN_SERIES=3, /**< This version is newer than any recommended version
+ * in its series, but later recommended versions exist.
+ */
+ VS_UNRECOMMENDED=4, /**< This version is not recommended (general case). */
+ VS_EMPTY=5, /**< The version list was empty; no agreed-on versions. */
+ VS_UNKNOWN, /**< We have no idea. */
+} version_status_t;
+
+enum networkstatus_type_t;
+
int router_get_router_hash(const char *s, size_t s_len, char *digest);
int router_get_dir_hash(const char *s, char *digest);
int router_get_networkstatus_v3_hashes(const char *s,
@@ -43,6 +59,7 @@ routerinfo_t *router_parse_entry_from_string(const char *s, const char *end,
int allow_annotations,
const char *prepend_annotations,
int *can_dl_again_out);
+struct digest_ri_map_t;
extrainfo_t *extrainfo_parse_entry_from_string(const char *s, const char *end,
int cache_copy, struct digest_ri_map_t *routermap,
int *can_dl_again_out);
@@ -64,8 +81,8 @@ void dump_distinct_digest_count(int severity);
int compare_vote_routerstatus_entries(const void **_a, const void **_b);
int networkstatus_verify_bw_weights(networkstatus_t *ns, int);
networkstatus_t *networkstatus_parse_vote_from_string(const char *s,
- const char **eos_out,
- networkstatus_type_t ns_type);
+ const char **eos_out,
+ enum networkstatus_type_t ns_type);
ns_detached_signatures_t *networkstatus_parse_detached_signatures(
const char *s, const char *eos);
@@ -142,4 +159,3 @@ STATIC void summarize_protover_flags(protover_summary_flags_t *out,
#define ED_DESC_SIGNATURE_PREFIX "Tor router descriptor signature v1"
#endif /* !defined(TOR_ROUTERPARSE_H) */
-
diff --git a/src/or/routerset.c b/src/feature/nodelist/routerset.c
index a2599b316c..cd42697748 100644
--- a/src/or/routerset.c
+++ b/src/feature/nodelist/routerset.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
+n * Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -27,14 +27,20 @@
#define ROUTERSET_PRIVATE
-#include "or.h"
-#include "bridges.h"
-#include "geoip.h"
-#include "nodelist.h"
-#include "policies.h"
-#include "router.h"
-#include "routerparse.h"
-#include "routerset.h"
+#include "core/or/or.h"
+#include "feature/client/bridges.h"
+#include "feature/stats/geoip.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/routerset.h"
+
+#include "core/or/addr_policy_st.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"
/** Return a new empty routerset. */
routerset_t *
@@ -455,4 +461,3 @@ routerset_free_(routerset_t *routerset)
bitarray_free(routerset->countries);
tor_free(routerset);
}
-
diff --git a/src/or/routerset.h b/src/feature/nodelist/routerset.h
index 53e8c66c5e..8a13ca042a 100644
--- a/src/or/routerset.h
+++ b/src/feature/nodelist/routerset.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -45,6 +45,8 @@ void routerset_free_(routerset_t *routerset);
int routerset_len(const routerset_t *set);
#ifdef ROUTERSET_PRIVATE
+#include "lib/container/bitarray.h"
+
STATIC char * routerset_get_countryname(const char *c);
STATIC int routerset_contains(const routerset_t *set, const tor_addr_t *addr,
uint16_t orport,
@@ -85,4 +87,3 @@ struct routerset_t {
};
#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
new file mode 100644
index 0000000000..714aa27435
--- /dev/null
+++ b/src/feature/nodelist/routerstatus_st.h
@@ -0,0 +1,80 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef ROUTERSTATUS_ST_H
+#define ROUTERSTATUS_ST_H
+
+#include "feature/dirclient/download_status_st.h"
+
+/** Contents of a single router entry in a network status object.
+ */
+struct routerstatus_t {
+ time_t published_on; /**< When was this router published? */
+ char nickname[MAX_NICKNAME_LEN+1]; /**< The nickname this router says it
+ * has. */
+ char identity_digest[DIGEST_LEN]; /**< Digest of the router's identity
+ * key. */
+ /** 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 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. */
+ unsigned int is_exit:1; /**< True iff this router is a good exit. */
+ unsigned int is_stable:1; /**< True iff this router stays up a long time. */
+ unsigned int is_fast:1; /**< True iff this router has good bandwidth. */
+ /** True iff this router is called 'running' in the consensus. We give it
+ * this funny name so that we don't accidentally use this bit as a view of
+ * whether we think the router is *currently* running. If that's what you
+ * want to know, look at is_running in node_t. */
+ unsigned int is_flagged_running:1;
+ unsigned int is_named:1; /**< True iff "nickname" belongs to this router. */
+ unsigned int is_unnamed:1; /**< True iff "nickname" belongs to another
+ * router. */
+ unsigned int is_valid:1; /**< True iff this router isn't invalid. */
+ unsigned int is_possible_guard:1; /**< True iff this router would be a good
+ * choice as an entry guard. */
+ unsigned int is_bad_exit:1; /**< True iff this node is a bad choice for
+ * an exit node. */
+ unsigned int is_hs_dir:1; /**< True iff this router is a v2-or-later hidden
+ * service directory. */
+ unsigned int is_v2_dir:1; /** True iff this router publishes an open DirPort
+ * or it claims to accept tunnelled dir requests.
+ */
+
+ unsigned int has_bandwidth:1; /**< The vote/consensus had bw info */
+ unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */
+ unsigned int bw_is_unmeasured:1; /**< This is a consensus entry, with
+ * the Unmeasured flag set. */
+
+ /** Flags to summarize the protocol versions for this routerstatus_t. */
+ protover_summary_flags_t pv;
+
+ uint32_t bandwidth_kb; /**< Bandwidth (capacity) of the router as reported in
+ * the vote/consensus, in kilobytes/sec. */
+
+ /** The consensus has guardfraction information for this router. */
+ unsigned int has_guardfraction:1;
+ /** The guardfraction value of this router. */
+ uint32_t guardfraction_percentage;
+
+ char *exitsummary; /**< exit policy summary -
+ * XXX weasel: this probably should not stay a string. */
+
+ /* ---- The fields below aren't derived from the networkstatus; they
+ * hold local information only. */
+
+ time_t last_dir_503_at; /**< When did this router last tell us that it
+ * was too busy to serve directory info? */
+ download_status_t dl_status;
+
+};
+
+#endif
+
diff --git a/src/feature/nodelist/signed_descriptor_st.h b/src/feature/nodelist/signed_descriptor_st.h
new file mode 100644
index 0000000000..bffad62895
--- /dev/null
+++ b/src/feature/nodelist/signed_descriptor_st.h
@@ -0,0 +1,61 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef SIGNED_DESCRIPTOR_ST_H
+#define SIGNED_DESCRIPTOR_ST_H
+
+#include "feature/dirclient/download_status_st.h"
+
+/** Information need to cache an onion router's descriptor. */
+struct signed_descriptor_t {
+ /** Pointer to the raw server descriptor, preceded by annotations. Not
+ * necessarily NUL-terminated. If saved_location is SAVED_IN_CACHE, this
+ * pointer is null. */
+ char *signed_descriptor_body;
+ /** Length of the annotations preceding the server descriptor. */
+ size_t annotations_len;
+ /** Length of the server descriptor. */
+ size_t signed_descriptor_len;
+ /** Digest of the server descriptor, computed as specified in
+ * dir-spec.txt. */
+ char signed_descriptor_digest[DIGEST_LEN];
+ /** Identity digest of the router. */
+ char identity_digest[DIGEST_LEN];
+ /** Declared publication time of the descriptor. */
+ time_t published_on;
+ /** For routerdescs only: digest of the corresponding extrainfo. */
+ char extra_info_digest[DIGEST_LEN];
+ /** For routerdescs only: A SHA256-digest of the extrainfo (if any) */
+ char extra_info_digest256[DIGEST256_LEN];
+ /** Certificate for ed25519 signing key. */
+ struct tor_cert_st *signing_key_cert;
+ /** For routerdescs only: Status of downloading the corresponding
+ * extrainfo. */
+ download_status_t ei_dl_status;
+ /** Where is the descriptor saved? */
+ saved_location_t saved_location;
+ /** If saved_location is SAVED_IN_CACHE or SAVED_IN_JOURNAL, the offset of
+ * this descriptor in the corresponding file. */
+ off_t saved_offset;
+ /** What position is this descriptor within routerlist->routers or
+ * routerlist->old_routers? -1 for none. */
+ int routerlist_index;
+ /** The valid-until time of the most recent consensus that listed this
+ * descriptor. 0 for "never listed in a consensus, so far as we know." */
+ time_t last_listed_as_valid_until;
+ /* If true, we do not ever try to save this object in the cache. */
+ unsigned int do_not_cache : 1;
+ /* If true, this item is meant to represent an extrainfo. */
+ unsigned int is_extrainfo : 1;
+ /* If true, we got an extrainfo for this item, and the digest was right,
+ * but it was incompatible. */
+ unsigned int extrainfo_is_bogus : 1;
+ /* If true, we are willing to transmit this item unencrypted. */
+ unsigned int send_unencrypted : 1;
+};
+
+#endif
+
diff --git a/src/or/torcert.c b/src/feature/nodelist/torcert.c
index 1c5afd965a..172d4f9de3 100644
--- a/src/or/torcert.c
+++ b/src/feature/nodelist/torcert.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -25,15 +25,16 @@
* that one is authority_cert_t, and it's mostly handled in routerlist.c.
*/
-#include "or.h"
-#include "config.h"
-#include "crypto_util.h"
-#include "torcert.h"
-#include "ed25519_cert.h"
-#include "torlog.h"
-#include "util.h"
-#include "compat.h"
-#include "link_handshake.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/nodelist/torcert.h"
+#include "trunnel/ed25519_cert.h"
+#include "lib/log/torlog.h"
+#include "trunnel/link_handshake.h"
+#include "lib/tls/tortls.h"
+
+#include "core/or/or_handshake_certs_st.h"
/** Helper for tor_cert_create(): signs any 32 bytes, not just an ed25519
* key.
@@ -167,7 +168,7 @@ tor_cert_parse(const uint8_t *encoded, const size_t len)
memcpy(cert->signed_key.pubkey, parsed->certified_key, 32);
int64_t valid_until_64 = ((int64_t)parsed->exp_field) * 3600;
-#if SIZEOF_TIME_T < SIZEOF_INT64_T
+#if SIZEOF_TIME_T < 8
if (valid_until_64 > TIME_MAX)
valid_until_64 = TIME_MAX - 1;
#endif
@@ -722,4 +723,3 @@ tor_cert_encode_ed22519(const tor_cert_t *cert, char **cert_str_out)
tor_free(ed_cert_b64);
return ret;
}
-
diff --git a/src/or/torcert.h b/src/feature/nodelist/torcert.h
index 18ca60b5a8..5fa97679df 100644
--- a/src/or/torcert.h
+++ b/src/feature/nodelist/torcert.h
@@ -1,10 +1,10 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TORCERT_H_INCLUDED
#define TORCERT_H_INCLUDED
-#include "crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
#define SIGNED_KEY_TYPE_ED25519 0x01
@@ -49,6 +49,8 @@ typedef struct tor_cert_st {
unsigned cert_valid : 1;
} tor_cert_t;
+struct tor_tls_t;
+
tor_cert_t *tor_cert_create(const ed25519_keypair_t *signing_key,
uint8_t cert_type,
const ed25519_public_key_t *signed_key,
@@ -90,15 +92,15 @@ void or_handshake_certs_free_(or_handshake_certs_t *certs);
FREE_AND_NULL(or_handshake_certs_t, or_handshake_certs_free_, (certs))
int or_handshake_certs_rsa_ok(int severity,
or_handshake_certs_t *certs,
- tor_tls_t *tls,
+ struct tor_tls_t *tls,
time_t now);
int or_handshake_certs_ed25519_ok(int severity,
or_handshake_certs_t *certs,
- tor_tls_t *tls,
+ struct tor_tls_t *tls,
time_t now);
void or_handshake_certs_check_both(int severity,
or_handshake_certs_t *certs,
- tor_tls_t *tls,
+ struct tor_tls_t *tls,
time_t now,
const ed25519_public_key_t **ed_id_out,
const common_digests_t **rsa_id_out);
@@ -106,4 +108,3 @@ void or_handshake_certs_check_both(int severity,
int tor_cert_encode_ed22519(const tor_cert_t *cert, char **cert_str_out);
#endif /* !defined(TORCERT_H_INCLUDED) */
-
diff --git a/src/feature/nodelist/vote_routerstatus_st.h b/src/feature/nodelist/vote_routerstatus_st.h
new file mode 100644
index 0000000000..ad0d35b4e6
--- /dev/null
+++ b/src/feature/nodelist/vote_routerstatus_st.h
@@ -0,0 +1,41 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef VOTE_ROUTERSTATUS_ST_H
+#define VOTE_ROUTERSTATUS_ST_H
+
+#include "feature/nodelist/routerstatus_st.h"
+#include "lib/defs/x25519_sizes.h"
+
+/** The claim about a single router, made in a vote. */
+struct vote_routerstatus_t {
+ routerstatus_t status; /**< Underlying 'status' object for this router.
+ * Flags are redundant. */
+ /** How many known-flags are allowed in a vote? This is the width of
+ * the flags field of vote_routerstatus_t */
+#define MAX_KNOWN_FLAGS_IN_VOTE 64
+ uint64_t flags; /**< Bit-field for all recognized flags; index into
+ * networkstatus_t.known_flags. */
+ char *version; /**< The version that the authority says this router is
+ * running. */
+ char *protocols; /**< The protocols that this authority says this router
+ * provides. */
+ unsigned int has_measured_bw:1; /**< The vote had a measured bw */
+ /** True iff the vote included an entry for ed25519 ID, or included
+ * "id ed25519 none" to indicate that there was no ed25519 ID. */
+ unsigned int has_ed25519_listing:1;
+ /** True if the Ed25519 listing here is the consensus-opinion for the
+ * Ed25519 listing; false if there was no consensus on Ed25519 key status,
+ * or if this VRS doesn't reflect it. */
+ unsigned int ed25519_reflects_consensus:1;
+ uint32_t measured_bw_kb; /**< Measured bandwidth (capacity) of the router */
+ /** The hash or hashes that the authority claims this microdesc has. */
+ vote_microdesc_hash_t *microdesc;
+ /** Ed25519 identity for this router, or zero if it has none. */
+ uint8_t ed25519_id[ED25519_PUBKEY_LEN];
+};
+
+#endif
diff --git a/src/or/dns.c b/src/feature/relay/dns.c
index ba734ed900..f4e39dfd3d 100644
--- a/src/or/dns.c
+++ b/src/feature/relay/dns.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -49,21 +49,30 @@
#define DNS_PRIVATE
-#include "or.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "config.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "dns.h"
-#include "main.h"
-#include "policies.h"
-#include "relay.h"
-#include "router.h"
+#include "core/or/or.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/relay/dns.h"
+#include "core/mainloop/main.h"
+#include "core/or/policies.h"
+#include "core/or/relay.h"
+#include "feature/relay/router.h"
#include "ht.h"
-#include "sandbox.h"
+#include "lib/sandbox/sandbox.h"
+#include "lib/evloop/compat_libevent.h"
+
+#include "core/or/edge_connection_st.h"
+#include "core/or/or_circuit_st.h"
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
#include <event2/event.h>
#include <event2/dns.h>
@@ -2132,4 +2141,3 @@ dns_insert_cache_entry(cached_resolve_t *new_entry)
{
HT_INSERT(cache_map, &cache_root, new_entry);
}
-
diff --git a/src/or/dns.h b/src/feature/relay/dns.h
index 28d9f947b4..69c1764b73 100644
--- a/src/or/dns.h
+++ b/src/feature/relay/dns.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -41,7 +41,7 @@ void dns_reset_correctness_checks(void);
void dump_dns_mem_usage(int severity);
#ifdef DNS_PRIVATE
-#include "dns_structs.h"
+#include "feature/relay/dns_structs.h"
MOCK_DECL(STATIC int,dns_resolve_impl,(edge_connection_t *exitconn,
int is_resolve,or_circuit_t *oncirc, char **hostname_out,
diff --git a/src/or/dns_structs.h b/src/feature/relay/dns_structs.h
index e22f23ac15..28c48ca0bc 100644
--- a/src/or/dns_structs.h
+++ b/src/feature/relay/dns_structs.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/or/ext_orport.c b/src/feature/relay/ext_orport.c
index b842442caf..7de57ac65d 100644
--- a/src/or/ext_orport.c
+++ b/src/feature/relay/ext_orport.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,17 +17,18 @@
*/
#define EXT_ORPORT_PRIVATE
-#include "or.h"
-#include "connection.h"
-#include "connection_or.h"
-#include "control.h"
-#include "config.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "ext_orport.h"
-#include "main.h"
-#include "proto_ext_or.h"
-#include "util.h"
+#include "core/or/or.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_or.h"
+#include "feature/control/control.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/relay/ext_orport.h"
+#include "core/mainloop/main.h"
+#include "core/proto/proto_ext_or.h"
+
+#include "core/or/or_connection_st.h"
/** Allocate and return a structure capable of holding an Extended
* ORPort message of body length <b>len</b>. */
diff --git a/src/or/ext_orport.h b/src/feature/relay/ext_orport.h
index 09acbc407e..7eebfdb25b 100644
--- a/src/or/ext_orport.h
+++ b/src/feature/relay/ext_orport.h
@@ -1,12 +1,31 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef EXT_ORPORT_H
#define EXT_ORPORT_H
+/** States of the Extended ORPort protocol. Be careful before changing
+ * the numbers: they matter. */
+#define EXT_OR_CONN_STATE_MIN_ 1
+/** Extended ORPort authentication is waiting for the authentication
+ * type selected by the client. */
+#define EXT_OR_CONN_STATE_AUTH_WAIT_AUTH_TYPE 1
+/** Extended ORPort authentication is waiting for the client nonce. */
+#define EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE 2
+/** Extended ORPort authentication is waiting for the client hash. */
+#define EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_HASH 3
+#define EXT_OR_CONN_STATE_AUTH_MAX 3
+/** Authentication finished and the Extended ORPort is now accepting
+ * traffic. */
+#define EXT_OR_CONN_STATE_OPEN 4
+/** Extended ORPort is flushing its last messages and preparing to
+ * start accepting OR connections. */
+#define EXT_OR_CONN_STATE_FLUSHING 5
+#define EXT_OR_CONN_STATE_MAX_ 5
+
int connection_ext_or_start_auth(or_connection_t *or_conn);
ext_or_cmd_t *ext_or_cmd_new(uint16_t len);
@@ -43,4 +62,3 @@ extern int ext_or_auth_cookie_is_set;
#endif /* defined(EXT_ORPORT_PRIVATE) */
#endif /* !defined(EXT_ORPORT_H) */
-
diff --git a/src/or/router.c b/src/feature/relay/router.c
index 5485ec913e..973d3e1100 100644
--- a/src/or/router.c
+++ b/src/feature/relay/router.c
@@ -1,43 +1,60 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTER_PRIVATE
-#include "or.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "config.h"
-#include "connection.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "crypto_curve25519.h"
-#include "directory.h"
-#include "dirserv.h"
-#include "dns.h"
-#include "geoip.h"
-#include "hibernate.h"
-#include "main.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "policies.h"
-#include "protover.h"
-#include "relay.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerkeys.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "statefile.h"
-#include "torcert.h"
-#include "transports.h"
-#include "routerset.h"
-
-#include "dirauth/mode.h"
+#include "core/or/or.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "feature/dircache/directory.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/relay/dns.h"
+#include "feature/stats/geoip.h"
+#include "feature/hibernate/hibernate.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "core/or/protover.h"
+#include "core/or/relay.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routerkeys.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "app/config/statefile.h"
+#include "feature/nodelist/torcert.h"
+#include "feature/client/transports.h"
+#include "feature/nodelist/routerset.h"
+
+#include "feature/dirauth/mode.h"
+
+#include "feature/nodelist/authority_cert_st.h"
+#include "core/or/crypt_path_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "feature/dirclient/dir_server_st.h"
+#include "core/or/extend_info_st.h"
+#include "feature/nodelist/extrainfo_st.h"
+#include "feature/nodelist/node_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "app/config/or_state_st.h"
+#include "core/or/port_cfg_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+
+#include "lib/osinfo/uname.h"
+#include "lib/tls/tortls.h"
+#include "lib/encoding/confline.h"
+#include "lib/crypt_ops/crypto_format.h"
/**
* \file router.c
@@ -1342,10 +1359,10 @@ router_should_be_dirserver(const or_options_t *options, int dir_port)
interval_length = 1;
}
log_info(LD_GENERAL, "Calculating whether to advertise %s: effective "
- "bwrate: %u, AccountingMax: "U64_FORMAT", "
+ "bwrate: %u, AccountingMax: %"PRIu64", "
"accounting interval length %d",
dir_port ? "dirport" : "begindir",
- effective_bw, U64_PRINTF_ARG(options->AccountingMax),
+ effective_bw, (options->AccountingMax),
interval_length);
acc_bytes = options->AccountingMax;
diff --git a/src/or/router.h b/src/feature/relay/router.h
index 752f2f2dbe..51ac365798 100644
--- a/src/or/router.h
+++ b/src/feature/relay/router.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,10 @@
#ifndef TOR_ROUTER_H
#define TOR_ROUTER_H
-#include "testsupport.h"
+#include "lib/testsupport/testsupport.h"
+
+struct curve25519_keypair_t;
+struct ed25519_keypair_t;
#define TOR_ROUTERINFO_ERROR_NO_EXT_ADDR (-1)
#define TOR_ROUTERINFO_ERROR_CANNOT_PARSE (-2)
@@ -107,10 +110,10 @@ MOCK_DECL(int,router_pick_published_address,(const or_options_t *options,
int router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e);
int 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,
- const curve25519_keypair_t *ntor_keypair,
- const ed25519_keypair_t *signing_keypair);
+ const crypto_pk_t *ident_key,
+ const crypto_pk_t *tap_key,
+ const struct curve25519_keypair_t *ntor_keypair,
+ const struct ed25519_keypair_t *signing_keypair);
char *router_dump_exit_policy_to_string(const routerinfo_t *router,
int include_ipv4,
int include_ipv6);
@@ -126,7 +129,7 @@ int router_has_orport(const routerinfo_t *router,
const tor_addr_port_t *orport);
int extrainfo_dump_to_string(char **s, extrainfo_t *extrainfo,
crypto_pk_t *ident_key,
- const ed25519_keypair_t *signing_keypair);
+ const struct ed25519_keypair_t *signing_keypair);
int is_legal_nickname(const char *s);
int is_legal_nickname_or_hexdigest(const char *s);
int is_legal_hexdigest(const char *s);
@@ -156,4 +159,3 @@ STATIC int router_write_fingerprint(int hashed);
#endif
#endif /* !defined(TOR_ROUTER_H) */
-
diff --git a/src/or/routerkeys.c b/src/feature/relay/routerkeys.c
index 43460da8cc..f12eb3d332 100644
--- a/src/or/routerkeys.c
+++ b/src/feature/relay/routerkeys.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,17 +14,25 @@
* (TODO: The keys in router.c should go here too.)
*/
-#include "or.h"
-#include "config.h"
-#include "crypto_util.h"
-#include "router.h"
-#include "crypto_pwbox.h"
-#include "routerkeys.h"
-#include "torcert.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routerkeys.h"
+#include "feature/nodelist/torcert.h"
+
+#include "lib/crypt_ops/crypto_pwbox.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/term/getpass.h"
+#include "lib/tls/tortls.h"
+#include "lib/crypt_ops/crypto_format.h"
#define ENC_KEY_HEADER "Boxed Ed25519 key"
#define ENC_KEY_TAG "master"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
/* DOCDOC */
static ssize_t
do_getpass(const char *prompt, char *buf, size_t buflen,
@@ -44,7 +52,7 @@ do_getpass(const char *prompt, char *buf, size_t buflen,
if (options->use_keygen_passphrase_fd) {
twice = 0;
fd = options->keygen_passphrase_fd;
- length = read_all(fd, buf, buflen-1, 0);
+ length = read_all_from_fd(fd, buf, buflen-1);
if (length >= 0)
buf[length] = 0;
goto done_reading;
@@ -1403,4 +1411,3 @@ routerkeys_free_all(void)
rsa_ed_crosscert = NULL; // redundant
rsa_ed_crosscert_len = 0;
}
-
diff --git a/src/or/routerkeys.h b/src/feature/relay/routerkeys.h
index 3e67952ea0..a6f06f6e20 100644
--- a/src/or/routerkeys.h
+++ b/src/feature/relay/routerkeys.h
@@ -1,10 +1,10 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_ROUTERKEYS_H
#define TOR_ROUTERKEYS_H
-#include "crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
#define INIT_ED_KEY_CREATE (1u<<0)
#define INIT_ED_KEY_REPLACE (1u<<1)
diff --git a/src/feature/rend/rend_authorized_client_st.h b/src/feature/rend/rend_authorized_client_st.h
new file mode 100644
index 0000000000..7ccf9771e1
--- /dev/null
+++ b/src/feature/rend/rend_authorized_client_st.h
@@ -0,0 +1,18 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef REND_AUTHORIZED_CLIENT_ST_H
+#define REND_AUTHORIZED_CLIENT_ST_H
+
+/** Hidden-service side configuration of client authorization. */
+struct rend_authorized_client_t {
+ char *client_name;
+ uint8_t descriptor_cookie[REND_DESC_COOKIE_LEN];
+ crypto_pk_t *client_key;
+};
+
+#endif
+
diff --git a/src/feature/rend/rend_encoded_v2_service_descriptor_st.h b/src/feature/rend/rend_encoded_v2_service_descriptor_st.h
new file mode 100644
index 0000000000..0555ef6728
--- /dev/null
+++ b/src/feature/rend/rend_encoded_v2_service_descriptor_st.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-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef REND_ENCODED_V2_SERVICE_DESCRIPTOR_ST_H
+#define REND_ENCODED_V2_SERVICE_DESCRIPTOR_ST_H
+
+/** ASCII-encoded v2 hidden service descriptor. */
+struct rend_encoded_v2_service_descriptor_t {
+ char desc_id[DIGEST_LEN]; /**< Descriptor ID. */
+ char *desc_str; /**< Descriptor string. */
+};
+
+#endif
+
diff --git a/src/feature/rend/rend_intro_point_st.h b/src/feature/rend/rend_intro_point_st.h
new file mode 100644
index 0000000000..89fe5ef2b3
--- /dev/null
+++ b/src/feature/rend/rend_intro_point_st.h
@@ -0,0 +1,76 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef REND_INTRO_POINT_ST_H
+#define REND_INTRO_POINT_ST_H
+
+struct replaycache_t;
+struct crypto_pk_t;
+
+/** Introduction point information. Used both in rend_service_t (on
+ * the service side) and in rend_service_descriptor_t (on both the
+ * client and service side). */
+struct rend_intro_point_t {
+ extend_info_t *extend_info; /**< Extend info for connecting to this
+ * introduction point via a multi-hop path. */
+ struct crypto_pk_t *intro_key; /**< Introduction key that replaces the
+ * service key, if this descriptor is V2. */
+
+ /** (Client side only) Flag indicating that a timeout has occurred
+ * after sending an INTRODUCE cell to this intro point. After a
+ * timeout, an intro point should not be tried again during the same
+ * hidden service connection attempt, but it may be tried again
+ * during a future connection attempt. */
+ unsigned int timed_out : 1;
+
+ /** (Client side only) The number of times we have failed to build a
+ * circuit to this intro point for some reason other than our
+ * circuit-build timeout. See also MAX_INTRO_POINT_REACHABILITY_FAILURES. */
+ unsigned int unreachable_count : 3;
+
+ /** (Service side only) Flag indicating that this intro point was
+ * included in the last HS descriptor we generated. */
+ unsigned int listed_in_last_desc : 1;
+
+ /** (Service side only) A replay cache recording the RSA-encrypted parts
+ * of INTRODUCE2 cells this intro point's circuit has received. This is
+ * used to prevent replay attacks. */
+ struct replaycache_t *accepted_intro_rsa_parts;
+
+ /** (Service side only) Count of INTRODUCE2 cells accepted from this
+ * intro point.
+ */
+ int accepted_introduce2_count;
+
+ /** (Service side only) Maximum number of INTRODUCE2 cells that this IP
+ * will accept. This is a random value between
+ * INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS and
+ * INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS. */
+ int max_introductions;
+
+ /** (Service side only) The time at which this intro point was first
+ * published, or -1 if this intro point has not yet been
+ * published. */
+ time_t time_published;
+
+ /** (Service side only) The time at which this intro point should
+ * (start to) expire, or -1 if we haven't decided when this intro
+ * point should expire. */
+ time_t time_to_expire;
+
+ /** (Service side only) The amount of circuit creation we've made to this
+ * intro point. This is incremented every time we do a circuit relaunch on
+ * this object which is triggered when the circuit dies but the node is
+ * still in the consensus. After MAX_INTRO_POINT_CIRCUIT_RETRIES, we give
+ * up on it. */
+ unsigned int circuit_retries;
+
+ /** (Service side only) Set if this intro point has an established circuit
+ * and unset if it doesn't. */
+ unsigned int circuit_established:1;
+};
+
+#endif
diff --git a/src/feature/rend/rend_service_descriptor_st.h b/src/feature/rend/rend_service_descriptor_st.h
new file mode 100644
index 0000000000..8ea8a62305
--- /dev/null
+++ b/src/feature/rend/rend_service_descriptor_st.h
@@ -0,0 +1,34 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef REND_SERVICE_DESCRIPTOR_ST_H
+#define REND_SERVICE_DESCRIPTOR_ST_H
+
+#define REND_PROTOCOL_VERSION_BITMASK_WIDTH 16
+
+/** Information used to connect to a hidden service. Used on both the
+ * service side and the client side. */
+struct rend_service_descriptor_t {
+ crypto_pk_t *pk; /**< This service's public key. */
+ int version; /**< Version of the descriptor format: 0 or 2. */
+ time_t timestamp; /**< Time when the descriptor was generated. */
+ /** Bitmask: which introduce/rendezvous protocols are supported?
+ * (We allow bits '0', '1', '2' and '3' to be set.) */
+ unsigned protocols : REND_PROTOCOL_VERSION_BITMASK_WIDTH;
+ /** List of the service's introduction points. Elements are removed if
+ * introduction attempts fail. */
+ smartlist_t *intro_nodes;
+ /** Has descriptor been uploaded to all hidden service directories? */
+ int all_uploads_performed;
+ /** List of hidden service directories to which an upload request for
+ * this descriptor could be sent. Smartlist exists only when at least one
+ * of the previous upload requests failed (otherwise it's not important
+ * to know which uploads succeeded and which not). */
+ smartlist_t *successful_uploads;
+};
+
+#endif
+
diff --git a/src/or/rendcache.c b/src/feature/rend/rendcache.c
index d27e1c293f..7af5063ba5 100644
--- a/src/or/rendcache.c
+++ b/src/feature/rend/rendcache.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Tor Project, Inc. */
+/* Copyright (c) 2015-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -7,13 +7,17 @@
**/
#define RENDCACHE_PRIVATE
-#include "rendcache.h"
+#include "feature/rend/rendcache.h"
-#include "config.h"
-#include "rephist.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "rendcommon.h"
+#include "app/config/config.h"
+#include "feature/stats/rephist.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/rend/rendcommon.h"
+
+#include "core/or/extend_info_st.h"
+#include "feature/rend/rend_intro_point_st.h"
+#include "feature/rend/rend_service_descriptor_st.h"
/** Map from service id (as generated by rend_get_service_id) to
* rend_cache_entry_t. */
@@ -908,9 +912,7 @@ rend_cache_store_v2_desc_as_client(const char *desc,
if (n_intro_points <= 0) {
log_warn(LD_REND, "Failed to parse introduction points. Either the "
"service has published a corrupt descriptor or you have "
- "provided invalid authorization data, or (maybe!) the "
- "server is deliberately serving broken data in an attempt "
- "to crash you with bug 21018.");
+ "provided invalid authorization data.");
goto err;
} else if (n_intro_points > MAX_INTRO_POINTS) {
log_warn(LD_REND, "Found too many introduction points on a hidden "
diff --git a/src/or/rendcache.h b/src/feature/rend/rendcache.h
index 8b6fd5b671..455e51645c 100644
--- a/src/or/rendcache.h
+++ b/src/feature/rend/rendcache.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Tor Project, Inc. */
+/* Copyright (c) 2015-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,8 +9,8 @@
#ifndef TOR_RENDCACHE_H
#define TOR_RENDCACHE_H
-#include "or.h"
-#include "rendcommon.h"
+#include "core/or/or.h"
+#include "feature/rend/rendcommon.h"
/** How old do we let hidden service descriptors get before discarding
* them as too old? */
diff --git a/src/or/rendclient.c b/src/feature/rend/rendclient.c
index 7ef12a4faf..9f62156eb9 100644
--- a/src/or/rendclient.c
+++ b/src/feature/rend/rendclient.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -7,31 +7,43 @@
* \brief Client code to access location-hidden services.
**/
-#include "or.h"
-#include "circpathbias.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "config.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "directory.h"
-#include "hs_circuit.h"
-#include "hs_client.h"
-#include "hs_common.h"
-#include "main.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "relay.h"
-#include "rendclient.h"
-#include "rendcommon.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerlist.h"
-#include "routerset.h"
+#include "core/or/or.h"
+#include "feature/client/circpathbias.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/dircache/directory.h"
+#include "feature/hs/hs_circuit.h"
+#include "feature/hs/hs_client.h"
+#include "feature/hs/hs_common.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/relay.h"
+#include "feature/rend/rendclient.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerset.h"
+#include "lib/encoding/confline.h"
+
+#include "core/or/cpath_build_state_st.h"
+#include "core/or/crypt_path_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "core/or/entry_connection_st.h"
+#include "core/or/extend_info_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "feature/rend/rend_intro_point_st.h"
+#include "feature/rend/rend_service_descriptor_st.h"
+#include "feature/nodelist/routerstatus_st.h"
static extend_info_t *rend_client_get_random_intro_impl(
const rend_cache_entry_t *rend_query,
@@ -248,7 +260,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
}
if (crypto_dh_get_public(cpath->rend_dh_handshake_state, tmp+dh_offset,
- DH_KEY_LEN)<0) {
+ DH1024_KEY_LEN)<0) {
log_warn(LD_BUG, "Internal error: couldn't extract g^x.");
status = -2;
goto perm_err;
@@ -259,7 +271,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
r = crypto_pk_obsolete_public_hybrid_encrypt(intro_key, payload+DIGEST_LEN,
sizeof(payload)-DIGEST_LEN,
tmp,
- (int)(dh_offset+DH_KEY_LEN),
+ (int)(dh_offset+DH1024_KEY_LEN),
PK_PKCS1_OAEP_PADDING, 0);
if (r<0) {
log_warn(LD_BUG,"Internal error: hybrid pk encrypt failed.");
@@ -864,7 +876,7 @@ int
rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request,
size_t request_len)
{
- if (request_len != DH_KEY_LEN+DIGEST_LEN) {
+ if (request_len != DH1024_KEY_LEN+DIGEST_LEN) {
log_warn(LD_PROTOCOL,"Incorrect length (%d) on RENDEZVOUS2 cell.",
(int)request_len);
goto err;
@@ -1243,4 +1255,3 @@ rend_client_non_anonymous_mode_enabled(const or_options_t *options)
return 0;
#endif /* defined(NON_ANONYMOUS_MODE_ENABLED) */
}
-
diff --git a/src/or/rendclient.h b/src/feature/rend/rendclient.h
index e8495ce09c..e41faa4932 100644
--- a/src/or/rendclient.h
+++ b/src/feature/rend/rendclient.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,7 @@
#ifndef TOR_RENDCLIENT_H
#define TOR_RENDCLIENT_H
-#include "rendcache.h"
+#include "feature/rend/rendcache.h"
void rend_client_purge_state(void);
diff --git a/src/or/rendcommon.c b/src/feature/rend/rendcommon.c
index f3fa2f64d1..5bf9477446 100644
--- a/src/or/rendcommon.c
+++ b/src/feature/rend/rendcommon.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,25 +10,37 @@
#define RENDCOMMON_PRIVATE
-#include "or.h"
-#include "circuitbuild.h"
-#include "circuituse.h"
-#include "config.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "hs_client.h"
-#include "hs_common.h"
-#include "hs_intropoint.h"
-#include "networkstatus.h"
-#include "rendclient.h"
-#include "rendcommon.h"
-#include "rendmid.h"
-#include "rendservice.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerlist.h"
-#include "routerparse.h"
+#include "core/or/or.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "app/config/config.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/hs/hs_client.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_intropoint.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/rend/rendclient.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/rend/rendmid.h"
+#include "feature/rend/rendservice.h"
+#include "feature/stats/rephist.h"
+#include "feature/hs_common/replaycache.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+
+#include "core/or/cpath_build_state_st.h"
+#include "core/or/crypt_path_st.h"
+#include "core/or/extend_info_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "feature/rend/rend_encoded_v2_service_descriptor_st.h"
+#include "feature/rend/rend_intro_point_st.h"
+#include "feature/rend/rend_service_descriptor_st.h"
+#include "feature/nodelist/routerstatus_st.h"
/** Return 0 if one and two are the same service ids, else -1 or 1 */
int
@@ -1042,4 +1054,3 @@ rend_circuit_pk_digest_eq(const origin_circuit_t *ocirc,
match:
return 1;
}
-
diff --git a/src/or/rendcommon.h b/src/feature/rend/rendcommon.h
index 1ed0f62609..4ea35f88c2 100644
--- a/src/or/rendcommon.h
+++ b/src/feature/rend/rendcommon.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/or/rendmid.c b/src/feature/rend/rendmid.c
index c4a34ca62c..22cd6c3435 100644
--- a/src/or/rendmid.c
+++ b/src/feature/rend/rendmid.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -7,18 +7,20 @@
* \brief Implement introductions points and rendezvous points.
**/
-#include "or.h"
-#include "channel.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "config.h"
-#include "crypto.h"
-#include "dos.h"
-#include "relay.h"
-#include "rendmid.h"
-#include "rephist.h"
-#include "hs_circuitmap.h"
-#include "hs_intropoint.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto.h"
+#include "core/or/dos.h"
+#include "core/or/relay.h"
+#include "feature/rend/rendmid.h"
+#include "feature/stats/rephist.h"
+#include "feature/hs/hs_circuitmap.h"
+#include "feature/hs/hs_intropoint.h"
+
+#include "core/or/or_circuit_st.h"
/** Respond to an ESTABLISH_INTRO cell by checking the signed data and
* setting the circuit's purpose and service pk digest.
@@ -155,7 +157,8 @@ rend_mid_introduce_legacy(or_circuit_t *circ, const uint8_t *request,
* to revise this protocol anyway.
*/
if (request_len < (DIGEST_LEN+(MAX_NICKNAME_LEN+1)+REND_COOKIE_LEN+
- DH_KEY_LEN+CIPHER_KEY_LEN+PKCS1_OAEP_PADDING_OVERHEAD)) {
+ DH1024_KEY_LEN+CIPHER_KEY_LEN+
+ PKCS1_OAEP_PADDING_OVERHEAD)) {
log_warn(LD_PROTOCOL, "Impossibly short INTRODUCE1 cell on circuit %u; "
"responding with nack.",
(unsigned)circ->p_circ_id);
@@ -365,4 +368,3 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
circuit_mark_for_close(TO_CIRCUIT(circ), reason);
return -1;
}
-
diff --git a/src/or/rendmid.h b/src/feature/rend/rendmid.h
index 6cc1fc8d95..907a0c6a73 100644
--- a/src/or/rendmid.h
+++ b/src/feature/rend/rendmid.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/or/rendservice.c b/src/feature/rend/rendservice.c
index 92c323b10d..da4a98b3d1 100644
--- a/src/or/rendservice.c
+++ b/src/feature/rend/rendservice.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,32 +9,57 @@
#define RENDSERVICE_PRIVATE
-#include "or.h"
-#include "circpathbias.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "config.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "directory.h"
-#include "hs_common.h"
-#include "hs_config.h"
-#include "main.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "policies.h"
-#include "rendclient.h"
-#include "rendcommon.h"
-#include "rendservice.h"
-#include "router.h"
-#include "relay.h"
-#include "rephist.h"
-#include "replaycache.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "routerset.h"
+#include "core/or/or.h"
+#include "feature/client/circpathbias.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "app/config/config.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/dircache/directory.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_config.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "feature/rend/rendclient.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/rend/rendservice.h"
+#include "feature/relay/router.h"
+#include "core/or/relay.h"
+#include "feature/stats/rephist.h"
+#include "feature/hs_common/replaycache.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/routerset.h"
+#include "lib/encoding/confline.h"
+
+#include "core/or/cpath_build_state_st.h"
+#include "core/or/crypt_path_st.h"
+#include "core/or/crypt_path_reference_st.h"
+#include "core/or/edge_connection_st.h"
+#include "core/or/extend_info_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "feature/rend/rend_authorized_client_st.h"
+#include "feature/rend/rend_encoded_v2_service_descriptor_st.h"
+#include "feature/rend/rend_intro_point_st.h"
+#include "feature/rend/rend_service_descriptor_st.h"
+#include "feature/nodelist/routerstatus_st.h"
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
struct rend_service_t;
static origin_circuit_t *find_intro_circuit(rend_intro_point_t *intro,
@@ -1992,7 +2017,7 @@ rend_service_receive_introduction(origin_circuit_t *circuit,
* part 1. */
replay = replaycache_add_test_and_elapsed(
service->accepted_intro_dh_parts,
- parsed_req->dh, DH_KEY_LEN,
+ parsed_req->dh, DH1024_KEY_LEN,
&elapsed);
if (replay) {
@@ -2042,7 +2067,7 @@ rend_service_receive_introduction(origin_circuit_t *circuit,
}
if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh,
(char *)(parsed_req->dh),
- DH_KEY_LEN, keys,
+ DH1024_KEY_LEN, keys,
DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) {
log_warn(LD_BUG, "Internal error: couldn't complete DH handshake");
reason = END_CIRC_REASON_INTERNAL;
@@ -2323,7 +2348,7 @@ rend_service_begin_parse_intro(const uint8_t *request,
/* min key length plus digest length plus nickname length */
if (request_len <
(DIGEST_LEN + REND_COOKIE_LEN + (MAX_NICKNAME_LEN + 1) +
- DH_KEY_LEN + 42)) {
+ DH1024_KEY_LEN + 42)) {
if (err_msg_out) {
tor_asprintf(&err_msg,
"got a truncated INTRODUCE%d cell",
@@ -2859,14 +2884,14 @@ rend_service_parse_intro_plaintext(
*/
ver_invariant_len = intro->plaintext_len - ver_specific_len;
- if (ver_invariant_len < REND_COOKIE_LEN + DH_KEY_LEN) {
+ if (ver_invariant_len < REND_COOKIE_LEN + DH1024_KEY_LEN) {
tor_asprintf(&err_msg,
"decrypted plaintext of INTRODUCE%d cell was truncated (%ld bytes)",
(int)(intro->type),
(long)(intro->plaintext_len));
status = -5;
goto err;
- } else if (ver_invariant_len > REND_COOKIE_LEN + DH_KEY_LEN) {
+ } else if (ver_invariant_len > REND_COOKIE_LEN + DH1024_KEY_LEN) {
tor_asprintf(&err_msg,
"decrypted plaintext of INTRODUCE%d cell was too long (%ld bytes)",
(int)(intro->type),
@@ -2879,7 +2904,7 @@ rend_service_parse_intro_plaintext(
REND_COOKIE_LEN);
memcpy(intro->dh,
intro->plaintext + ver_specific_len + REND_COOKIE_LEN,
- DH_KEY_LEN);
+ DH1024_KEY_LEN);
}
/* Flag it as being fully parsed */
@@ -3436,12 +3461,12 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
/* All we need to do is send a RELAY_RENDEZVOUS1 cell... */
memcpy(buf, rend_cookie, REND_COOKIE_LEN);
if (crypto_dh_get_public(hop->rend_dh_handshake_state,
- buf+REND_COOKIE_LEN, DH_KEY_LEN)<0) {
+ buf+REND_COOKIE_LEN, DH1024_KEY_LEN)<0) {
log_warn(LD_GENERAL,"Couldn't get DH public key.");
reason = END_CIRC_REASON_INTERNAL;
goto err;
}
- memcpy(buf+REND_COOKIE_LEN+DH_KEY_LEN, hop->rend_circ_nonce,
+ memcpy(buf+REND_COOKIE_LEN+DH1024_KEY_LEN, hop->rend_circ_nonce,
DIGEST_LEN);
/* Send the cell */
@@ -4424,4 +4449,3 @@ set_rend_rend_service_staging_list(smartlist_t *new_list)
}
#endif /* defined(TOR_UNIT_TESTS) */
-
diff --git a/src/or/rendservice.h b/src/feature/rend/rendservice.h
index cc872ab575..7096789629 100644
--- a/src/or/rendservice.h
+++ b/src/feature/rend/rendservice.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,14 +12,15 @@
#ifndef TOR_RENDSERVICE_H
#define TOR_RENDSERVICE_H
-#include "or.h"
-#include "hs_service.h"
+#include "core/or/or.h"
+#include "feature/hs/hs_service.h"
-typedef struct rend_intro_cell_s rend_intro_cell_t;
+typedef struct rend_intro_cell_t rend_intro_cell_t;
+struct config_line_t;
/* This can be used for both INTRODUCE1 and INTRODUCE2 */
-struct rend_intro_cell_s {
+struct rend_intro_cell_t {
/* Is this an INTRODUCE1 or INTRODUCE2? (set to 1 or 2) */
uint8_t type;
/* Public key digest */
@@ -58,7 +59,7 @@ struct rend_intro_cell_s {
/* Rendezvous cookie */
uint8_t rc[REND_COOKIE_LEN];
/* Diffie-Hellman data */
- uint8_t dh[DH_KEY_LEN];
+ uint8_t dh[DH1024_KEY_LEN];
};
#ifdef RENDSERVICE_PRIVATE
@@ -138,7 +139,7 @@ STATIC void rend_service_prune_list_impl_(void);
#endif /* defined(RENDSERVICE_PRIVATE) */
int rend_num_services(void);
-int rend_config_service(const config_line_t *line_,
+int rend_config_service(const struct config_line_t *line_,
const or_options_t *options,
hs_service_config_t *config);
void rend_service_prune_list(void);
@@ -218,4 +219,3 @@ int rend_service_reveal_startup_time(const or_options_t *options);
int rend_service_non_anonymous_mode_enabled(const or_options_t *options);
#endif /* !defined(TOR_RENDSERVICE_H) */
-
diff --git a/src/or/geoip.c b/src/feature/stats/geoip.c
index d59043a7f6..d891bd80e2 100644
--- a/src/or/geoip.c
+++ b/src/feature/stats/geoip.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2017, The Tor Project, Inc. */
+/* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -28,15 +28,18 @@
*/
#define GEOIP_PRIVATE
-#include "or.h"
+#include "core/or/or.h"
#include "ht.h"
-#include "buffers.h"
-#include "config.h"
-#include "control.h"
-#include "dnsserv.h"
-#include "dos.h"
-#include "geoip.h"
-#include "routerlist.h"
+#include "lib/container/buffers.h"
+#include "app/config/config.h"
+#include "feature/control/control.h"
+#include "feature/client/dnsserv.h"
+#include "core/or/dos.h"
+#include "feature/stats/geoip.h"
+#include "feature/nodelist/routerlist.h"
+
+#include "lib/container/order.h"
+#include "lib/time/tvdiff.h"
static void init_geoip_countries(void);
@@ -1037,12 +1040,12 @@ geoip_get_transport_history(void)
void *transport_count_ptr = strmap_get(transport_counts, transport_name);
uintptr_t transport_count = (uintptr_t) transport_count_ptr;
- log_debug(LD_GENERAL, "We got "U64_FORMAT" clients with transport '%s'.",
- U64_PRINTF_ARG((uint64_t)transport_count), transport_name);
+ log_debug(LD_GENERAL, "We got %"PRIu64" clients with transport '%s'.",
+ ((uint64_t)transport_count), transport_name);
- smartlist_add_asprintf(string_chunks, "%s="U64_FORMAT,
+ smartlist_add_asprintf(string_chunks, "%s=%"PRIu64,
transport_name,
- U64_PRINTF_ARG(round_uint64_to_next_multiple_of(
+ (round_uint64_to_next_multiple_of(
(uint64_t)transport_count,
granularity)));
} SMARTLIST_FOREACH_END(transport_name);
@@ -1884,4 +1887,3 @@ geoip_free_all(void)
memset(geoip_digest, 0, sizeof(geoip_digest));
memset(geoip6_digest, 0, sizeof(geoip6_digest));
}
-
diff --git a/src/or/geoip.h b/src/feature/stats/geoip.h
index 753bdbf82a..a2175c01e5 100644
--- a/src/or/geoip.h
+++ b/src/feature/stats/geoip.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,8 +12,66 @@
#ifndef TOR_GEOIP_H
#define TOR_GEOIP_H
-#include "testsupport.h"
-#include "dos.h"
+#include "lib/testsupport/testsupport.h"
+#include "core/or/dos.h"
+
+/** Indicates an action that we might be noting geoip statistics on.
+ * Note that if we're noticing CONNECT, we're a bridge, and if we're noticing
+ * the others, we're not.
+ */
+typedef enum {
+ /** We've noticed a connection as a bridge relay or entry guard. */
+ GEOIP_CLIENT_CONNECT = 0,
+ /** We've served a networkstatus consensus as a directory server. */
+ GEOIP_CLIENT_NETWORKSTATUS = 1,
+} geoip_client_action_t;
+/** Indicates either a positive reply or a reason for rejectng a network
+ * status request that will be included in geoip statistics. */
+typedef enum {
+ /** Request is answered successfully. */
+ GEOIP_SUCCESS = 0,
+ /** V3 network status is not signed by a sufficient number of requested
+ * authorities. */
+ GEOIP_REJECT_NOT_ENOUGH_SIGS = 1,
+ /** Requested network status object is unavailable. */
+ GEOIP_REJECT_UNAVAILABLE = 2,
+ /** Requested network status not found. */
+ GEOIP_REJECT_NOT_FOUND = 3,
+ /** Network status has not been modified since If-Modified-Since time. */
+ GEOIP_REJECT_NOT_MODIFIED = 4,
+ /** Directory is busy. */
+ GEOIP_REJECT_BUSY = 5,
+} geoip_ns_response_t;
+#define GEOIP_NS_RESPONSE_NUM 6
+
+/** Directory requests that we are measuring can be either direct or
+ * tunneled. */
+typedef enum {
+ DIRREQ_DIRECT = 0,
+ DIRREQ_TUNNELED = 1,
+} dirreq_type_t;
+
+/** Possible states for either direct or tunneled directory requests that
+ * are relevant for determining network status download times. */
+typedef enum {
+ /** Found that the client requests a network status; applies to both
+ * direct and tunneled requests; initial state of a request that we are
+ * measuring. */
+ DIRREQ_IS_FOR_NETWORK_STATUS = 0,
+ /** Finished writing a network status to the directory connection;
+ * applies to both direct and tunneled requests; completes a direct
+ * request. */
+ DIRREQ_FLUSHING_DIR_CONN_FINISHED = 1,
+ /** END cell sent to circuit that initiated a tunneled request. */
+ DIRREQ_END_CELL_SENT = 2,
+ /** Flushed last cell from queue of the circuit that initiated a
+ * tunneled request to the outbuf of the OR connection. */
+ DIRREQ_CIRC_QUEUE_FLUSHED = 3,
+ /** Flushed last byte from buffer of the channel belonging to the
+ * circuit that initiated a tunneled request; completes a tunneled
+ * request. */
+ DIRREQ_CHANNEL_BUFFER_FLUSHED = 4
+} dirreq_state_t;
#ifdef GEOIP_PRIVATE
STATIC int geoip_parse_entry(const char *line, sa_family_t family);
@@ -97,4 +155,3 @@ char *geoip_get_bridge_stats_controller(time_t);
char *format_client_stats_heartbeat(time_t now);
#endif /* !defined(TOR_GEOIP_H) */
-
diff --git a/src/or/rephist.c b/src/feature/stats/rephist.c
index c7117bad63..6bb680c5dc 100644
--- a/src/or/rephist.c
+++ b/src/feature/stats/rephist.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -74,20 +74,33 @@
* (The "rephist" name originally stood for "reputation and history". )
**/
-#include "or.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "config.h"
-#include "crypto_rand.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "rephist.h"
-#include "router.h"
-#include "routerlist.h"
+#include "core/or/or.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
#include "ht.h"
-#include "channelpadding.h"
-#include "connection_or.h"
-#include "statefile.h"
+#include "core/or/channelpadding.h"
+#include "core/or/connection_or.h"
+#include "app/config/statefile.h"
+
+#include "feature/nodelist/networkstatus_st.h"
+#include "core/or/or_circuit_st.h"
+#include "app/config/or_state_st.h"
+
+#include "lib/container/bloomfilt.h"
+#include "lib/container/order.h"
+#include "lib/math/fp.h"
+#include "lib/math/laplace.h"
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
static void bw_arrays_init(void);
static void predicted_ports_alloc(void);
@@ -1210,9 +1223,9 @@ rep_hist_bandwidth_assess(void)
r = find_largest_max(read_array);
w = find_largest_max(write_array);
if (r>w)
- return (int)(U64_TO_DBL(w)/NUM_SECS_ROLLING_MEASURE);
+ return (int)(((double)w)/NUM_SECS_ROLLING_MEASURE);
else
- return (int)(U64_TO_DBL(r)/NUM_SECS_ROLLING_MEASURE);
+ return (int)(((double)r)/NUM_SECS_ROLLING_MEASURE);
}
/** Print the bandwidth history of b (either [dir-]read_array or
@@ -1258,9 +1271,9 @@ rep_hist_fill_bandwidth_history(char *buf, size_t len, const bw_array_t *b)
total = cutoff;
if (n==(b->num_maxes_set-1))
- tor_snprintf(cp, len-(cp-buf), U64_FORMAT, U64_PRINTF_ARG(total));
+ tor_snprintf(cp, len-(cp-buf), "%"PRIu64, (total));
else
- tor_snprintf(cp, len-(cp-buf), U64_FORMAT",", U64_PRINTF_ARG(total));
+ tor_snprintf(cp, len-(cp-buf), "%"PRIu64",", (total));
cp += strlen(cp);
}
return cp-buf;
@@ -1372,17 +1385,17 @@ rep_hist_update_bwhist_state_section(or_state_t *state,
for (j=0; j < b->num_maxes_set; ++j,++i) {
if (i >= NUM_TOTALS)
i = 0;
- smartlist_add_asprintf(*s_values, U64_FORMAT,
- U64_PRINTF_ARG(b->totals[i] & ~0x3ff));
+ smartlist_add_asprintf(*s_values, "%"PRIu64,
+ (b->totals[i] & ~0x3ff));
maxval = b->maxima[i] / NUM_SECS_ROLLING_MEASURE;
- smartlist_add_asprintf(*s_maxima, U64_FORMAT,
- U64_PRINTF_ARG(maxval & ~0x3ff));
+ smartlist_add_asprintf(*s_maxima, "%"PRIu64,
+ (maxval & ~0x3ff));
}
- smartlist_add_asprintf(*s_values, U64_FORMAT,
- U64_PRINTF_ARG(b->total_in_period & ~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, U64_FORMAT,
- U64_PRINTF_ARG(maxval & ~0x3ff));
+ smartlist_add_asprintf(*s_maxima, "%"PRIu64,
+ (maxval & ~0x3ff));
}
/** Update <b>state</b> with the newest bandwidth history. Done before
@@ -1956,8 +1969,8 @@ rep_hist_format_exit_stats(time_t now)
exit_bytes_written[cur_port],
EXIT_STATS_ROUND_UP_BYTES);
num /= 1024;
- smartlist_add_asprintf(written_strings, "%d="U64_FORMAT,
- cur_port, U64_PRINTF_ARG(num));
+ smartlist_add_asprintf(written_strings, "%d=%"PRIu64,
+ cur_port, (num));
other_written -= exit_bytes_written[cur_port];
}
if (exit_bytes_read[cur_port] > 0) {
@@ -1965,8 +1978,8 @@ rep_hist_format_exit_stats(time_t now)
exit_bytes_read[cur_port],
EXIT_STATS_ROUND_UP_BYTES);
num /= 1024;
- smartlist_add_asprintf(read_strings, "%d="U64_FORMAT,
- cur_port, U64_PRINTF_ARG(num));
+ smartlist_add_asprintf(read_strings, "%d=%"PRIu64,
+ cur_port, (num));
other_read -= exit_bytes_read[cur_port];
}
if (exit_streams[cur_port] > 0) {
@@ -1982,13 +1995,13 @@ rep_hist_format_exit_stats(time_t now)
other_written = round_uint64_to_next_multiple_of(other_written,
EXIT_STATS_ROUND_UP_BYTES);
other_written /= 1024;
- smartlist_add_asprintf(written_strings, "other="U64_FORMAT,
- U64_PRINTF_ARG(other_written));
+ smartlist_add_asprintf(written_strings, "other=%"PRIu64,
+ (other_written));
other_read = round_uint64_to_next_multiple_of(other_read,
EXIT_STATS_ROUND_UP_BYTES);
other_read /= 1024;
- smartlist_add_asprintf(read_strings, "other="U64_FORMAT,
- U64_PRINTF_ARG(other_read));
+ smartlist_add_asprintf(read_strings, "other=%"PRIu64,
+ (other_read));
other_streams = round_uint32_to_next_multiple_of(other_streams,
EXIT_STATS_ROUND_UP_STREAMS);
smartlist_add_asprintf(streams_strings, "other=%u", other_streams);
@@ -2248,8 +2261,8 @@ rep_hist_format_buffer_stats(time_t now)
time_in_queue_strings = smartlist_new();
for (i = 0; i < SHARES; i++) {
smartlist_add_asprintf(processed_cells_strings,
- U64_FORMAT, !circs_in_share[i] ? 0 :
- U64_PRINTF_ARG(processed_cells[i] /
+ "%"PRIu64, !circs_in_share[i] ? 0 :
+ (processed_cells[i] /
circs_in_share[i]));
}
for (i = 0; i < SHARES; i++) {
@@ -2916,14 +2929,14 @@ rep_hist_format_hs_stats(time_t now)
format_iso_time(t, now);
tor_asprintf(&hs_stats_string, "hidserv-stats-end %s (%d s)\n"
- "hidserv-rend-relayed-cells "I64_FORMAT" delta_f=%d "
+ "hidserv-rend-relayed-cells %"PRId64" delta_f=%d "
"epsilon=%.2f bin_size=%d\n"
- "hidserv-dir-onions-seen "I64_FORMAT" delta_f=%d "
+ "hidserv-dir-onions-seen %"PRId64" delta_f=%d "
"epsilon=%.2f bin_size=%d\n",
t, (unsigned) (now - start_of_hs_stats_interval),
- I64_PRINTF_ARG(obfuscated_cells_seen), REND_CELLS_DELTA_F,
+ (obfuscated_cells_seen), REND_CELLS_DELTA_F,
REND_CELLS_EPSILON, REND_CELLS_BIN_SIZE,
- I64_PRINTF_ARG(obfuscated_onions_seen),
+ (obfuscated_onions_seen),
ONIONS_SEEN_DELTA_F,
ONIONS_SEEN_EPSILON, ONIONS_SEEN_BIN_SIZE);
@@ -3109,33 +3122,33 @@ rep_hist_get_padding_count_lines(void)
}
tor_asprintf(&result, "padding-counts %s (%d s)"
- " bin-size="U64_FORMAT
- " write-drop="U64_FORMAT
- " write-pad="U64_FORMAT
- " write-total="U64_FORMAT
- " read-drop="U64_FORMAT
- " read-pad="U64_FORMAT
- " read-total="U64_FORMAT
- " enabled-read-pad="U64_FORMAT
- " enabled-read-total="U64_FORMAT
- " enabled-write-pad="U64_FORMAT
- " enabled-write-total="U64_FORMAT
- " max-chanpad-timers="U64_FORMAT
+ " bin-size=%"PRIu64
+ " write-drop=%"PRIu64
+ " write-pad=%"PRIu64
+ " write-total=%"PRIu64
+ " read-drop=%"PRIu64
+ " read-pad=%"PRIu64
+ " read-total=%"PRIu64
+ " enabled-read-pad=%"PRIu64
+ " enabled-read-total=%"PRIu64
+ " enabled-write-pad=%"PRIu64
+ " enabled-write-total=%"PRIu64
+ " max-chanpad-timers=%"PRIu64
"\n",
padding_published.first_published_at,
REPHIST_CELL_PADDING_COUNTS_INTERVAL,
- U64_PRINTF_ARG(ROUND_CELL_COUNTS_TO),
- U64_PRINTF_ARG(padding_published.write_drop_cell_count),
- U64_PRINTF_ARG(padding_published.write_pad_cell_count),
- U64_PRINTF_ARG(padding_published.write_cell_count),
- U64_PRINTF_ARG(padding_published.read_drop_cell_count),
- U64_PRINTF_ARG(padding_published.read_pad_cell_count),
- U64_PRINTF_ARG(padding_published.read_cell_count),
- U64_PRINTF_ARG(padding_published.enabled_read_pad_cell_count),
- U64_PRINTF_ARG(padding_published.enabled_read_cell_count),
- U64_PRINTF_ARG(padding_published.enabled_write_pad_cell_count),
- U64_PRINTF_ARG(padding_published.enabled_write_cell_count),
- U64_PRINTF_ARG(padding_published.maximum_chanpad_timers)
+ (uint64_t)ROUND_CELL_COUNTS_TO,
+ (padding_published.write_drop_cell_count),
+ (padding_published.write_pad_cell_count),
+ (padding_published.write_cell_count),
+ (padding_published.read_drop_cell_count),
+ (padding_published.read_pad_cell_count),
+ (padding_published.read_cell_count),
+ (padding_published.enabled_read_pad_cell_count),
+ (padding_published.enabled_read_cell_count),
+ (padding_published.enabled_write_pad_cell_count),
+ (padding_published.enabled_write_cell_count),
+ (padding_published.maximum_chanpad_timers)
);
return result;
@@ -3149,22 +3162,22 @@ rep_hist_log_link_protocol_counts(void)
{
log_notice(LD_HEARTBEAT,
"Since startup, we have initiated "
- U64_FORMAT" v1 connections, "
- U64_FORMAT" v2 connections, "
- U64_FORMAT" v3 connections, and "
- U64_FORMAT" v4 connections; and received "
- U64_FORMAT" v1 connections, "
- U64_FORMAT" v2 connections, "
- U64_FORMAT" v3 connections, and "
- U64_FORMAT" v4 connections.",
- U64_PRINTF_ARG(link_proto_count[1][1]),
- U64_PRINTF_ARG(link_proto_count[2][1]),
- U64_PRINTF_ARG(link_proto_count[3][1]),
- U64_PRINTF_ARG(link_proto_count[4][1]),
- U64_PRINTF_ARG(link_proto_count[1][0]),
- U64_PRINTF_ARG(link_proto_count[2][0]),
- U64_PRINTF_ARG(link_proto_count[3][0]),
- U64_PRINTF_ARG(link_proto_count[4][0]));
+ "%"PRIu64" v1 connections, "
+ "%"PRIu64" v2 connections, "
+ "%"PRIu64" v3 connections, and "
+ "%"PRIu64" v4 connections; and received "
+ "%"PRIu64" v1 connections, "
+ "%"PRIu64" v2 connections, "
+ "%"PRIu64" v3 connections, and "
+ "%"PRIu64" v4 connections.",
+ (link_proto_count[1][1]),
+ (link_proto_count[2][1]),
+ (link_proto_count[3][1]),
+ (link_proto_count[4][1]),
+ (link_proto_count[1][0]),
+ (link_proto_count[2][0]),
+ (link_proto_count[3][0]),
+ (link_proto_count[4][0]));
}
/** Free all storage held by the OR/link history caches, by the
@@ -3205,4 +3218,3 @@ rep_hist_free_all(void)
tor_assert_nonfatal(rephist_total_alloc == 0);
tor_assert_nonfatal_once(rephist_total_num == 0);
}
-
diff --git a/src/or/rephist.h b/src/feature/stats/rephist.h
index 5072721592..06a5e48211 100644
--- a/src/or/rephist.h
+++ b/src/feature/stats/rephist.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/include.am b/src/include.am
index 90ecf90d45..b5cca7e30a 100644
--- a/src/include.am
+++ b/src/include.am
@@ -1,11 +1,45 @@
include src/ext/include.am
+include src/lib/arch/include.am
+include src/lib/err/include.am
+include src/lib/cc/include.am
+include src/lib/ctime/include.am
+include src/lib/compress/include.am
+include src/lib/container/include.am
+include src/lib/crypt_ops/include.am
+include src/lib/defs/include.am
+include src/lib/encoding/include.am
+include src/lib/evloop/include.am
+include src/lib/fdio/include.am
+include src/lib/fs/include.am
+include src/lib/include.libdonna.am
+include src/lib/intmath/include.am
+include src/lib/lock/include.am
+include src/lib/log/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/net/include.am
+include src/lib/osinfo/include.am
+include src/lib/process/include.am
+include src/lib/sandbox/include.am
+include src/lib/string/include.am
+include src/lib/smartlist_core/include.am
+include src/lib/term/include.am
+include src/lib/testsupport/include.am
+include src/lib/thread/include.am
+include src/lib/time/include.am
+include src/lib/tls/include.am
+include src/lib/trace/include.am
+include src/lib/wallclock/include.am
include src/trunnel/include.am
-include src/common/include.am
-include src/or/include.am
+
+include src/core/include.am
+include src/app/include.am
+
include src/rust/include.am
include src/test/include.am
include src/tools/include.am
include src/win32/include.am
include src/config/include.am
include src/test/fuzz/include.am
-include src/trace/include.am
diff --git a/src/lib/arch/.may_include b/src/lib/arch/.may_include
new file mode 100644
index 0000000000..4285c3dcb8
--- /dev/null
+++ b/src/lib/arch/.may_include
@@ -0,0 +1,2 @@
+orconfig.h
+lib/cc/*.h
diff --git a/src/lib/arch/bytes.h b/src/lib/arch/bytes.h
new file mode 100644
index 0000000000..a2e2224d3c
--- /dev/null
+++ b/src/lib/arch/bytes.h
@@ -0,0 +1,182 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_BYTES_H
+#define TOR_BYTES_H
+
+/**
+ * \file bytes.h
+ *
+ * \brief Inline functions for reading and writing multibyte values from
+ * the middle of strings, and for manipulating byte order.
+ **/
+
+#include <string.h>
+#include "lib/cc/torint.h"
+
+/* The uint8 variants are defined to make the code more uniform. */
+static inline uint8_t
+get_uint8(const void *cp)
+{
+ return *(const uint8_t*)(cp);
+}
+static inline void
+set_uint8(void *cp, uint8_t v)
+{
+ *(uint8_t*)cp = v;
+}
+
+/**
+ * Read a 16-bit value beginning at <b>cp</b>. Equivalent to
+ * *(uint16_t*)(cp), but will not cause segfaults on platforms that forbid
+ * unaligned memory access.
+ */
+static inline uint16_t
+get_uint16(const void *cp)
+{
+ uint16_t v;
+ memcpy(&v,cp,2);
+ return v;
+}
+/**
+ * Read a 32-bit value beginning at <b>cp</b>. Equivalent to
+ * *(uint32_t*)(cp), but will not cause segfaults on platforms that forbid
+ * unaligned memory access.
+ */
+static inline uint32_t
+get_uint32(const void *cp)
+{
+ uint32_t v;
+ memcpy(&v,cp,4);
+ return v;
+}
+/**
+ * Read a 64-bit value beginning at <b>cp</b>. Equivalent to
+ * *(uint64_t*)(cp), but will not cause segfaults on platforms that forbid
+ * unaligned memory access.
+ */
+static inline uint64_t
+get_uint64(const void *cp)
+{
+ uint64_t v;
+ memcpy(&v,cp,8);
+ return v;
+}
+
+/**
+ * Set a 16-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
+ * *(uint16_t*)(cp) = v, but will not cause segfaults on platforms that forbid
+ * unaligned memory access. */
+static inline void
+set_uint16(void *cp, uint16_t v)
+{
+ memcpy(cp,&v,2);
+}
+/**
+ * Set a 32-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
+ * *(uint32_t*)(cp) = v, but will not cause segfaults on platforms that forbid
+ * unaligned memory access. */
+static inline void
+set_uint32(void *cp, uint32_t v)
+{
+ memcpy(cp,&v,4);
+}
+/**
+ * Set a 64-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
+ * *(uint64_t*)(cp) = v, but will not cause segfaults on platforms that forbid
+ * unaligned memory access. */
+static inline void
+set_uint64(void *cp, uint64_t v)
+{
+ memcpy(cp,&v,8);
+}
+
+#ifdef WORDS_BIGENDIAN
+static inline uint16_t
+tor_htons(uint32_t a)
+{
+ return a;
+}
+
+static inline uint16_t
+tor_ntohs(uint64_t a)
+{
+ return a;
+}
+
+static inline uint32_t
+tor_htonl(uint32_t a)
+{
+ return a;
+}
+
+static inline uint32_t
+tor_ntohl(uint64_t a)
+{
+ return a;
+}
+
+static inline uint64_t
+tor_htonll(uint64_t a)
+{
+ return a;
+}
+
+static inline uint64_t
+tor_ntohll(uint64_t a)
+{
+ return a;
+}
+#else
+static inline uint16_t
+tor_htons(uint16_t a)
+{
+ /* Our compilers will indeed recognize this as bswap. */
+ return
+ ((a & 0x00ff) << 8) |
+ ((a & 0xff00) >> 8);
+}
+
+static inline uint16_t
+tor_ntohs(uint16_t a)
+{
+ return tor_htons(a);
+}
+
+static inline uint32_t
+tor_htonl(uint32_t a)
+{
+ /* Our compilers will indeed recognize this as bswap. */
+ return
+ ((a & 0x000000ff) <<24) |
+ ((a & 0x0000ff00) << 8) |
+ ((a & 0x00ff0000) >> 8) |
+ ((a & 0xff000000) >>24);
+}
+
+static inline uint32_t
+tor_ntohl(uint32_t a)
+{
+ return tor_htonl(a);
+}
+
+/** Return a uint64_t value from <b>a</b> in network byte order. */
+static inline uint64_t
+tor_htonll(uint64_t a)
+{
+ /* Little endian. The worst... */
+ return tor_htonl((uint32_t)(a>>32)) |
+ (((uint64_t)tor_htonl((uint32_t)a))<<32);
+}
+
+/** Return a uint64_t value from <b>a</b> in host byte order. */
+static inline uint64_t
+tor_ntohll(uint64_t a)
+{
+ return tor_htonll(a);
+}
+#endif
+
+#endif
diff --git a/src/lib/arch/include.am b/src/lib/arch/include.am
new file mode 100644
index 0000000000..f92ee9222f
--- /dev/null
+++ b/src/lib/arch/include.am
@@ -0,0 +1,3 @@
+
+noinst_HEADERS += \
+ src/lib/arch/bytes.h
diff --git a/src/lib/cc/.may_include b/src/lib/cc/.may_include
new file mode 100644
index 0000000000..2b06e8519c
--- /dev/null
+++ b/src/lib/cc/.may_include
@@ -0,0 +1 @@
+orconfig.h
diff --git a/src/lib/cc/compat_compiler.h b/src/lib/cc/compat_compiler.h
new file mode 100644
index 0000000000..0f1acc381a
--- /dev/null
+++ b/src/lib/cc/compat_compiler.h
@@ -0,0 +1,214 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_COMPAT_COMPILER_H
+#define TOR_COMPAT_COMPILER_H
+
+#include "orconfig.h"
+#include <inttypes.h>
+
+#if defined(__has_feature)
+# if __has_feature(address_sanitizer)
+/* Some of the fancy glibc strcmp() macros include references to memory that
+ * clang rejects because it is off the end of a less-than-3. Clang hates this,
+ * even though those references never actually happen. */
+# undef strcmp
+#endif /* __has_feature(address_sanitizer) */
+#endif /* defined(__has_feature) */
+
+#ifndef NULL_REP_IS_ZERO_BYTES
+#error "It seems your platform does not represent NULL as zero. We can't cope."
+#endif
+
+#ifndef DOUBLE_0_REP_IS_ZERO_BYTES
+#error "It seems your platform does not represent 0.0 as zeros. We can't cope."
+#endif
+
+#if 'a'!=97 || 'z'!=122 || 'A'!=65 || ' '!=32
+#error "It seems that you encode characters in something other than ASCII."
+#endif
+
+/* GCC can check printf and scanf types on arbitrary functions. */
+#ifdef __GNUC__
+#define CHECK_PRINTF(formatIdx, firstArg) \
+ __attribute__ ((format(printf, formatIdx, firstArg)))
+#else
+#define CHECK_PRINTF(formatIdx, firstArg)
+#endif /* defined(__GNUC__) */
+#ifdef __GNUC__
+#define CHECK_SCANF(formatIdx, firstArg) \
+ __attribute__ ((format(scanf, formatIdx, firstArg)))
+#else
+#define CHECK_SCANF(formatIdx, firstArg)
+#endif /* defined(__GNUC__) */
+
+/* What GCC do we have? */
+#ifdef __GNUC__
+#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
+#else
+#define GCC_VERSION 0
+#endif
+
+/* Temporarily enable and disable warnings. */
+#ifdef __GNUC__
+# define PRAGMA_STRINGIFY_(s) #s
+# define PRAGMA_JOIN_STRINGIFY_(a,b) PRAGMA_STRINGIFY_(a ## b)
+/* Support for macro-generated pragmas (c99) */
+# define PRAGMA_(x) _Pragma (#x)
+# ifdef __clang__
+# define PRAGMA_DIAGNOSTIC_(x) PRAGMA_(clang diagnostic x)
+# else
+# define PRAGMA_DIAGNOSTIC_(x) PRAGMA_(GCC diagnostic x)
+# endif
+# if defined(__clang__) || GCC_VERSION >= 406
+/* we have push/pop support */
+# define DISABLE_GCC_WARNING(warningopt) \
+ PRAGMA_DIAGNOSTIC_(push) \
+ PRAGMA_DIAGNOSTIC_(ignored PRAGMA_JOIN_STRINGIFY_(-W,warningopt))
+# define ENABLE_GCC_WARNING(warningopt) \
+ PRAGMA_DIAGNOSTIC_(pop)
+#else /* !(defined(__clang__) || GCC_VERSION >= 406) */
+/* older version of gcc: no push/pop support. */
+# define DISABLE_GCC_WARNING(warningopt) \
+ PRAGMA_DIAGNOSTIC_(ignored PRAGMA_JOIN_STRINGIFY_(-W,warningopt))
+# define ENABLE_GCC_WARNING(warningopt) \
+ PRAGMA_DIAGNOSTIC_(warning PRAGMA_JOIN_STRINGIFY_(-W,warningopt))
+#endif /* defined(__clang__) || GCC_VERSION >= 406 */
+#else /* !(defined(__GNUC__)) */
+/* not gcc at all */
+# define DISABLE_GCC_WARNING(warning)
+# define ENABLE_GCC_WARNING(warning)
+#endif /* defined(__GNUC__) */
+
+/* inline is __inline on windows. */
+#ifdef _WIN32
+#define inline __inline
+#endif
+
+/* Try to get a reasonable __func__ substitute in place. */
+#if defined(_MSC_VER)
+
+#define __func__ __FUNCTION__
+
+#else
+/* For platforms where autoconf works, make sure __func__ is defined
+ * sanely. */
+#ifndef HAVE_MACRO__func__
+#ifdef HAVE_MACRO__FUNCTION__
+#define __func__ __FUNCTION__
+#elif HAVE_MACRO__FUNC__
+#define __func__ __FUNC__
+#else
+#define __func__ "???"
+#endif /* defined(HAVE_MACRO__FUNCTION__) || ... */
+#endif /* !defined(HAVE_MACRO__func__) */
+#endif /* defined(_MSC_VER) */
+
+#ifdef ENUM_VALS_ARE_SIGNED
+#define ENUM_BF(t) unsigned
+#else
+/** Wrapper for having a bitfield of an enumerated type. Where possible, we
+ * just use the enumerated type (so the compiler can help us and notice
+ * problems), but if enumerated types are unsigned, we must use unsigned,
+ * so that the loss of precision doesn't make large values negative. */
+#define ENUM_BF(t) t
+#endif /* defined(ENUM_VALS_ARE_SIGNED) */
+
+/* GCC has several useful attributes. */
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define ATTR_NORETURN __attribute__((noreturn))
+#define ATTR_CONST __attribute__((const))
+#define ATTR_MALLOC __attribute__((malloc))
+#define ATTR_NORETURN __attribute__((noreturn))
+#define ATTR_WUR __attribute__((warn_unused_result))
+#define ATTR_UNUSED __attribute__ ((unused))
+
+/** Macro: Evaluates to <b>exp</b> and hints the compiler that the value
+ * of <b>exp</b> will probably be true.
+ *
+ * In other words, "if (PREDICT_LIKELY(foo))" is the same as "if (foo)",
+ * except that it tells the compiler that the branch will be taken most of the
+ * time. This can generate slightly better code with some CPUs.
+ */
+#define PREDICT_LIKELY(exp) __builtin_expect(!!(exp), 1)
+/** Macro: Evaluates to <b>exp</b> and hints the compiler that the value
+ * of <b>exp</b> will probably be false.
+ *
+ * In other words, "if (PREDICT_UNLIKELY(foo))" is the same as "if (foo)",
+ * except that it tells the compiler that the branch will usually not be
+ * taken. This can generate slightly better code with some CPUs.
+ */
+#define PREDICT_UNLIKELY(exp) __builtin_expect(!!(exp), 0)
+#else /* !(defined(__GNUC__) && __GNUC__ >= 3) */
+#define ATTR_NORETURN
+#define ATTR_CONST
+#define ATTR_MALLOC
+#define ATTR_NORETURN
+#define ATTR_UNUSED
+#define ATTR_WUR
+#define PREDICT_LIKELY(exp) (exp)
+#define PREDICT_UNLIKELY(exp) (exp)
+#endif /* defined(__GNUC__) && __GNUC__ >= 3 */
+
+/** Expands to a syntactically valid empty statement. */
+#define STMT_NIL (void)0
+
+/** Expands to a syntactically valid empty statement, explicitly (void)ing its
+ * argument. */
+#define STMT_VOID(a) while (0) { (void)(a); }
+
+#ifdef __GNUC__
+/** STMT_BEGIN and STMT_END are used to wrap blocks inside macros so that
+ * the macro can be used as if it were a single C statement. */
+#define STMT_BEGIN (void) ({
+#define STMT_END })
+#elif defined(sun) || defined(__sun__)
+#define STMT_BEGIN if (1) {
+#define STMT_END } else STMT_NIL
+#else
+#define STMT_BEGIN do {
+#define STMT_END } while (0)
+#endif /* defined(__GNUC__) || ... */
+
+/* Some tools (like coccinelle) don't like to see operators as macro
+ * arguments. */
+#define OP_LT <
+#define OP_GT >
+#define OP_GE >=
+#define OP_LE <=
+#define OP_EQ ==
+#define OP_NE !=
+
+#if defined(__MINGW32__) || defined(__MINGW64__)
+#define MINGW_ANY
+#endif
+
+/** Macro: yield a pointer to the field at position <b>off</b> within the
+ * structure <b>st</b>. Example:
+ * <pre>
+ * struct a { int foo; int bar; } x;
+ * off_t bar_offset = offsetof(struct a, bar);
+ * int *bar_p = STRUCT_VAR_P(&x, bar_offset);
+ * *bar_p = 3;
+ * </pre>
+ */
+#define STRUCT_VAR_P(st, off) ((void*) ( ((char*)(st)) + (off) ) )
+
+/** Macro: yield a pointer to an enclosing structure given a pointer to
+ * a substructure at offset <b>off</b>. Example:
+ * <pre>
+ * struct base { ... };
+ * struct subtype { int x; struct base b; } x;
+ * struct base *bp = &x.base;
+ * struct *sp = SUBTYPE_P(bp, struct subtype, b);
+ * </pre>
+ */
+#define SUBTYPE_P(p, subtype, basemember) \
+ ((void*) ( ((char*)(p)) - offsetof(subtype, basemember) ))
+
+/** Macro: Yields the number of elements in array x. */
+#define ARRAY_LENGTH(x) ((sizeof(x)) / sizeof(x[0]))
+
+#endif /* !defined(TOR_COMPAT_H) */
diff --git a/src/lib/cc/include.am b/src/lib/cc/include.am
new file mode 100644
index 0000000000..2ae90f97dd
--- /dev/null
+++ b/src/lib/cc/include.am
@@ -0,0 +1,4 @@
+
+noinst_HEADERS += \
+ src/lib/cc/compat_compiler.h \
+ src/lib/cc/torint.h
diff --git a/src/lib/cc/torint.h b/src/lib/cc/torint.h
new file mode 100644
index 0000000000..91db25833b
--- /dev/null
+++ b/src/lib/cc/torint.h
@@ -0,0 +1,123 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file torint.h
+ * \brief Header file to define uint32_t and friends
+ **/
+
+#ifndef TOR_TORINT_H
+#define TOR_TORINT_H
+
+/**
+ * \file torint.h
+ *
+ * \brief Integer definitions used throughout Tor.
+ **/
+
+#include "orconfig.h"
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <limits.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_LIMITS_H
+#include <sys/limits.h>
+#endif
+
+#ifndef SIZE_MAX
+#if SIZEOF_SIZE_T == 8
+#define SIZE_MAX UINT64_MAX
+#elif SIZEOF_SIZE_T == 4
+#define SIZE_MAX UINT32_MAX
+#else
+#error "Can't define SIZE_MAX"
+#endif /* SIZEOF_SIZE_T == 8 || ... */
+#endif /* !defined(SIZE_MAX) */
+
+#ifndef HAVE_SSIZE_T
+#if SIZEOF_SIZE_T == 8
+typedef int64_t ssize_t;
+#elif SIZEOF_SIZE_T == 4
+typedef int32_t ssize_t;
+#else
+#error "Can't define ssize_t."
+#endif /* SIZEOF_SIZE_T == 8 || ... */
+#endif /* !defined(HAVE_SSIZE_T) */
+
+/* This assumes a sane (2's-complement) representation. But if you
+ * aren't 2's complement, and you don't define LONG_MAX, then you're so
+ * bizarre that I want nothing to do with you. */
+#ifndef USING_TWOS_COMPLEMENT
+#error "Seems that your platform doesn't use 2's complement arithmetic. Argh."
+#endif
+
+#ifndef TIME_MAX
+
+#if (SIZEOF_TIME_T == SIZEOF_INT)
+#define TIME_MAX ((time_t)INT_MAX)
+#elif (SIZEOF_TIME_T == SIZEOF_LONG)
+#define TIME_MAX ((time_t)LONG_MAX)
+#elif (SIZEOF_TIME_T == 8)
+#define TIME_MAX ((time_t)INT64_MAX)
+#else
+#error "Can't define TIME_MAX"
+#endif /* (SIZEOF_TIME_T == SIZEOF_INT) || ... */
+
+#endif /* !defined(TIME_MAX) */
+
+#ifndef TIME_MIN
+
+#if (SIZEOF_TIME_T == SIZEOF_INT)
+#define TIME_MIN ((time_t)INT_MIN)
+#elif (SIZEOF_TIME_T == SIZEOF_LONG)
+#define TIME_MIN ((time_t)LONG_MIN)
+#elif (SIZEOF_TIME_T == 8)
+#define TIME_MIN ((time_t)INT64_MIN)
+#else
+#error "Can't define TIME_MIN"
+#endif /* (SIZEOF_TIME_T == SIZEOF_INT) || ... */
+
+#endif /* !defined(TIME_MIN) */
+
+#ifndef SIZE_MAX
+#if (SIZEOF_SIZE_T == 4)
+#define SIZE_MAX UINT32_MAX
+#elif (SIZEOF_SIZE_T == 8)
+#define SIZE_MAX UINT64_MAX
+#else
+#error "Can't define SIZE_MAX"
+#endif /* (SIZEOF_SIZE_T == 4) || ... */
+#endif /* !defined(SIZE_MAX) */
+
+#ifdef _WIN32
+# ifdef _WIN64
+# define TOR_PRIuSZ PRIu64
+# else
+# define TOR_PRIuSZ PRIu32
+# endif
+#else
+# define TOR_PRIuSZ "zu"
+#endif
+
+#ifndef SSIZE_MAX
+#if (SIZEOF_SIZE_T == 4)
+#define SSIZE_MAX INT32_MAX
+#elif (SIZEOF_SIZE_T == 8)
+#define SSIZE_MAX INT64_MAX
+#else
+#error "Can't define SSIZE_MAX"
+#endif /* (SIZEOF_SIZE_T == 4) || ... */
+#endif /* !defined(SSIZE_MAX) */
+
+/** Any ssize_t larger than this amount is likely to be an underflow. */
+#define SSIZE_T_CEILING ((ssize_t)(SSIZE_MAX-16))
+/** Any size_t larger than this amount is likely to be an underflow. */
+#define SIZE_T_CEILING ((size_t)(SSIZE_MAX-16))
+
+#endif /* !defined(TOR_TORINT_H) */
diff --git a/src/lib/compress/.may_include b/src/lib/compress/.may_include
new file mode 100644
index 0000000000..68fe9f1c54
--- /dev/null
+++ b/src/lib/compress/.may_include
@@ -0,0 +1,12 @@
+orconfig.h
+lib/arch/*.h
+lib/cc/*.h
+lib/compress/*.h
+lib/container/*.h
+lib/ctime/*.h
+lib/intmath/*.h
+lib/log/*.h
+lib/malloc/*.h
+lib/string/*.h
+lib/testsupport/*.h
+lib/thread/*.h
diff --git a/src/common/compress.c b/src/lib/compress/compress.c
index cb1549f1aa..e87e788f14 100644
--- a/src/common/compress.c
+++ b/src/lib/compress/compress.c
@@ -1,32 +1,39 @@
/* Copyright (c) 2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file compress.c
- * \brief Common compression API.
+ * \brief Common compression API implementation.
+ *
+ * This file provides a unified interface to all the compression libraries Tor
+ * knows how to use.
**/
#include "orconfig.h"
#include <stdlib.h>
#include <stdio.h>
-#include <assert.h>
#include <string.h>
-#include "torint.h"
+#include "lib/cc/torint.h"
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
-#include "util.h"
-#include "torlog.h"
-#include "compress.h"
-#include "compress_lzma.h"
-#include "compress_none.h"
-#include "compress_zlib.h"
-#include "compress_zstd.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/arch/bytes.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/compress/compress.h"
+#include "lib/compress/compress_lzma.h"
+#include "lib/compress/compress_none.h"
+#include "lib/compress/compress_zlib.h"
+#include "lib/compress/compress_zstd.h"
+#include "lib/intmath/cmp.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/thread/threads.h"
/** Total number of bytes allocated for compression state overhead. */
static atomic_counter_t total_compress_allocation;
@@ -277,7 +284,7 @@ detect_compression_method(const char *in, size_t in_len)
if (in_len > 2 && fast_memeq(in, "\x1f\x8b", 2)) {
return GZIP_METHOD;
} else if (in_len > 2 && (in[0] & 0x0f) == 8 &&
- (ntohs(get_uint16(in)) % 31) == 0) {
+ (tor_ntohs(get_uint16(in)) % 31) == 0) {
return ZLIB_METHOD;
} else if (in_len > 2 &&
fast_memeq(in, "\x5d\x00\x00", 3)) {
@@ -672,4 +679,3 @@ tor_compress_log_init_warnings(void)
{
tor_zstd_warn_if_version_mismatched();
}
-
diff --git a/src/common/compress.h b/src/lib/compress/compress.h
index 65d63a4386..4466e27c4d 100644
--- a/src/common/compress.h
+++ b/src/lib/compress/compress.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -11,11 +11,14 @@
#ifndef TOR_COMPRESS_H
#define TOR_COMPRESS_H
+#include <stddef.h>
+#include "lib/testsupport/testsupport.h"
+
/** Enumeration of what kind of compression to use. Only ZLIB_METHOD and
* GZIP_METHOD is guaranteed to be supported by the compress/uncompress
* functions here. Call tor_compress_supports_method() to check if a given
* compression schema is supported by Tor. */
-typedef enum {
+typedef enum compress_method_t {
NO_METHOD=0, // This method must be first.
GZIP_METHOD=1,
ZLIB_METHOD=2,
@@ -29,7 +32,7 @@ typedef enum {
* BEST_COMPRESSION saves the most bandwidth; LOW_COMPRESSION saves the most
* memory.
**/
-typedef enum {
+typedef enum compression_level_t {
BEST_COMPRESSION, HIGH_COMPRESSION, MEDIUM_COMPRESSION, LOW_COMPRESSION
} compression_level_t;
@@ -89,5 +92,8 @@ size_t tor_compress_state_size(const tor_compress_state_t *state);
void tor_compress_init(void);
void tor_compress_log_init_warnings(void);
-#endif /* !defined(TOR_COMPRESS_H) */
+struct buf_t;
+int buf_add_compress(struct buf_t *buf, struct tor_compress_state_t *state,
+ const char *data, size_t data_len, int done);
+#endif /* !defined(TOR_COMPRESS_H) */
diff --git a/src/lib/compress/compress_buf.c b/src/lib/compress/compress_buf.c
new file mode 100644
index 0000000000..63ee9e0102
--- /dev/null
+++ b/src/lib/compress/compress_buf.c
@@ -0,0 +1,83 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file compress_buf.c
+ *
+ * \brief Working with compressed data in buffers.
+ **/
+
+#define BUFFERS_PRIVATE
+#include "lib/cc/compat_compiler.h"
+#include "lib/container/buffers.h"
+#include "lib/compress/compress.h"
+#include "lib/log/util_bug.h"
+
+#ifdef PARANOIA
+/** Helper: If PARANOIA is defined, assert that the buffer in local variable
+ * <b>buf</b> is well-formed. */
+#define check() STMT_BEGIN buf_assert_ok(buf); STMT_END
+#else
+#define check() STMT_NIL
+#endif /* defined(PARANOIA) */
+
+/** Compress or uncompress the <b>data_len</b> bytes in <b>data</b> using the
+ * compression state <b>state</b>, appending the result to <b>buf</b>. If
+ * <b>done</b> is true, flush the data in the state and finish the
+ * compression/uncompression. Return -1 on failure, 0 on success. */
+int
+buf_add_compress(buf_t *buf, tor_compress_state_t *state,
+ const char *data, size_t data_len,
+ const int done)
+{
+ char *next;
+ size_t old_avail, avail;
+ int over = 0;
+
+ do {
+ int need_new_chunk = 0;
+ if (!buf->tail || ! CHUNK_REMAINING_CAPACITY(buf->tail)) {
+ size_t cap = data_len / 4;
+ buf_add_chunk_with_capacity(buf, cap, 1);
+ }
+ next = CHUNK_WRITE_PTR(buf->tail);
+ avail = old_avail = CHUNK_REMAINING_CAPACITY(buf->tail);
+ switch (tor_compress_process(state, &next, &avail,
+ &data, &data_len, done)) {
+ case TOR_COMPRESS_DONE:
+ over = 1;
+ break;
+ case TOR_COMPRESS_ERROR:
+ return -1;
+ case TOR_COMPRESS_OK:
+ if (data_len == 0) {
+ tor_assert_nonfatal(!done);
+ over = 1;
+ }
+ break;
+ case TOR_COMPRESS_BUFFER_FULL:
+ if (avail) {
+ /* The compression module says we need more room
+ * (TOR_COMPRESS_BUFFER_FULL). Start a new chunk automatically,
+ * whether were going to or not. */
+ need_new_chunk = 1;
+ }
+ if (data_len == 0 && !done) {
+ /* We've consumed all the input data, though, so there's no
+ * point in forging ahead right now. */
+ over = 1;
+ }
+ break;
+ }
+ buf->datalen += old_avail - avail;
+ buf->tail->datalen += old_avail - avail;
+ if (need_new_chunk) {
+ buf_add_chunk_with_capacity(buf, data_len/4, 1);
+ }
+
+ } while (!over);
+ check();
+ return 0;
+}
diff --git a/src/common/compress_lzma.c b/src/lib/compress/compress_lzma.c
index 051c59ba2d..3b6f91b84b 100644
--- a/src/common/compress_lzma.c
+++ b/src/lib/compress/compress_lzma.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,10 +13,12 @@
#include "orconfig.h"
-#include "util.h"
-#include "torlog.h"
-#include "compress.h"
-#include "compress_lzma.h"
+#include "lib/compress/compress.h"
+#include "lib/compress/compress_lzma.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/thread/threads.h"
#ifdef HAVE_LZMA
#include <lzma.h>
@@ -358,4 +360,3 @@ tor_lzma_init(void)
{
atomic_counter_init(&total_lzma_allocation);
}
-
diff --git a/src/common/compress_lzma.h b/src/lib/compress/compress_lzma.h
index 38a447c1f3..9ef3382a25 100644
--- a/src/common/compress_lzma.h
+++ b/src/lib/compress/compress_lzma.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/common/compress_none.c b/src/lib/compress/compress_none.c
index 34314e4af7..9574c47a7e 100644
--- a/src/common/compress_none.c
+++ b/src/lib/compress/compress_none.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,10 +16,12 @@
#include "orconfig.h"
-#include "util.h"
-#include "torlog.h"
-#include "compress.h"
-#include "compress_none.h"
+#include "lib/log/torlog.h"
+#include "lib/compress/compress.h"
+#include "lib/compress/compress_none.h"
+#include "lib/intmath/cmp.h"
+
+#include <string.h>
/** Transfer some bytes using the identity transformation. Read up to
* *<b>in_len</b> bytes from *<b>in</b>, and write up to *<b>out_len</b> bytes
@@ -50,4 +52,3 @@ tor_cnone_compress_process(char **out, size_t *out_len,
return TOR_COMPRESS_BUFFER_FULL;
}
}
-
diff --git a/src/common/compress_none.h b/src/lib/compress/compress_none.h
index 77c3cef47b..5c395bbb30 100644
--- a/src/common/compress_none.h
+++ b/src/lib/compress/compress_none.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/common/compress_zlib.c b/src/lib/compress/compress_zlib.c
index 23d71d27be..12e6727dee 100644
--- a/src/common/compress_zlib.c
+++ b/src/lib/compress/compress_zlib.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,10 +13,11 @@
#include "orconfig.h"
-#include "util.h"
-#include "torlog.h"
-#include "compress.h"
-#include "compress_zlib.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/compress/compress.h"
+#include "lib/compress/compress_zlib.h"
+#include "lib/thread/threads.h"
/* zlib 1.2.4 and 1.2.5 do some "clever" things with macros. Instead of
saying "(defined(FOO) ? FOO : 0)" they like to say "FOO-0", on the theory
@@ -301,4 +302,3 @@ tor_zlib_init(void)
{
atomic_counter_init(&total_zlib_allocation);
}
-
diff --git a/src/common/compress_zlib.h b/src/lib/compress/compress_zlib.h
index e3c1a2b339..7af68044de 100644
--- a/src/common/compress_zlib.h
+++ b/src/lib/compress/compress_zlib.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/common/compress_zstd.c b/src/lib/compress/compress_zstd.c
index 316a3fb417..0a553db55c 100644
--- a/src/common/compress_zstd.c
+++ b/src/lib/compress/compress_zstd.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,10 +13,12 @@
#include "orconfig.h"
-#include "util.h"
-#include "torlog.h"
-#include "compress.h"
-#include "compress_zstd.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/compress/compress.h"
+#include "lib/compress/compress_zstd.h"
+#include "lib/string/printf.h"
+#include "lib/thread/threads.h"
#ifdef ENABLE_ZSTD_ADVANCED_APIS
/* This is a lie, but we make sure it doesn't get us in trouble by wrapping
@@ -533,4 +535,3 @@ tor_zstd_set_static_apis_disabled_for_testing(int disabled)
static_apis_disable_for_testing = disabled;
}
#endif
-
diff --git a/src/common/compress_zstd.h b/src/lib/compress/compress_zstd.h
index bd42cf65ce..1177537a9e 100644
--- a/src/common/compress_zstd.h
+++ b/src/lib/compress/compress_zstd.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/include.am b/src/lib/compress/include.am
new file mode 100644
index 0000000000..75c9032bd2
--- /dev/null
+++ b/src/lib/compress/include.am
@@ -0,0 +1,26 @@
+
+noinst_LIBRARIES += src/lib/libtor-compress.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-compress-testing.a
+endif
+
+src_lib_libtor_compress_a_SOURCES = \
+ src/lib/compress/compress.c \
+ src/lib/compress/compress_buf.c \
+ src/lib/compress/compress_lzma.c \
+ src/lib/compress/compress_none.c \
+ src/lib/compress/compress_zlib.c \
+ src/lib/compress/compress_zstd.c
+
+src_lib_libtor_compress_testing_a_SOURCES = \
+ $(src_lib_libtor_compress_a_SOURCES)
+src_lib_libtor_compress_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_compress_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/compress/compress.h \
+ src/lib/compress/compress_lzma.h \
+ src/lib/compress/compress_none.h \
+ src/lib/compress/compress_zlib.h \
+ src/lib/compress/compress_zstd.h
diff --git a/src/lib/container/.may_include b/src/lib/container/.may_include
new file mode 100644
index 0000000000..90de5eda40
--- /dev/null
+++ b/src/lib/container/.may_include
@@ -0,0 +1,18 @@
+orconfig.h
+lib/cc/*.h
+lib/container/*.h
+lib/ctime/*.h
+lib/defs/*.h
+lib/malloc/*.h
+lib/err/*.h
+lib/smartlist_core/*.h
+lib/string/*.h
+lib/testsupport/testsupport.h
+lib/intmath/*.h
+lib/log/*.h
+
+# XXXX I am unsure about this one. It's only here for buffers.c
+lib/time/*.h
+
+ht.h
+siphash.h
diff --git a/src/lib/container/bitarray.h b/src/lib/container/bitarray.h
new file mode 100644
index 0000000000..172d56cc06
--- /dev/null
+++ b/src/lib/container/bitarray.h
@@ -0,0 +1,86 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_BITARRAY_H
+#define TOR_BITARRAY_H
+
+/**
+ * \file bitarray.h
+ *
+ * \brief Implements a variable-sized (but non-resizeable) bit-array.
+ **/
+
+#include "orconfig.h"
+#include <string.h>
+#include "lib/cc/torint.h"
+#include "lib/malloc/util_malloc.h"
+
+#if SIZEOF_INT == 4
+#define BITARRAY_SHIFT 5
+#elif SIZEOF_INT == 8
+#define BITARRAY_SHIFT 6
+#else
+#error "int is neither 4 nor 8 bytes. I can't deal with that."
+#endif /* SIZEOF_INT == 4 || ... */
+#define BITARRAY_MASK ((1u<<BITARRAY_SHIFT)-1)
+
+/** A random-access array of one-bit-wide elements. */
+typedef unsigned int bitarray_t;
+/** Create a new bit array that can hold <b>n_bits</b> bits. */
+static inline bitarray_t *
+bitarray_init_zero(unsigned int n_bits)
+{
+ /* round up to the next int. */
+ size_t sz = (n_bits+BITARRAY_MASK) >> BITARRAY_SHIFT;
+ return tor_calloc(sz, sizeof(unsigned int));
+}
+/** Expand <b>ba</b> from holding <b>n_bits_old</b> to <b>n_bits_new</b>,
+ * clearing all new bits. Returns a possibly changed pointer to the
+ * bitarray. */
+static inline bitarray_t *
+bitarray_expand(bitarray_t *ba,
+ unsigned int n_bits_old, unsigned int n_bits_new)
+{
+ size_t sz_old = (n_bits_old+BITARRAY_MASK) >> BITARRAY_SHIFT;
+ size_t sz_new = (n_bits_new+BITARRAY_MASK) >> BITARRAY_SHIFT;
+ char *ptr;
+ if (sz_new <= sz_old)
+ return ba;
+ ptr = tor_reallocarray(ba, sz_new, sizeof(unsigned int));
+ /* This memset does nothing to the older excess bytes. But they were
+ * already set to 0 by bitarry_init_zero. */
+ memset(ptr+sz_old*sizeof(unsigned int), 0,
+ (sz_new-sz_old)*sizeof(unsigned int));
+ return (bitarray_t*) ptr;
+}
+/** Free the bit array <b>ba</b>. */
+static inline void
+bitarray_free_(bitarray_t *ba)
+{
+ tor_free(ba);
+}
+#define bitarray_free(ba) FREE_AND_NULL(bitarray_t, bitarray_free_, (ba))
+
+/** Set the <b>bit</b>th bit in <b>b</b> to 1. */
+static inline void
+bitarray_set(bitarray_t *b, int bit)
+{
+ b[bit >> BITARRAY_SHIFT] |= (1u << (bit & BITARRAY_MASK));
+}
+/** Set the <b>bit</b>th bit in <b>b</b> to 0. */
+static inline void
+bitarray_clear(bitarray_t *b, int bit)
+{
+ b[bit >> BITARRAY_SHIFT] &= ~ (1u << (bit & BITARRAY_MASK));
+}
+/** Return true iff <b>bit</b>th bit in <b>b</b> is nonzero. NOTE: does
+ * not necessarily return 1 on true. */
+static inline unsigned int
+bitarray_is_set(bitarray_t *b, int bit)
+{
+ return b[bit >> BITARRAY_SHIFT] & (1u << (bit & BITARRAY_MASK));
+}
+
+#endif /* !defined(TOR_CONTAINER_H) */
diff --git a/src/lib/container/bloomfilt.c b/src/lib/container/bloomfilt.c
new file mode 100644
index 0000000000..1cab817e18
--- /dev/null
+++ b/src/lib/container/bloomfilt.c
@@ -0,0 +1,113 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file bloomfilt.c
+ * \brief Uses bitarray_t to implement a bloom filter.
+ **/
+
+#include <stdlib.h>
+
+#include "lib/malloc/util_malloc.h"
+#include "lib/container/bloomfilt.h"
+#include "lib/intmath/bits.h"
+#include "lib/log/util_bug.h"
+#include "siphash.h"
+
+/** How many bloom-filter bits we set per address. This is twice the
+ * BLOOMFILT_N_HASHES value, since we split the siphash output into two 32-bit
+ * values. */
+#define N_BITS_PER_ITEM (BLOOMFILT_N_HASHES * 2)
+
+struct bloomfilt_t {
+ /** siphash keys to make BLOOMFILT_N_HASHES independent hashes for each
+ * items. */
+ struct sipkey key[BLOOMFILT_N_HASHES];
+ bloomfilt_hash_fn hashfn; /**< Function used to generate hashes */
+ uint32_t mask; /**< One less than the number of bits in <b>ba</b>; always
+ * one less than a power of two. */
+ bitarray_t *ba; /**< A bit array to implement the Bloom filter. */
+};
+
+#define BIT(set, n) ((n) & (set)->mask)
+
+/** Add the element <b>item</b> to <b>set</b>. */
+void
+bloomfilt_add(bloomfilt_t *set,
+ const void *item)
+{
+ int i;
+ for (i = 0; i < BLOOMFILT_N_HASHES; ++i) {
+ uint64_t h = set->hashfn(&set->key[i], item);
+ uint32_t high_bits = (uint32_t)(h >> 32);
+ uint32_t low_bits = (uint32_t)(h);
+ bitarray_set(set->ba, BIT(set, high_bits));
+ bitarray_set(set->ba, BIT(set, low_bits));
+ }
+}
+
+/** If <b>item</b> is in <b>set</b>, return nonzero. Otherwise,
+ * <em>probably</em> return zero. */
+int
+bloomfilt_probably_contains(const bloomfilt_t *set,
+ const void *item)
+{
+ int i, matches = 0;
+ for (i = 0; i < BLOOMFILT_N_HASHES; ++i) {
+ uint64_t h = set->hashfn(&set->key[i], item);
+ uint32_t high_bits = (uint32_t)(h >> 32);
+ uint32_t low_bits = (uint32_t)(h);
+ // Note that !! is necessary here, since bitarray_is_set does not
+ // necessarily return 1 on true.
+ matches += !! bitarray_is_set(set->ba, BIT(set, high_bits));
+ matches += !! bitarray_is_set(set->ba, BIT(set, low_bits));
+ }
+ return matches == N_BITS_PER_ITEM;
+}
+
+/** Return a newly allocated bloomfilt_t, optimized to hold a total of
+ * <b>max_elements</b> elements with a reasonably low false positive weight.
+ *
+ * Uses the siphash-based function <b>hashfn</b> to compute hard-to-collide
+ * functions of the items, and the key material <b>random_key</b> to
+ * key the hash. There must be BLOOMFILT_KEY_LEN bytes in the supplied key.
+ **/
+bloomfilt_t *
+bloomfilt_new(int max_elements,
+ bloomfilt_hash_fn hashfn,
+ const uint8_t *random_key)
+{
+ /* The probability of false positives is about P=(1 - exp(-kn/m))^k, where k
+ * is the number of hash functions per entry, m is the bits in the array,
+ * and n is the number of elements inserted. For us, k==4, n<=max_elements,
+ * and m==n_bits= approximately max_elements*32. This gives
+ * P<(1-exp(-4*n/(32*n)))^4 == (1-exp(1/-8))^4 == .00019
+ *
+ * It would be more optimal in space vs false positives to get this false
+ * positive rate by going for k==13, and m==18.5n, but we also want to
+ * conserve CPU, and k==13 is pretty big.
+ */
+ int n_bits = 1u << (tor_log2(max_elements)+5);
+ bloomfilt_t *r = tor_malloc(sizeof(bloomfilt_t));
+ r->mask = n_bits - 1;
+ r->ba = bitarray_init_zero(n_bits);
+
+ tor_assert(sizeof(r->key) == BLOOMFILT_KEY_LEN);
+ memcpy(r->key, random_key, sizeof(r->key));
+
+ r->hashfn = hashfn;
+
+ return r;
+}
+
+/** Free all storage held in <b>set</b>. */
+void
+bloomfilt_free_(bloomfilt_t *set)
+{
+ if (!set)
+ return;
+ bitarray_free(set->ba);
+ tor_free(set);
+}
diff --git a/src/lib/container/bloomfilt.h b/src/lib/container/bloomfilt.h
new file mode 100644
index 0000000000..14f909cb19
--- /dev/null
+++ b/src/lib/container/bloomfilt.h
@@ -0,0 +1,41 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_BLOOMFILT_H
+#define TOR_BLOOMFILT_H
+
+/**
+ * \file bloomfilt.h
+ *
+ * \brief Header for bloomfilt.c
+ **/
+
+#include "orconfig.h"
+#include "lib/cc/torint.h"
+#include "lib/container/bitarray.h"
+
+/** A set of elements, implemented as a Bloom filter. */
+typedef struct bloomfilt_t bloomfilt_t;
+
+/** How many 64-bit siphash values to extract per item. */
+#define BLOOMFILT_N_HASHES 2
+
+/** How much key material do we need to randomize hashes? */
+#define BLOOMFILT_KEY_LEN (BLOOMFILT_N_HASHES * 16)
+
+struct sipkey;
+typedef uint64_t (*bloomfilt_hash_fn)(const struct sipkey *key,
+ const void *item);
+
+void bloomfilt_add(bloomfilt_t *set, const void *item);
+int bloomfilt_probably_contains(const bloomfilt_t *set, const void *item);
+
+bloomfilt_t *bloomfilt_new(int max_elements,
+ bloomfilt_hash_fn hashfn,
+ const uint8_t *random_key);
+void bloomfilt_free_(bloomfilt_t* set);
+#define bloomfilt_free(set) FREE_AND_NULL(bloomfilt_t, bloomfilt_free_, (set))
+
+#endif /* !defined(TOR_BLOOMFILT_H) */
diff --git a/src/common/buffers.c b/src/lib/container/buffers.c
index a01add9bef..5849704e35 100644
--- a/src/common/buffers.c
+++ b/src/lib/container/buffers.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,21 +16,31 @@
* 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
* monitored in main.c.
+ *
+ * This module only handles the buffer implementation itself. To use a buffer
+ * with the network, a compressor, or a TLS connection, see the other buffer_*
+ * modules.
**/
#define BUFFERS_PRIVATE
#include "orconfig.h"
#include <stddef.h>
-#include "buffers.h"
-#include "compat.h"
-#include "compress.h"
-#include "util.h"
-#include "torint.h"
-#include "torlog.h"
+#include "lib/container/buffers.h"
+#include "lib/cc/torint.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/string/printf.h"
+#include "lib/time/compat_time.h"
+
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#include <stdlib.h>
+#include <string.h>
+
//#define PARANOIA
#ifdef PARANOIA
@@ -506,177 +516,6 @@ buf_get_total_allocation(void)
return total_bytes_allocated_in_chunks;
}
-/** Read up to <b>at_most</b> bytes from the socket <b>fd</b> into
- * <b>chunk</b> (which must be on <b>buf</b>). If we get an EOF, set
- * *<b>reached_eof</b> to 1. Return -1 on error, 0 on eof or blocking,
- * and the number of bytes read otherwise. */
-static inline int
-read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most,
- int *reached_eof, int *socket_error)
-{
- ssize_t read_result;
- if (at_most > CHUNK_REMAINING_CAPACITY(chunk))
- at_most = CHUNK_REMAINING_CAPACITY(chunk);
- read_result = tor_socket_recv(fd, CHUNK_WRITE_PTR(chunk), at_most, 0);
-
- if (read_result < 0) {
- int e = tor_socket_errno(fd);
- if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */
-#ifdef _WIN32
- if (e == WSAENOBUFS)
- log_warn(LD_NET,"recv() failed: WSAENOBUFS. Not enough ram?");
-#endif
- *socket_error = e;
- return -1;
- }
- return 0; /* would block. */
- } else if (read_result == 0) {
- log_debug(LD_NET,"Encountered eof on fd %d", (int)fd);
- *reached_eof = 1;
- return 0;
- } else { /* actually got bytes. */
- buf->datalen += read_result;
- chunk->datalen += read_result;
- log_debug(LD_NET,"Read %ld bytes. %d on inbuf.", (long)read_result,
- (int)buf->datalen);
- tor_assert(read_result < INT_MAX);
- return (int)read_result;
- }
-}
-
-/** Read from socket <b>s</b>, writing onto end of <b>buf</b>. Read at most
- * <b>at_most</b> bytes, growing the buffer as necessary. If recv() returns 0
- * (because of EOF), set *<b>reached_eof</b> to 1 and return 0. Return -1 on
- * error; else return the number of bytes read.
- */
-/* XXXX indicate "read blocked" somehow? */
-int
-buf_read_from_socket(buf_t *buf, tor_socket_t s, size_t at_most,
- int *reached_eof,
- int *socket_error)
-{
- /* XXXX It's stupid to overload the return values for these functions:
- * "error status" and "number of bytes read" are not mutually exclusive.
- */
- int r = 0;
- size_t total_read = 0;
-
- check();
- tor_assert(reached_eof);
- tor_assert(SOCKET_OK(s));
-
- if (BUG(buf->datalen >= INT_MAX))
- return -1;
- if (BUG(buf->datalen >= INT_MAX - at_most))
- return -1;
-
- while (at_most > total_read) {
- size_t readlen = at_most - total_read;
- chunk_t *chunk;
- if (!buf->tail || CHUNK_REMAINING_CAPACITY(buf->tail) < MIN_READ_LEN) {
- chunk = buf_add_chunk_with_capacity(buf, at_most, 1);
- if (readlen > chunk->memlen)
- readlen = chunk->memlen;
- } else {
- size_t cap = CHUNK_REMAINING_CAPACITY(buf->tail);
- chunk = buf->tail;
- if (cap < readlen)
- readlen = cap;
- }
-
- r = read_to_chunk(buf, chunk, s, readlen, reached_eof, socket_error);
- check();
- if (r < 0)
- return r; /* Error */
- tor_assert(total_read+r < INT_MAX);
- total_read += r;
- if ((size_t)r < readlen) { /* eof, block, or no more to read. */
- break;
- }
- }
- return (int)total_read;
-}
-
-/** Helper for buf_flush_to_socket(): try to write <b>sz</b> bytes from chunk
- * <b>chunk</b> of buffer <b>buf</b> onto socket <b>s</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.
- */
-static inline int
-flush_chunk(tor_socket_t s, buf_t *buf, chunk_t *chunk, size_t sz,
- size_t *buf_flushlen)
-{
- ssize_t write_result;
-
- if (sz > chunk->datalen)
- sz = chunk->datalen;
- write_result = tor_socket_send(s, chunk->data, sz, 0);
-
- if (write_result < 0) {
- int e = tor_socket_errno(s);
- if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */
-#ifdef _WIN32
- if (e == WSAENOBUFS)
- log_warn(LD_NET,"write() failed: WSAENOBUFS. Not enough ram?");
-#endif
- return -1;
- }
- log_debug(LD_NET,"write() would block, returning.");
- return 0;
- } else {
- *buf_flushlen -= write_result;
- buf_drain(buf, write_result);
- tor_assert(write_result < INT_MAX);
- return (int)write_result;
- }
-}
-
-/** Write data from <b>buf</b> to the socket <b>s</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
- * from the buffer. Return the number of bytes written on success,
- * -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)
-{
- /* 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(s));
- if (BUG(*buf_flushlen > buf->datalen)) {
- *buf_flushlen = buf->datalen;
- }
- if (BUG(sz > *buf_flushlen)) {
- sz = *buf_flushlen;
- }
-
- check();
- while (sz) {
- size_t flushlen0;
- tor_assert(buf->head);
- if (buf->head->datalen >= sz)
- flushlen0 = sz;
- else
- flushlen0 = buf->head->datalen;
-
- r = flush_chunk(s, buf, buf->head, flushlen0, buf_flushlen);
- check();
- if (r < 0)
- return r;
- flushed += r;
- sz -= r;
- if (r == 0 || (size_t)r < flushlen0) /* can't flush any more now. */
- break;
- }
- tor_assert(flushed < INT_MAX);
- return (int)flushed;
-}
-
/** Append <b>string_len</b> bytes from <b>string</b> to the end of
* <b>buf</b>.
*
@@ -1037,65 +876,6 @@ buf_get_line(buf_t *buf, char *data_out, size_t *data_len)
return 1;
}
-/** Compress or uncompress the <b>data_len</b> bytes in <b>data</b> using the
- * compression state <b>state</b>, appending the result to <b>buf</b>. If
- * <b>done</b> is true, flush the data in the state and finish the
- * compression/uncompression. Return -1 on failure, 0 on success. */
-int
-buf_add_compress(buf_t *buf, tor_compress_state_t *state,
- const char *data, size_t data_len,
- const int done)
-{
- char *next;
- size_t old_avail, avail;
- int over = 0;
-
- do {
- int need_new_chunk = 0;
- if (!buf->tail || ! CHUNK_REMAINING_CAPACITY(buf->tail)) {
- size_t cap = data_len / 4;
- buf_add_chunk_with_capacity(buf, cap, 1);
- }
- next = CHUNK_WRITE_PTR(buf->tail);
- avail = old_avail = CHUNK_REMAINING_CAPACITY(buf->tail);
- switch (tor_compress_process(state, &next, &avail,
- &data, &data_len, done)) {
- case TOR_COMPRESS_DONE:
- over = 1;
- break;
- case TOR_COMPRESS_ERROR:
- return -1;
- case TOR_COMPRESS_OK:
- if (data_len == 0) {
- tor_assert_nonfatal(!done);
- over = 1;
- }
- break;
- case TOR_COMPRESS_BUFFER_FULL:
- if (avail) {
- /* The compression module says we need more room
- * (TOR_COMPRESS_BUFFER_FULL). Start a new chunk automatically,
- * whether were going to or not. */
- need_new_chunk = 1;
- }
- if (data_len == 0 && !done) {
- /* We've consumed all the input data, though, so there's no
- * point in forging ahead right now. */
- over = 1;
- }
- break;
- }
- buf->datalen += old_avail - avail;
- buf->tail->datalen += old_avail - avail;
- if (need_new_chunk) {
- buf_add_chunk_with_capacity(buf, data_len/4, 1);
- }
-
- } while (!over);
- check();
- return 0;
-}
-
/** Set *<b>output</b> to contain a copy of the data in *<b>input</b> */
int
buf_set_to_copy(buf_t **output,
@@ -1143,4 +923,3 @@ buf_assert_ok(buf_t *buf)
tor_assert(buf->datalen == total);
}
}
-
diff --git a/src/common/buffers.h b/src/lib/container/buffers.h
index 4275152de2..c48f83cfc7 100644
--- a/src/common/buffers.h
+++ b/src/lib/container/buffers.h
@@ -1,24 +1,25 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file buffers.h
+ *
* \brief Header file for buffers.c.
**/
#ifndef TOR_BUFFERS_H
#define TOR_BUFFERS_H
-#include "compat.h"
-#include "torint.h"
-#include "testsupport.h"
+#include "lib/cc/compat_compiler.h"
+#include "lib/cc/torint.h"
+#include "lib/testsupport/testsupport.h"
-typedef struct buf_t buf_t;
+#include <stdarg.h>
-struct tor_compress_state_t;
+typedef struct buf_t buf_t;
buf_t *buf_new(void);
buf_t *buf_new_with_capacity(size_t size);
@@ -35,21 +36,12 @@ size_t buf_slack(const buf_t *buf);
uint32_t buf_get_oldest_chunk_timestamp(const buf_t *buf, uint32_t now);
size_t buf_get_total_allocation(void);
-int buf_read_from_socket(buf_t *buf, tor_socket_t s, size_t at_most,
- int *reached_eof,
- int *socket_error);
-
-int buf_flush_to_socket(buf_t *buf, tor_socket_t s, size_t sz,
- size_t *buf_flushlen);
-
int buf_add(buf_t *buf, const char *string, size_t string_len);
void buf_add_string(buf_t *buf, const char *string);
void buf_add_printf(buf_t *buf, const char *format, ...)
CHECK_PRINTF(2, 3);
void buf_add_vprintf(buf_t *buf, const char *format, va_list args)
CHECK_PRINTF(2, 0);
-int buf_add_compress(buf_t *buf, struct tor_compress_state_t *state,
- const char *data, size_t data_len, int done);
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);
void buf_peek(const buf_t *buf, char *string, size_t string_len);
@@ -128,4 +120,3 @@ CHUNK_WRITE_PTR(chunk_t *chunk)
#endif /* defined(BUFFERS_PRIVATE) */
#endif /* !defined(TOR_BUFFERS_H) */
-
diff --git a/src/common/handles.h b/src/lib/container/handles.h
index aef8cd89ef..21ec0dfeec 100644
--- a/src/common/handles.h
+++ b/src/lib/container/handles.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -50,8 +50,9 @@
#define TOR_HANDLE_H
#include "orconfig.h"
-#include "tor_queue.h"
-#include "util.h"
+
+#include "lib/log/util_bug.h"
+#include "lib/malloc/util_malloc.h"
#define HANDLE_ENTRY(name, structname) \
struct name ## _handle_head_t *handle_head
@@ -150,4 +151,3 @@
}
#endif /* !defined(TOR_HANDLE_H) */
-
diff --git a/src/lib/container/include.am b/src/lib/container/include.am
new file mode 100644
index 0000000000..e6492098b5
--- /dev/null
+++ b/src/lib/container/include.am
@@ -0,0 +1,27 @@
+
+noinst_LIBRARIES += src/lib/libtor-container.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-container-testing.a
+endif
+
+src_lib_libtor_container_a_SOURCES = \
+ src/lib/container/bloomfilt.c \
+ src/lib/container/buffers.c \
+ src/lib/container/map.c \
+ src/lib/container/order.c \
+ src/lib/container/smartlist.c
+
+src_lib_libtor_container_testing_a_SOURCES = \
+ $(src_lib_libtor_container_a_SOURCES)
+src_lib_libtor_container_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_container_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/container/bitarray.h \
+ src/lib/container/bloomfilt.h \
+ src/lib/container/buffers.h \
+ src/lib/container/handles.h \
+ src/lib/container/map.h \
+ src/lib/container/order.h \
+ src/lib/container/smartlist.h
diff --git a/src/lib/container/map.c b/src/lib/container/map.c
new file mode 100644
index 0000000000..0602eac891
--- /dev/null
+++ b/src/lib/container/map.c
@@ -0,0 +1,413 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file map.c
+ *
+ * \brief Hash-table implementations of a string-to-void* map, and of
+ * a digest-to-void* map.
+ **/
+
+#include "lib/container/map.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/defs/digest_sizes.h"
+#include "lib/string/util_string.h"
+#include "lib/malloc/util_malloc.h"
+
+#include "lib/log/util_bug.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "ht.h"
+
+/** Helper: Declare an entry type and a map type to implement a mapping using
+ * ht.h. The map type will be called <b>maptype</b>. The key part of each
+ * entry is declared using the C declaration <b>keydecl</b>. All functions
+ * and types associated with the map get prefixed with <b>prefix</b> */
+#define DEFINE_MAP_STRUCTS(maptype, keydecl, prefix) \
+ typedef struct prefix ## entry_t { \
+ HT_ENTRY(prefix ## entry_t) node; \
+ void *val; \
+ keydecl; \
+ } prefix ## entry_t; \
+ struct maptype { \
+ HT_HEAD(prefix ## impl, prefix ## entry_t) head; \
+ }
+
+DEFINE_MAP_STRUCTS(strmap_t, char *key, strmap_);
+DEFINE_MAP_STRUCTS(digestmap_t, char key[DIGEST_LEN], digestmap_);
+DEFINE_MAP_STRUCTS(digest256map_t, uint8_t key[DIGEST256_LEN], digest256map_);
+
+/** Helper: compare strmap_entry_t objects by key value. */
+static inline int
+strmap_entries_eq(const strmap_entry_t *a, const strmap_entry_t *b)
+{
+ return !strcmp(a->key, b->key);
+}
+
+/** Helper: return a hash value for a strmap_entry_t. */
+static inline unsigned int
+strmap_entry_hash(const strmap_entry_t *a)
+{
+ return (unsigned) siphash24g(a->key, strlen(a->key));
+}
+
+/** Helper: compare digestmap_entry_t objects by key value. */
+static inline int
+digestmap_entries_eq(const digestmap_entry_t *a, const digestmap_entry_t *b)
+{
+ return tor_memeq(a->key, b->key, DIGEST_LEN);
+}
+
+/** Helper: return a hash value for a digest_map_t. */
+static inline unsigned int
+digestmap_entry_hash(const digestmap_entry_t *a)
+{
+ return (unsigned) siphash24g(a->key, DIGEST_LEN);
+}
+
+/** Helper: compare digestmap_entry_t objects by key value. */
+static inline int
+digest256map_entries_eq(const digest256map_entry_t *a,
+ const digest256map_entry_t *b)
+{
+ return tor_memeq(a->key, b->key, DIGEST256_LEN);
+}
+
+/** Helper: return a hash value for a digest_map_t. */
+static inline unsigned int
+digest256map_entry_hash(const digest256map_entry_t *a)
+{
+ return (unsigned) siphash24g(a->key, DIGEST256_LEN);
+}
+
+HT_PROTOTYPE(strmap_impl, strmap_entry_t, node, strmap_entry_hash,
+ strmap_entries_eq)
+HT_GENERATE2(strmap_impl, strmap_entry_t, node, strmap_entry_hash,
+ strmap_entries_eq, 0.6, tor_reallocarray_, tor_free_)
+
+HT_PROTOTYPE(digestmap_impl, digestmap_entry_t, node, digestmap_entry_hash,
+ digestmap_entries_eq)
+HT_GENERATE2(digestmap_impl, digestmap_entry_t, node, digestmap_entry_hash,
+ digestmap_entries_eq, 0.6, tor_reallocarray_, tor_free_)
+
+HT_PROTOTYPE(digest256map_impl, digest256map_entry_t, node,
+ digest256map_entry_hash,
+ digest256map_entries_eq)
+HT_GENERATE2(digest256map_impl, digest256map_entry_t, node,
+ digest256map_entry_hash,
+ digest256map_entries_eq, 0.6, tor_reallocarray_, tor_free_)
+
+#define strmap_entry_free(ent) \
+ FREE_AND_NULL(strmap_entry_t, strmap_entry_free_, (ent))
+#define digestmap_entry_free(ent) \
+ FREE_AND_NULL(digestmap_entry_t, digestmap_entry_free_, (ent))
+#define digest256map_entry_free(ent) \
+ FREE_AND_NULL(digest256map_entry_t, digest256map_entry_free_, (ent))
+
+static inline void
+strmap_entry_free_(strmap_entry_t *ent)
+{
+ tor_free(ent->key);
+ tor_free(ent);
+}
+static inline void
+digestmap_entry_free_(digestmap_entry_t *ent)
+{
+ tor_free(ent);
+}
+static inline void
+digest256map_entry_free_(digest256map_entry_t *ent)
+{
+ tor_free(ent);
+}
+
+static inline void
+strmap_assign_tmp_key(strmap_entry_t *ent, const char *key)
+{
+ ent->key = (char*)key;
+}
+static inline void
+digestmap_assign_tmp_key(digestmap_entry_t *ent, const char *key)
+{
+ memcpy(ent->key, key, DIGEST_LEN);
+}
+static inline void
+digest256map_assign_tmp_key(digest256map_entry_t *ent, const uint8_t *key)
+{
+ memcpy(ent->key, key, DIGEST256_LEN);
+}
+static inline void
+strmap_assign_key(strmap_entry_t *ent, const char *key)
+{
+ ent->key = tor_strdup(key);
+}
+static inline void
+digestmap_assign_key(digestmap_entry_t *ent, const char *key)
+{
+ memcpy(ent->key, key, DIGEST_LEN);
+}
+static inline void
+digest256map_assign_key(digest256map_entry_t *ent, const uint8_t *key)
+{
+ memcpy(ent->key, key, DIGEST256_LEN);
+}
+
+/**
+ * Macro: implement all the functions for a map that are declared in
+ * map.h by the DECLARE_MAP_FNS() macro. You must additionally define a
+ * prefix_entry_free_() function to free entries (and their keys), a
+ * prefix_assign_tmp_key() function to temporarily set a stack-allocated
+ * entry to hold a key, and a prefix_assign_key() function to set a
+ * heap-allocated entry to hold a key.
+ */
+#define IMPLEMENT_MAP_FNS(maptype, keytype, prefix) \
+ /** Create and return a new empty map. */ \
+ MOCK_IMPL(maptype *, \
+ prefix##_new,(void)) \
+ { \
+ maptype *result; \
+ result = tor_malloc(sizeof(maptype)); \
+ HT_INIT(prefix##_impl, &result->head); \
+ return result; \
+ } \
+ \
+ /** Return the item from <b>map</b> whose key matches <b>key</b>, or \
+ * NULL if no such value exists. */ \
+ void * \
+ prefix##_get(const maptype *map, const keytype key) \
+ { \
+ prefix ##_entry_t *resolve; \
+ prefix ##_entry_t search; \
+ tor_assert(map); \
+ tor_assert(key); \
+ prefix ##_assign_tmp_key(&search, key); \
+ resolve = HT_FIND(prefix ##_impl, &map->head, &search); \
+ if (resolve) { \
+ return resolve->val; \
+ } else { \
+ return NULL; \
+ } \
+ } \
+ \
+ /** Add an entry to <b>map</b> mapping <b>key</b> to <b>val</b>; \
+ * return the previous value, or NULL if no such value existed. */ \
+ void * \
+ prefix##_set(maptype *map, const keytype key, void *val) \
+ { \
+ prefix##_entry_t search; \
+ void *oldval; \
+ tor_assert(map); \
+ tor_assert(key); \
+ tor_assert(val); \
+ prefix##_assign_tmp_key(&search, key); \
+ /* We a lot of our time in this function, so the code below is */ \
+ /* meant to optimize the check/alloc/set cycle by avoiding the two */\
+ /* trips to the hash table that we would do in the unoptimized */ \
+ /* version of this code. (Each of HT_INSERT and HT_FIND calls */ \
+ /* HT_SET_HASH and HT_FIND_P.) */ \
+ HT_FIND_OR_INSERT_(prefix##_impl, node, prefix##_entry_hash, \
+ &(map->head), \
+ prefix##_entry_t, &search, ptr, \
+ { \
+ /* we found an entry. */ \
+ oldval = (*ptr)->val; \
+ (*ptr)->val = val; \
+ return oldval; \
+ }, \
+ { \
+ /* We didn't find the entry. */ \
+ prefix##_entry_t *newent = \
+ tor_malloc_zero(sizeof(prefix##_entry_t)); \
+ prefix##_assign_key(newent, key); \
+ newent->val = val; \
+ HT_FOI_INSERT_(node, &(map->head), \
+ &search, newent, ptr); \
+ return NULL; \
+ }); \
+ } \
+ \
+ /** Remove the value currently associated with <b>key</b> from the map. \
+ * Return the value if one was set, or NULL if there was no entry for \
+ * <b>key</b>. \
+ * \
+ * Note: you must free any storage associated with the returned value. \
+ */ \
+ void * \
+ prefix##_remove(maptype *map, const keytype key) \
+ { \
+ prefix##_entry_t *resolve; \
+ prefix##_entry_t search; \
+ void *oldval; \
+ tor_assert(map); \
+ tor_assert(key); \
+ prefix##_assign_tmp_key(&search, key); \
+ resolve = HT_REMOVE(prefix##_impl, &map->head, &search); \
+ if (resolve) { \
+ oldval = resolve->val; \
+ prefix##_entry_free(resolve); \
+ return oldval; \
+ } else { \
+ return NULL; \
+ } \
+ } \
+ \
+ /** Return the number of elements in <b>map</b>. */ \
+ int \
+ prefix##_size(const maptype *map) \
+ { \
+ return HT_SIZE(&map->head); \
+ } \
+ \
+ /** Return true iff <b>map</b> has no entries. */ \
+ int \
+ prefix##_isempty(const maptype *map) \
+ { \
+ return HT_EMPTY(&map->head); \
+ } \
+ \
+ /** Assert that <b>map</b> is not corrupt. */ \
+ void \
+ prefix##_assert_ok(const maptype *map) \
+ { \
+ tor_assert(!prefix##_impl_HT_REP_IS_BAD_(&map->head)); \
+ } \
+ \
+ /** Remove all entries from <b>map</b>, and deallocate storage for \
+ * those entries. If free_val is provided, invoked it every value in \
+ * <b>map</b>. */ \
+ MOCK_IMPL(void, \
+ prefix##_free_, (maptype *map, void (*free_val)(void*))) \
+ { \
+ prefix##_entry_t **ent, **next, *this; \
+ if (!map) \
+ return; \
+ for (ent = HT_START(prefix##_impl, &map->head); ent != NULL; \
+ ent = next) { \
+ this = *ent; \
+ next = HT_NEXT_RMV(prefix##_impl, &map->head, ent); \
+ if (free_val) \
+ free_val(this->val); \
+ prefix##_entry_free(this); \
+ } \
+ tor_assert(HT_EMPTY(&map->head)); \
+ HT_CLEAR(prefix##_impl, &map->head); \
+ tor_free(map); \
+ } \
+ \
+ /** return an <b>iterator</b> pointer to the front of a map. \
+ * \
+ * Iterator example: \
+ * \
+ * \code \
+ * // uppercase values in "map", removing empty values. \
+ * \
+ * strmap_iter_t *iter; \
+ * const char *key; \
+ * void *val; \
+ * char *cp; \
+ * \
+ * for (iter = strmap_iter_init(map); !strmap_iter_done(iter); ) { \
+ * strmap_iter_get(iter, &key, &val); \
+ * cp = (char*)val; \
+ * if (!*cp) { \
+ * iter = strmap_iter_next_rmv(map,iter); \
+ * free(val); \
+ * } else { \
+ * for (;*cp;cp++) *cp = TOR_TOUPPER(*cp); \
+ */ \
+ prefix##_iter_t * \
+ prefix##_iter_init(maptype *map) \
+ { \
+ tor_assert(map); \
+ return HT_START(prefix##_impl, &map->head); \
+ } \
+ \
+ /** Advance <b>iter</b> a single step to the next entry, and return \
+ * its new value. */ \
+ prefix##_iter_t * \
+ prefix##_iter_next(maptype *map, prefix##_iter_t *iter) \
+ { \
+ tor_assert(map); \
+ tor_assert(iter); \
+ return HT_NEXT(prefix##_impl, &map->head, iter); \
+ } \
+ /** Advance <b>iter</b> a single step to the next entry, removing the \
+ * current entry, and return its new value. */ \
+ prefix##_iter_t * \
+ prefix##_iter_next_rmv(maptype *map, prefix##_iter_t *iter) \
+ { \
+ prefix##_entry_t *rmv; \
+ tor_assert(map); \
+ tor_assert(iter); \
+ tor_assert(*iter); \
+ rmv = *iter; \
+ iter = HT_NEXT_RMV(prefix##_impl, &map->head, iter); \
+ prefix##_entry_free(rmv); \
+ return iter; \
+ } \
+ /** Set *<b>keyp</b> and *<b>valp</b> to the current entry pointed \
+ * to by iter. */ \
+ void \
+ prefix##_iter_get(prefix##_iter_t *iter, const keytype *keyp, \
+ void **valp) \
+ { \
+ tor_assert(iter); \
+ tor_assert(*iter); \
+ tor_assert(keyp); \
+ tor_assert(valp); \
+ *keyp = (*iter)->key; \
+ *valp = (*iter)->val; \
+ } \
+ /** Return true iff <b>iter</b> has advanced past the last entry of \
+ * <b>map</b>. */ \
+ int \
+ prefix##_iter_done(prefix##_iter_t *iter) \
+ { \
+ return iter == NULL; \
+ }
+
+IMPLEMENT_MAP_FNS(strmap_t, char *, strmap)
+IMPLEMENT_MAP_FNS(digestmap_t, char *, digestmap)
+IMPLEMENT_MAP_FNS(digest256map_t, uint8_t *, digest256map)
+
+/** Same as strmap_set, but first converts <b>key</b> to lowercase. */
+void *
+strmap_set_lc(strmap_t *map, const char *key, void *val)
+{
+ /* We could be a little faster by using strcasecmp instead, and a separate
+ * type, but I don't think it matters. */
+ void *v;
+ char *lc_key = tor_strdup(key);
+ tor_strlower(lc_key);
+ v = strmap_set(map,lc_key,val);
+ tor_free(lc_key);
+ return v;
+}
+
+/** Same as strmap_get, but first converts <b>key</b> to lowercase. */
+void *
+strmap_get_lc(const strmap_t *map, const char *key)
+{
+ void *v;
+ char *lc_key = tor_strdup(key);
+ tor_strlower(lc_key);
+ v = strmap_get(map,lc_key);
+ tor_free(lc_key);
+ return v;
+}
+
+/** Same as strmap_remove, but first converts <b>key</b> to lowercase */
+void *
+strmap_remove_lc(strmap_t *map, const char *key)
+{
+ void *v;
+ char *lc_key = tor_strdup(key);
+ tor_strlower(lc_key);
+ v = strmap_remove(map,lc_key);
+ tor_free(lc_key);
+ return v;
+}
diff --git a/src/lib/container/map.h b/src/lib/container/map.h
new file mode 100644
index 0000000000..ff71622682
--- /dev/null
+++ b/src/lib/container/map.h
@@ -0,0 +1,261 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_MAP_H
+#define TOR_MAP_H
+
+/**
+ * \file map.h
+ *
+ * \brief Headers for map.c.
+ **/
+
+#include "lib/testsupport/testsupport.h"
+#include "lib/cc/torint.h"
+
+#include "siphash.h"
+
+#define DECLARE_MAP_FNS(maptype, keytype, prefix) \
+ typedef struct maptype maptype; \
+ typedef struct prefix##entry_t *prefix##iter_t; \
+ MOCK_DECL(maptype*, prefix##new, (void)); \
+ void* prefix##set(maptype *map, keytype key, void *val); \
+ void* prefix##get(const maptype *map, keytype key); \
+ void* prefix##remove(maptype *map, keytype key); \
+ MOCK_DECL(void, prefix##free_, (maptype *map, void (*free_val)(void*))); \
+ int prefix##isempty(const maptype *map); \
+ int prefix##size(const maptype *map); \
+ prefix##iter_t *prefix##iter_init(maptype *map); \
+ prefix##iter_t *prefix##iter_next(maptype *map, prefix##iter_t *iter); \
+ prefix##iter_t *prefix##iter_next_rmv(maptype *map, prefix##iter_t *iter); \
+ void prefix##iter_get(prefix##iter_t *iter, keytype *keyp, void **valp); \
+ int prefix##iter_done(prefix##iter_t *iter); \
+ void prefix##assert_ok(const maptype *map)
+
+/* Map from const char * to void *. Implemented with a hash table. */
+DECLARE_MAP_FNS(strmap_t, const char *, strmap_);
+/* Map from const char[DIGEST_LEN] to void *. Implemented with a hash table. */
+DECLARE_MAP_FNS(digestmap_t, const char *, digestmap_);
+/* Map from const uint8_t[DIGEST256_LEN] to void *. Implemented with a hash
+ * table. */
+DECLARE_MAP_FNS(digest256map_t, const uint8_t *, digest256map_);
+
+#define MAP_FREE_AND_NULL(maptype, map, fn) \
+ do { \
+ maptype ## _free_((map), (fn)); \
+ (map) = NULL; \
+ } while (0)
+
+#define strmap_free(map, fn) MAP_FREE_AND_NULL(strmap, (map), (fn))
+#define digestmap_free(map, fn) MAP_FREE_AND_NULL(digestmap, (map), (fn))
+#define digest256map_free(map, fn) MAP_FREE_AND_NULL(digest256map, (map), (fn))
+
+#undef DECLARE_MAP_FNS
+
+/** Iterates over the key-value pairs in a map <b>map</b> in order.
+ * <b>prefix</b> is as for DECLARE_MAP_FNS (i.e., strmap_ or digestmap_).
+ * The map's keys and values are of type keytype and valtype respectively;
+ * each iteration assigns them to keyvar and valvar.
+ *
+ * Example use:
+ * MAP_FOREACH(digestmap_, m, const char *, k, routerinfo_t *, r) {
+ * // use k and r
+ * } MAP_FOREACH_END.
+ */
+/* Unpacks to, approximately:
+ * {
+ * digestmap_iter_t *k_iter;
+ * for (k_iter = digestmap_iter_init(m); !digestmap_iter_done(k_iter);
+ * k_iter = digestmap_iter_next(m, k_iter)) {
+ * const char *k;
+ * void *r_voidp;
+ * routerinfo_t *r;
+ * digestmap_iter_get(k_iter, &k, &r_voidp);
+ * r = r_voidp;
+ * // use k and r
+ * }
+ * }
+ */
+#define MAP_FOREACH(prefix, map, keytype, keyvar, valtype, valvar) \
+ STMT_BEGIN \
+ prefix##iter_t *keyvar##_iter; \
+ for (keyvar##_iter = prefix##iter_init(map); \
+ !prefix##iter_done(keyvar##_iter); \
+ keyvar##_iter = prefix##iter_next(map, keyvar##_iter)) { \
+ keytype keyvar; \
+ void *valvar##_voidp; \
+ valtype valvar; \
+ prefix##iter_get(keyvar##_iter, &keyvar, &valvar##_voidp); \
+ valvar = valvar##_voidp;
+
+/** As MAP_FOREACH, except allows members to be removed from the map
+ * during the iteration via MAP_DEL_CURRENT. Example use:
+ *
+ * Example use:
+ * MAP_FOREACH(digestmap_, m, const char *, k, routerinfo_t *, r) {
+ * if (is_very_old(r))
+ * MAP_DEL_CURRENT(k);
+ * } MAP_FOREACH_END.
+ **/
+/* Unpacks to, approximately:
+ * {
+ * digestmap_iter_t *k_iter;
+ * int k_del=0;
+ * for (k_iter = digestmap_iter_init(m); !digestmap_iter_done(k_iter);
+ * k_iter = k_del ? digestmap_iter_next(m, k_iter)
+ * : digestmap_iter_next_rmv(m, k_iter)) {
+ * const char *k;
+ * void *r_voidp;
+ * routerinfo_t *r;
+ * k_del=0;
+ * digestmap_iter_get(k_iter, &k, &r_voidp);
+ * r = r_voidp;
+ * if (is_very_old(r)) {
+ * k_del = 1;
+ * }
+ * }
+ * }
+ */
+#define MAP_FOREACH_MODIFY(prefix, map, keytype, keyvar, valtype, valvar) \
+ STMT_BEGIN \
+ prefix##iter_t *keyvar##_iter; \
+ int keyvar##_del=0; \
+ for (keyvar##_iter = prefix##iter_init(map); \
+ !prefix##iter_done(keyvar##_iter); \
+ keyvar##_iter = keyvar##_del ? \
+ prefix##iter_next_rmv(map, keyvar##_iter) : \
+ prefix##iter_next(map, keyvar##_iter)) { \
+ keytype keyvar; \
+ void *valvar##_voidp; \
+ valtype valvar; \
+ keyvar##_del=0; \
+ prefix##iter_get(keyvar##_iter, &keyvar, &valvar##_voidp); \
+ valvar = valvar##_voidp;
+
+/** Used with MAP_FOREACH_MODIFY to remove the currently-iterated-upon
+ * member of the map. */
+#define MAP_DEL_CURRENT(keyvar) \
+ STMT_BEGIN \
+ keyvar##_del = 1; \
+ STMT_END
+
+/** Used to end a MAP_FOREACH() block. */
+#define MAP_FOREACH_END } STMT_END ;
+
+/** As MAP_FOREACH, but does not require declaration of prefix or keytype.
+ * Example use:
+ * DIGESTMAP_FOREACH(m, k, routerinfo_t *, r) {
+ * // use k and r
+ * } DIGESTMAP_FOREACH_END.
+ */
+#define DIGESTMAP_FOREACH(map, keyvar, valtype, valvar) \
+ MAP_FOREACH(digestmap_, map, const char *, keyvar, valtype, valvar)
+
+/** As MAP_FOREACH_MODIFY, but does not require declaration of prefix or
+ * keytype.
+ * Example use:
+ * DIGESTMAP_FOREACH_MODIFY(m, k, routerinfo_t *, r) {
+ * if (is_very_old(r))
+ * MAP_DEL_CURRENT(k);
+ * } DIGESTMAP_FOREACH_END.
+ */
+#define DIGESTMAP_FOREACH_MODIFY(map, keyvar, valtype, valvar) \
+ MAP_FOREACH_MODIFY(digestmap_, map, const char *, keyvar, valtype, valvar)
+/** Used to end a DIGESTMAP_FOREACH() block. */
+#define DIGESTMAP_FOREACH_END MAP_FOREACH_END
+
+#define DIGEST256MAP_FOREACH(map, keyvar, valtype, valvar) \
+ MAP_FOREACH(digest256map_, map, const uint8_t *, keyvar, valtype, valvar)
+#define DIGEST256MAP_FOREACH_MODIFY(map, keyvar, valtype, valvar) \
+ MAP_FOREACH_MODIFY(digest256map_, map, const uint8_t *, \
+ keyvar, valtype, valvar)
+#define DIGEST256MAP_FOREACH_END MAP_FOREACH_END
+
+#define STRMAP_FOREACH(map, keyvar, valtype, valvar) \
+ MAP_FOREACH(strmap_, map, const char *, keyvar, valtype, valvar)
+#define STRMAP_FOREACH_MODIFY(map, keyvar, valtype, valvar) \
+ MAP_FOREACH_MODIFY(strmap_, map, const char *, keyvar, valtype, valvar)
+#define STRMAP_FOREACH_END MAP_FOREACH_END
+
+void* strmap_set_lc(strmap_t *map, const char *key, void *val);
+void* strmap_get_lc(const strmap_t *map, const char *key);
+void* strmap_remove_lc(strmap_t *map, const char *key);
+
+#define DECLARE_TYPED_DIGESTMAP_FNS(prefix, maptype, valtype) \
+ typedef struct maptype maptype; \
+ typedef struct prefix##iter_t *prefix##iter_t; \
+ ATTR_UNUSED static inline maptype* \
+ prefix##new(void) \
+ { \
+ return (maptype*)digestmap_new(); \
+ } \
+ ATTR_UNUSED static inline digestmap_t* \
+ prefix##to_digestmap(maptype *map) \
+ { \
+ return (digestmap_t*)map; \
+ } \
+ ATTR_UNUSED static inline valtype* \
+ prefix##get(maptype *map, const char *key) \
+ { \
+ return (valtype*)digestmap_get((digestmap_t*)map, key); \
+ } \
+ ATTR_UNUSED static inline valtype* \
+ prefix##set(maptype *map, const char *key, valtype *val) \
+ { \
+ return (valtype*)digestmap_set((digestmap_t*)map, key, val); \
+ } \
+ ATTR_UNUSED static inline valtype* \
+ prefix##remove(maptype *map, const char *key) \
+ { \
+ return (valtype*)digestmap_remove((digestmap_t*)map, key); \
+ } \
+ ATTR_UNUSED static inline void \
+ prefix##f##ree_(maptype *map, void (*free_val)(void*)) \
+ { \
+ digestmap_free_((digestmap_t*)map, free_val); \
+ } \
+ ATTR_UNUSED static inline int \
+ prefix##isempty(maptype *map) \
+ { \
+ return digestmap_isempty((digestmap_t*)map); \
+ } \
+ ATTR_UNUSED static inline int \
+ prefix##size(maptype *map) \
+ { \
+ return digestmap_size((digestmap_t*)map); \
+ } \
+ ATTR_UNUSED static inline \
+ prefix##iter_t *prefix##iter_init(maptype *map) \
+ { \
+ return (prefix##iter_t*) digestmap_iter_init((digestmap_t*)map); \
+ } \
+ ATTR_UNUSED static inline \
+ prefix##iter_t *prefix##iter_next(maptype *map, prefix##iter_t *iter) \
+ { \
+ return (prefix##iter_t*) digestmap_iter_next( \
+ (digestmap_t*)map, (digestmap_iter_t*)iter); \
+ } \
+ ATTR_UNUSED static inline prefix##iter_t* \
+ prefix##iter_next_rmv(maptype *map, prefix##iter_t *iter) \
+ { \
+ return (prefix##iter_t*) digestmap_iter_next_rmv( \
+ (digestmap_t*)map, (digestmap_iter_t*)iter); \
+ } \
+ ATTR_UNUSED static inline void \
+ prefix##iter_get(prefix##iter_t *iter, \
+ const char **keyp, \
+ valtype **valp) \
+ { \
+ void *v; \
+ digestmap_iter_get((digestmap_iter_t*) iter, keyp, &v); \
+ *valp = v; \
+ } \
+ ATTR_UNUSED static inline int \
+ prefix##iter_done(prefix##iter_t *iter) \
+ { \
+ return digestmap_iter_done((digestmap_iter_t*)iter); \
+ }
+
+#endif /* !defined(TOR_CONTAINER_H) */
diff --git a/src/lib/container/order.c b/src/lib/container/order.c
new file mode 100644
index 0000000000..1efef2c734
--- /dev/null
+++ b/src/lib/container/order.c
@@ -0,0 +1,48 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file order.c
+ * \brief Functions for finding the n'th element of an array.
+ **/
+
+#include <stdlib.h>
+
+#include "lib/container/order.h"
+#include "lib/log/util_bug.h"
+
+/** Declare a function called <b>funcname</b> that acts as a find_nth_FOO
+ * function for an array of type <b>elt_t</b>*.
+ *
+ * NOTE: The implementation kind of sucks: It's O(n log n), whereas finding
+ * the kth element of an n-element list can be done in O(n). Then again, this
+ * implementation is not in critical path, and it is obviously correct. */
+#define IMPLEMENT_ORDER_FUNC(funcname, elt_t) \
+ static int \
+ _cmp_ ## elt_t(const void *_a, const void *_b) \
+ { \
+ const elt_t *a = _a, *b = _b; \
+ if (*a<*b) \
+ return -1; \
+ else if (*a>*b) \
+ return 1; \
+ else \
+ return 0; \
+ } \
+ elt_t \
+ funcname(elt_t *array, int n_elements, int nth) \
+ { \
+ tor_assert(nth >= 0); \
+ tor_assert(nth < n_elements); \
+ qsort(array, n_elements, sizeof(elt_t), _cmp_ ##elt_t); \
+ return array[nth]; \
+ }
+
+IMPLEMENT_ORDER_FUNC(find_nth_int, int)
+IMPLEMENT_ORDER_FUNC(find_nth_time, time_t)
+IMPLEMENT_ORDER_FUNC(find_nth_double, double)
+IMPLEMENT_ORDER_FUNC(find_nth_uint32, uint32_t)
+IMPLEMENT_ORDER_FUNC(find_nth_int32, int32_t)
+IMPLEMENT_ORDER_FUNC(find_nth_long, long)
diff --git a/src/lib/container/order.h b/src/lib/container/order.h
new file mode 100644
index 0000000000..f0675f347b
--- /dev/null
+++ b/src/lib/container/order.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_ORDER_H
+#define TOR_ORDER_H
+
+/**
+ * \file order.h
+ *
+ * \brief Header for order.c.
+ **/
+
+#include "lib/cc/compat_compiler.h"
+#include "lib/cc/torint.h"
+
+/* These functions, given an <b>array</b> of <b>n_elements</b>, return the
+ * <b>nth</b> lowest element. <b>nth</b>=0 gives the lowest element;
+ * <b>n_elements</b>-1 gives the highest; and (<b>n_elements</b>-1) / 2 gives
+ * the median. As a side effect, the elements of <b>array</b> are sorted. */
+int find_nth_int(int *array, int n_elements, int nth);
+time_t find_nth_time(time_t *array, int n_elements, int nth);
+double find_nth_double(double *array, int n_elements, int nth);
+int32_t find_nth_int32(int32_t *array, int n_elements, int nth);
+uint32_t find_nth_uint32(uint32_t *array, int n_elements, int nth);
+long find_nth_long(long *array, int n_elements, int nth);
+static inline int
+median_int(int *array, int n_elements)
+{
+ return find_nth_int(array, n_elements, (n_elements-1)/2);
+}
+static inline time_t
+median_time(time_t *array, int n_elements)
+{
+ return find_nth_time(array, n_elements, (n_elements-1)/2);
+}
+static inline double
+median_double(double *array, int n_elements)
+{
+ return find_nth_double(array, n_elements, (n_elements-1)/2);
+}
+static inline uint32_t
+median_uint32(uint32_t *array, int n_elements)
+{
+ return find_nth_uint32(array, n_elements, (n_elements-1)/2);
+}
+static inline int32_t
+median_int32(int32_t *array, int n_elements)
+{
+ return find_nth_int32(array, n_elements, (n_elements-1)/2);
+}
+
+static inline uint32_t
+third_quartile_uint32(uint32_t *array, int n_elements)
+{
+ return find_nth_uint32(array, n_elements, (n_elements*3)/4);
+}
+
+#endif /* !defined(TOR_CONTAINER_H) */
diff --git a/src/lib/container/smartlist.c b/src/lib/container/smartlist.c
new file mode 100644
index 0000000000..c3abbff513
--- /dev/null
+++ b/src/lib/container/smartlist.c
@@ -0,0 +1,839 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file smartlist.c
+ *
+ * \brief Higher-level functions for the "smartlist" resizeable array
+ * abstraction.
+ *
+ * The functions declared here use higher-level functionality than those in
+ * smartlist_core.c, and handle things like smartlists of different types,
+ * sorting, searching, heap-structured smartlists, and other convenience
+ * functions.
+ **/
+
+#include "lib/container/smartlist.h"
+#include "lib/err/torerr.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/defs/digest_sizes.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/string/compat_ctype.h"
+#include "lib/string/compat_string.h"
+#include "lib/string/util_string.h"
+#include "lib/string/printf.h"
+
+#include "lib/log/util_bug.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/** Append the string produced by tor_asprintf(<b>pattern</b>, <b>...</b>)
+ * to <b>sl</b>. */
+void
+smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern, ...)
+{
+ va_list ap;
+ va_start(ap, pattern);
+ smartlist_add_vasprintf(sl, pattern, ap);
+ va_end(ap);
+}
+
+/** va_list-based backend of smartlist_add_asprintf. */
+void
+smartlist_add_vasprintf(struct smartlist_t *sl, const char *pattern,
+ va_list args)
+{
+ char *str = NULL;
+
+ tor_vasprintf(&str, pattern, args);
+ tor_assert(str != NULL);
+
+ smartlist_add(sl, str);
+}
+
+/** Reverse the order of the items in <b>sl</b>. */
+void
+smartlist_reverse(smartlist_t *sl)
+{
+ int i, j;
+ void *tmp;
+ tor_assert(sl);
+ for (i = 0, j = sl->num_used-1; i < j; ++i, --j) {
+ tmp = sl->list[i];
+ sl->list[i] = sl->list[j];
+ sl->list[j] = tmp;
+ }
+}
+
+/** If there are any strings in sl equal to element, remove and free them.
+ * Does not preserve order. */
+void
+smartlist_string_remove(smartlist_t *sl, const char *element)
+{
+ int i;
+ tor_assert(sl);
+ tor_assert(element);
+ for (i = 0; i < sl->num_used; ++i) {
+ if (!strcmp(element, sl->list[i])) {
+ tor_free(sl->list[i]);
+ 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;
+ }
+ }
+}
+
+/** Return true iff <b>sl</b> has some element E such that
+ * !strcmp(E,<b>element</b>)
+ */
+int
+smartlist_contains_string(const smartlist_t *sl, const char *element)
+{
+ int i;
+ if (!sl) return 0;
+ for (i=0; i < sl->num_used; i++)
+ if (strcmp((const char*)sl->list[i],element)==0)
+ return 1;
+ return 0;
+}
+
+/** If <b>element</b> is equal to an element of <b>sl</b>, return that
+ * element's index. Otherwise, return -1. */
+int
+smartlist_string_pos(const smartlist_t *sl, const char *element)
+{
+ int i;
+ if (!sl) return -1;
+ for (i=0; i < sl->num_used; i++)
+ if (strcmp((const char*)sl->list[i],element)==0)
+ return i;
+ return -1;
+}
+
+/** If <b>element</b> is the same pointer as an element of <b>sl</b>, return
+ * that element's index. Otherwise, return -1. */
+int
+smartlist_pos(const smartlist_t *sl, const void *element)
+{
+ int i;
+ if (!sl) return -1;
+ for (i=0; i < sl->num_used; i++)
+ if (element == sl->list[i])
+ return i;
+ return -1;
+}
+
+/** Return true iff <b>sl</b> has some element E such that
+ * !strcasecmp(E,<b>element</b>)
+ */
+int
+smartlist_contains_string_case(const smartlist_t *sl, const char *element)
+{
+ int i;
+ if (!sl) return 0;
+ for (i=0; i < sl->num_used; i++)
+ if (strcasecmp((const char*)sl->list[i],element)==0)
+ return 1;
+ return 0;
+}
+
+/** Return true iff <b>sl</b> has some element E such that E is equal
+ * to the decimal encoding of <b>num</b>.
+ */
+int
+smartlist_contains_int_as_string(const smartlist_t *sl, int num)
+{
+ char buf[32]; /* long enough for 64-bit int, and then some. */
+ tor_snprintf(buf,sizeof(buf),"%d", num);
+ return smartlist_contains_string(sl, buf);
+}
+
+/** Return true iff the two lists contain the same strings in the same
+ * order, or if they are both NULL. */
+int
+smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2)
+{
+ if (sl1 == NULL)
+ return sl2 == NULL;
+ if (sl2 == NULL)
+ return 0;
+ if (smartlist_len(sl1) != smartlist_len(sl2))
+ return 0;
+ SMARTLIST_FOREACH(sl1, const char *, cp1, {
+ const char *cp2 = smartlist_get(sl2, cp1_sl_idx);
+ if (strcmp(cp1, cp2))
+ return 0;
+ });
+ return 1;
+}
+
+/** Return true iff the two lists contain the same int pointer values in
+ * the same order, or if they are both NULL. */
+int
+smartlist_ints_eq(const smartlist_t *sl1, const smartlist_t *sl2)
+{
+ if (sl1 == NULL)
+ return sl2 == NULL;
+ if (sl2 == NULL)
+ return 0;
+ if (smartlist_len(sl1) != smartlist_len(sl2))
+ return 0;
+ SMARTLIST_FOREACH(sl1, int *, cp1, {
+ int *cp2 = smartlist_get(sl2, cp1_sl_idx);
+ if (*cp1 != *cp2)
+ return 0;
+ });
+ return 1;
+}
+
+/** Return true iff <b>sl</b> has some element E such that
+ * tor_memeq(E,<b>element</b>,DIGEST_LEN)
+ */
+int
+smartlist_contains_digest(const smartlist_t *sl, const char *element)
+{
+ int i;
+ if (!sl) return 0;
+ for (i=0; i < sl->num_used; i++)
+ if (tor_memeq((const char*)sl->list[i],element,DIGEST_LEN))
+ return 1;
+ return 0;
+}
+
+/** Return true iff some element E of sl2 has smartlist_contains(sl1,E).
+ */
+int
+smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2)
+{
+ int i;
+ for (i=0; i < sl2->num_used; i++)
+ if (smartlist_contains(sl1, sl2->list[i]))
+ return 1;
+ return 0;
+}
+
+/** Remove every element E of sl1 such that !smartlist_contains(sl2,E).
+ * Does not preserve the order of sl1.
+ */
+void
+smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2)
+{
+ int i;
+ for (i=0; i < sl1->num_used; i++)
+ if (!smartlist_contains(sl2, sl1->list[i])) {
+ sl1->list[i] = sl1->list[--sl1->num_used]; /* swap with the end */
+ i--; /* so we process the new i'th element */
+ sl1->list[sl1->num_used] = NULL;
+ }
+}
+
+/** Remove every element E of sl1 such that smartlist_contains(sl2,E).
+ * Does not preserve the order of sl1.
+ */
+void
+smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2)
+{
+ int i;
+ for (i=0; i < sl2->num_used; i++)
+ smartlist_remove(sl1, sl2->list[i]);
+}
+
+/** Allocate and return a new string containing the concatenation of
+ * the elements of <b>sl</b>, in order, separated by <b>join</b>. If
+ * <b>terminate</b> is true, also terminate the string with <b>join</b>.
+ * If <b>len_out</b> is not NULL, set <b>len_out</b> to the length of
+ * the returned string. Requires that every element of <b>sl</b> is
+ * NUL-terminated string.
+ */
+char *
+smartlist_join_strings(smartlist_t *sl, const char *join,
+ int terminate, size_t *len_out)
+{
+ return smartlist_join_strings2(sl,join,strlen(join),terminate,len_out);
+}
+
+/** As smartlist_join_strings, but instead of separating/terminated with a
+ * NUL-terminated string <b>join</b>, uses the <b>join_len</b>-byte sequence
+ * at <b>join</b>. (Useful for generating a sequence of NUL-terminated
+ * strings.)
+ */
+char *
+smartlist_join_strings2(smartlist_t *sl, const char *join,
+ size_t join_len, int terminate, size_t *len_out)
+{
+ int i;
+ size_t n = 0;
+ char *r = NULL, *dst, *src;
+
+ tor_assert(sl);
+ tor_assert(join);
+
+ if (terminate)
+ n = join_len;
+
+ for (i = 0; i < sl->num_used; ++i) {
+ n += strlen(sl->list[i]);
+ if (i+1 < sl->num_used) /* avoid double-counting the last one */
+ n += join_len;
+ }
+ dst = r = tor_malloc(n+1);
+ for (i = 0; i < sl->num_used; ) {
+ for (src = sl->list[i]; *src; )
+ *dst++ = *src++;
+ if (++i < sl->num_used) {
+ memcpy(dst, join, join_len);
+ dst += join_len;
+ }
+ }
+ if (terminate) {
+ memcpy(dst, join, join_len);
+ dst += join_len;
+ }
+ *dst = '\0';
+
+ if (len_out)
+ *len_out = dst-r;
+ return r;
+}
+
+/** Sort the members of <b>sl</b> into an order defined by
+ * the ordering function <b>compare</b>, which returns less then 0 if a
+ * precedes b, greater than 0 if b precedes a, and 0 if a 'equals' b.
+ */
+void
+smartlist_sort(smartlist_t *sl, int (*compare)(const void **a, const void **b))
+{
+ if (!sl->num_used)
+ return;
+ qsort(sl->list, sl->num_used, sizeof(void*),
+ (int (*)(const void *,const void*))compare);
+}
+
+/** Given a smartlist <b>sl</b> sorted with the function <b>compare</b>,
+ * return the most frequent member in the list. Break ties in favor of
+ * later elements. If the list is empty, return NULL. If count_out is
+ * non-null, set it to the count of the most frequent member.
+ */
+void *
+smartlist_get_most_frequent_(const smartlist_t *sl,
+ int (*compare)(const void **a, const void **b),
+ int *count_out)
+{
+ const void *most_frequent = NULL;
+ int most_frequent_count = 0;
+
+ const void *cur = NULL;
+ int i, count=0;
+
+ if (!sl->num_used) {
+ if (count_out)
+ *count_out = 0;
+ return NULL;
+ }
+ for (i = 0; i < sl->num_used; ++i) {
+ const void *item = sl->list[i];
+ if (cur && 0 == compare(&cur, &item)) {
+ ++count;
+ } else {
+ if (cur && count >= most_frequent_count) {
+ most_frequent = cur;
+ most_frequent_count = count;
+ }
+ cur = item;
+ count = 1;
+ }
+ }
+ if (cur && count >= most_frequent_count) {
+ most_frequent = cur;
+ most_frequent_count = count;
+ }
+ if (count_out)
+ *count_out = most_frequent_count;
+ return (void*)most_frequent;
+}
+
+/** Given a sorted smartlist <b>sl</b> and the comparison function used to
+ * sort it, remove all duplicate members. If free_fn is provided, calls
+ * free_fn on each duplicate. Otherwise, just removes them. Preserves order.
+ */
+void
+smartlist_uniq(smartlist_t *sl,
+ int (*compare)(const void **a, const void **b),
+ void (*free_fn)(void *a))
+{
+ int i;
+ for (i=1; i < sl->num_used; ++i) {
+ if (compare((const void **)&(sl->list[i-1]),
+ (const void **)&(sl->list[i])) == 0) {
+ if (free_fn)
+ free_fn(sl->list[i]);
+ smartlist_del_keeporder(sl, i--);
+ }
+ }
+}
+
+/** Assuming the members of <b>sl</b> are in order, return a pointer to the
+ * member that matches <b>key</b>. Ordering and matching are defined by a
+ * <b>compare</b> function that returns 0 on a match; less than 0 if key is
+ * less than member, and greater than 0 if key is greater then member.
+ */
+void *
+smartlist_bsearch(smartlist_t *sl, const void *key,
+ int (*compare)(const void *key, const void **member))
+{
+ int found, idx;
+ idx = smartlist_bsearch_idx(sl, key, compare, &found);
+ return found ? smartlist_get(sl, idx) : NULL;
+}
+
+/** Assuming the members of <b>sl</b> are in order, return the index of the
+ * member that matches <b>key</b>. If no member matches, return the index of
+ * the first member greater than <b>key</b>, or smartlist_len(sl) if no member
+ * is greater than <b>key</b>. Set <b>found_out</b> to true on a match, to
+ * false otherwise. Ordering and matching are defined by a <b>compare</b>
+ * function that returns 0 on a match; less than 0 if key is less than member,
+ * and greater than 0 if key is greater then member.
+ */
+int
+smartlist_bsearch_idx(const smartlist_t *sl, const void *key,
+ int (*compare)(const void *key, const void **member),
+ int *found_out)
+{
+ int hi, lo, cmp, mid, len, diff;
+
+ tor_assert(sl);
+ tor_assert(compare);
+ tor_assert(found_out);
+
+ len = smartlist_len(sl);
+
+ /* Check for the trivial case of a zero-length list */
+ if (len == 0) {
+ *found_out = 0;
+ /* We already know smartlist_len(sl) is 0 in this case */
+ return 0;
+ }
+
+ /* Okay, we have a real search to do */
+ tor_assert(len > 0);
+ lo = 0;
+ hi = len - 1;
+
+ /*
+ * These invariants are always true:
+ *
+ * For all i such that 0 <= i < lo, sl[i] < key
+ * For all i such that hi < i <= len, sl[i] > key
+ */
+
+ while (lo <= hi) {
+ diff = hi - lo;
+ /*
+ * We want mid = (lo + hi) / 2, but that could lead to overflow, so
+ * instead diff = hi - lo (non-negative because of loop condition), and
+ * then hi = lo + diff, mid = (lo + lo + diff) / 2 = lo + (diff / 2).
+ */
+ mid = lo + (diff / 2);
+ cmp = compare(key, (const void**) &(sl->list[mid]));
+ if (cmp == 0) {
+ /* sl[mid] == key; we found it */
+ *found_out = 1;
+ return mid;
+ } else if (cmp > 0) {
+ /*
+ * key > sl[mid] and an index i such that sl[i] == key must
+ * have i > mid if it exists.
+ */
+
+ /*
+ * Since lo <= mid <= hi, hi can only decrease on each iteration (by
+ * being set to mid - 1) and hi is initially len - 1, mid < len should
+ * always hold, and this is not symmetric with the left end of list
+ * mid > 0 test below. A key greater than the right end of the list
+ * should eventually lead to lo == hi == mid == len - 1, and then
+ * we set lo to len below and fall out to the same exit we hit for
+ * a key in the middle of the list but not matching. Thus, we just
+ * assert for consistency here rather than handle a mid == len case.
+ */
+ tor_assert(mid < len);
+ /* Move lo to the element immediately after sl[mid] */
+ lo = mid + 1;
+ } else {
+ /* This should always be true in this case */
+ tor_assert(cmp < 0);
+
+ /*
+ * key < sl[mid] and an index i such that sl[i] == key must
+ * have i < mid if it exists.
+ */
+
+ if (mid > 0) {
+ /* Normal case, move hi to the element immediately before sl[mid] */
+ hi = mid - 1;
+ } else {
+ /* These should always be true in this case */
+ tor_assert(mid == lo);
+ tor_assert(mid == 0);
+ /*
+ * We were at the beginning of the list and concluded that every
+ * element e compares e > key.
+ */
+ *found_out = 0;
+ return 0;
+ }
+ }
+ }
+
+ /*
+ * lo > hi; we have no element matching key but we have elements falling
+ * on both sides of it. The lo index points to the first element > key.
+ */
+ tor_assert(lo == hi + 1); /* All other cases should have been handled */
+ tor_assert(lo >= 0);
+ tor_assert(lo <= len);
+ tor_assert(hi >= 0);
+ tor_assert(hi <= len);
+
+ if (lo < len) {
+ cmp = compare(key, (const void **) &(sl->list[lo]));
+ tor_assert(cmp < 0);
+ } else {
+ cmp = compare(key, (const void **) &(sl->list[len-1]));
+ tor_assert(cmp > 0);
+ }
+
+ *found_out = 0;
+ return lo;
+}
+
+/** Helper: compare two const char **s. */
+static int
+compare_string_ptrs_(const void **_a, const void **_b)
+{
+ return strcmp((const char*)*_a, (const char*)*_b);
+}
+
+/** Sort a smartlist <b>sl</b> containing strings into lexically ascending
+ * order. */
+void
+smartlist_sort_strings(smartlist_t *sl)
+{
+ smartlist_sort(sl, compare_string_ptrs_);
+}
+
+/** Return the most frequent string in the sorted list <b>sl</b> */
+const char *
+smartlist_get_most_frequent_string(smartlist_t *sl)
+{
+ return smartlist_get_most_frequent(sl, compare_string_ptrs_);
+}
+
+/** Return the most frequent string in the sorted list <b>sl</b>.
+ * If <b>count_out</b> is provided, set <b>count_out</b> to the
+ * number of times that string appears.
+ */
+const char *
+smartlist_get_most_frequent_string_(smartlist_t *sl, int *count_out)
+{
+ return smartlist_get_most_frequent_(sl, compare_string_ptrs_, count_out);
+}
+
+/** Remove duplicate strings from a sorted list, and free them with tor_free().
+ */
+void
+smartlist_uniq_strings(smartlist_t *sl)
+{
+ smartlist_uniq(sl, compare_string_ptrs_, tor_free_);
+}
+
+/** Helper: compare two pointers. */
+static int
+compare_ptrs_(const void **_a, const void **_b)
+{
+ const void *a = *_a, *b = *_b;
+ if (a<b)
+ return -1;
+ else if (a==b)
+ return 0;
+ else
+ return 1;
+}
+
+/** Sort <b>sl</b> in ascending order of the pointers it contains. */
+void
+smartlist_sort_pointers(smartlist_t *sl)
+{
+ smartlist_sort(sl, compare_ptrs_);
+}
+
+/* Heap-based priority queue implementation for O(lg N) insert and remove.
+ * Recall that the heap property is that, for every index I, h[I] <
+ * H[LEFT_CHILD[I]] and h[I] < H[RIGHT_CHILD[I]].
+ *
+ * For us to remove items other than the topmost item, each item must store
+ * its own index within the heap. When calling the pqueue functions, tell
+ * them about the offset of the field that stores the index within the item.
+ *
+ * Example:
+ *
+ * typedef struct timer_t {
+ * struct timeval tv;
+ * int heap_index;
+ * } timer_t;
+ *
+ * static int compare(const void *p1, const void *p2) {
+ * const timer_t *t1 = p1, *t2 = p2;
+ * if (t1->tv.tv_sec < t2->tv.tv_sec) {
+ * return -1;
+ * } else if (t1->tv.tv_sec > t2->tv.tv_sec) {
+ * return 1;
+ * } else {
+ * return t1->tv.tv_usec - t2->tv_usec;
+ * }
+ * }
+ *
+ * void timer_heap_insert(smartlist_t *heap, timer_t *timer) {
+ * smartlist_pqueue_add(heap, compare, offsetof(timer_t, heap_index),
+ * timer);
+ * }
+ *
+ * void timer_heap_pop(smartlist_t *heap) {
+ * return smartlist_pqueue_pop(heap, compare,
+ * offsetof(timer_t, heap_index));
+ * }
+ */
+
+/** @{ */
+/** Functions to manipulate heap indices to find a node's parent and children.
+ *
+ * For a 1-indexed array, we would use LEFT_CHILD[x] = 2*x and RIGHT_CHILD[x]
+ * = 2*x + 1. But this is C, so we have to adjust a little. */
+
+/* MAX_PARENT_IDX is the largest IDX in the smartlist which might have
+ * children whose indices fit inside an int.
+ * LEFT_CHILD(MAX_PARENT_IDX) == INT_MAX-2;
+ * RIGHT_CHILD(MAX_PARENT_IDX) == INT_MAX-1;
+ * LEFT_CHILD(MAX_PARENT_IDX + 1) == INT_MAX // impossible, see max list size.
+ */
+#define MAX_PARENT_IDX ((INT_MAX - 2) / 2)
+/* If this is true, then i is small enough to potentially have children
+ * in the smartlist, and it is save to use LEFT_CHILD/RIGHT_CHILD on it. */
+#define IDX_MAY_HAVE_CHILDREN(i) ((i) <= MAX_PARENT_IDX)
+#define LEFT_CHILD(i) ( 2*(i) + 1 )
+#define RIGHT_CHILD(i) ( 2*(i) + 2 )
+#define PARENT(i) ( ((i)-1) / 2 )
+/** }@ */
+
+/** @{ */
+/** Helper macros for heaps: Given a local variable <b>idx_field_offset</b>
+ * set to the offset of an integer index within the heap element structure,
+ * IDX_OF_ITEM(p) gives you the index of p, and IDXP(p) gives you a pointer to
+ * where p's index is stored. Given additionally a local smartlist <b>sl</b>,
+ * UPDATE_IDX(i) sets the index of the element at <b>i</b> to the correct
+ * value (that is, to <b>i</b>).
+ */
+#define IDXP(p) ((int*)STRUCT_VAR_P(p, idx_field_offset))
+
+#define UPDATE_IDX(i) do { \
+ void *updated = sl->list[i]; \
+ *IDXP(updated) = i; \
+ } while (0)
+
+#define IDX_OF_ITEM(p) (*IDXP(p))
+/** @} */
+
+/** Helper. <b>sl</b> may have at most one violation of the heap property:
+ * the item at <b>idx</b> may be greater than one or both of its children.
+ * Restore the heap property. */
+static inline void
+smartlist_heapify(smartlist_t *sl,
+ int (*compare)(const void *a, const void *b),
+ int idx_field_offset,
+ int idx)
+{
+ while (1) {
+ if (! IDX_MAY_HAVE_CHILDREN(idx)) {
+ /* idx is so large that it cannot have any children, since doing so
+ * would mean the smartlist was over-capacity. Therefore it cannot
+ * violate the heap property by being greater than a child (since it
+ * doesn't have any). */
+ return;
+ }
+
+ int left_idx = LEFT_CHILD(idx);
+ int best_idx;
+
+ if (left_idx >= sl->num_used)
+ return;
+ if (compare(sl->list[idx],sl->list[left_idx]) < 0)
+ best_idx = idx;
+ else
+ best_idx = left_idx;
+ if (left_idx+1 < sl->num_used &&
+ compare(sl->list[left_idx+1],sl->list[best_idx]) < 0)
+ best_idx = left_idx + 1;
+
+ if (best_idx == idx) {
+ return;
+ } else {
+ void *tmp = sl->list[idx];
+ sl->list[idx] = sl->list[best_idx];
+ sl->list[best_idx] = tmp;
+ UPDATE_IDX(idx);
+ UPDATE_IDX(best_idx);
+
+ idx = best_idx;
+ }
+ }
+}
+
+/** Insert <b>item</b> into the heap stored in <b>sl</b>, where order is
+ * determined by <b>compare</b> and the offset of the item in the heap is
+ * stored in an int-typed field at position <b>idx_field_offset</b> within
+ * item.
+ */
+void
+smartlist_pqueue_add(smartlist_t *sl,
+ int (*compare)(const void *a, const void *b),
+ int idx_field_offset,
+ void *item)
+{
+ int idx;
+ smartlist_add(sl,item);
+ UPDATE_IDX(sl->num_used-1);
+
+ for (idx = sl->num_used - 1; idx; ) {
+ int parent = PARENT(idx);
+ if (compare(sl->list[idx], sl->list[parent]) < 0) {
+ void *tmp = sl->list[parent];
+ sl->list[parent] = sl->list[idx];
+ sl->list[idx] = tmp;
+ UPDATE_IDX(parent);
+ UPDATE_IDX(idx);
+ idx = parent;
+ } else {
+ return;
+ }
+ }
+}
+
+/** Remove and return the top-priority item from the heap stored in <b>sl</b>,
+ * where order is determined by <b>compare</b> and the item's position is
+ * stored at position <b>idx_field_offset</b> within the item. <b>sl</b> must
+ * not be empty. */
+void *
+smartlist_pqueue_pop(smartlist_t *sl,
+ int (*compare)(const void *a, const void *b),
+ int idx_field_offset)
+{
+ void *top;
+ tor_assert(sl->num_used);
+
+ top = sl->list[0];
+ *IDXP(top)=-1;
+ if (--sl->num_used) {
+ sl->list[0] = sl->list[sl->num_used];
+ sl->list[sl->num_used] = NULL;
+ UPDATE_IDX(0);
+ smartlist_heapify(sl, compare, idx_field_offset, 0);
+ }
+ sl->list[sl->num_used] = NULL;
+ return top;
+}
+
+/** Remove the item <b>item</b> from the heap stored in <b>sl</b>,
+ * where order is determined by <b>compare</b> and the item's position is
+ * stored at position <b>idx_field_offset</b> within the item. <b>sl</b> must
+ * not be empty. */
+void
+smartlist_pqueue_remove(smartlist_t *sl,
+ int (*compare)(const void *a, const void *b),
+ int idx_field_offset,
+ void *item)
+{
+ int idx = IDX_OF_ITEM(item);
+ tor_assert(idx >= 0);
+ tor_assert(sl->list[idx] == item);
+ --sl->num_used;
+ *IDXP(item) = -1;
+ if (idx == sl->num_used) {
+ sl->list[sl->num_used] = NULL;
+ return;
+ } else {
+ sl->list[idx] = sl->list[sl->num_used];
+ sl->list[sl->num_used] = NULL;
+ UPDATE_IDX(idx);
+ smartlist_heapify(sl, compare, idx_field_offset, idx);
+ }
+}
+
+/** Assert that the heap property is correctly maintained by the heap stored
+ * in <b>sl</b>, where order is determined by <b>compare</b>. */
+void
+smartlist_pqueue_assert_ok(smartlist_t *sl,
+ int (*compare)(const void *a, const void *b),
+ int idx_field_offset)
+{
+ int i;
+ for (i = sl->num_used - 1; i >= 0; --i) {
+ if (i>0)
+ tor_assert(compare(sl->list[PARENT(i)], sl->list[i]) <= 0);
+ tor_assert(IDX_OF_ITEM(sl->list[i]) == i);
+ }
+}
+
+/** Helper: compare two DIGEST_LEN digests. */
+static int
+compare_digests_(const void **_a, const void **_b)
+{
+ return tor_memcmp((const char*)*_a, (const char*)*_b, DIGEST_LEN);
+}
+
+/** Sort the list of DIGEST_LEN-byte digests into ascending order. */
+void
+smartlist_sort_digests(smartlist_t *sl)
+{
+ smartlist_sort(sl, compare_digests_);
+}
+
+/** Remove duplicate digests from a sorted list, and free them with tor_free().
+ */
+void
+smartlist_uniq_digests(smartlist_t *sl)
+{
+ smartlist_uniq(sl, compare_digests_, tor_free_);
+}
+
+/** Helper: compare two DIGEST256_LEN digests. */
+static int
+compare_digests256_(const void **_a, const void **_b)
+{
+ return tor_memcmp((const char*)*_a, (const char*)*_b, DIGEST256_LEN);
+}
+
+/** Sort the list of DIGEST256_LEN-byte digests into ascending order. */
+void
+smartlist_sort_digests256(smartlist_t *sl)
+{
+ smartlist_sort(sl, compare_digests256_);
+}
+
+/** Return the most frequent member of the sorted list of DIGEST256_LEN
+ * digests in <b>sl</b> */
+const uint8_t *
+smartlist_get_most_frequent_digest256(smartlist_t *sl)
+{
+ return smartlist_get_most_frequent(sl, compare_digests256_);
+}
+
+/** Remove duplicate 256-bit digests from a sorted list, and free them with
+ * tor_free().
+ */
+void
+smartlist_uniq_digests256(smartlist_t *sl)
+{
+ smartlist_uniq(sl, compare_digests256_, tor_free_);
+}
diff --git a/src/lib/container/smartlist.h b/src/lib/container/smartlist.h
new file mode 100644
index 0000000000..3b19cbfce4
--- /dev/null
+++ b/src/lib/container/smartlist.h
@@ -0,0 +1,165 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_SMARTLIST_H
+#define TOR_SMARTLIST_H
+
+/**
+ * \file smartlist.h
+ *
+ * \brief Header for smartlist.c
+ **/
+
+#include <stdarg.h>
+
+#include "lib/smartlist_core/smartlist_core.h"
+#include "lib/smartlist_core/smartlist_foreach.h"
+#include "lib/smartlist_core/smartlist_split.h"
+
+void smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern, ...)
+ CHECK_PRINTF(2, 3);
+void smartlist_add_vasprintf(struct smartlist_t *sl, const char *pattern,
+ va_list args)
+ CHECK_PRINTF(2, 0);
+void smartlist_reverse(smartlist_t *sl);
+void smartlist_string_remove(smartlist_t *sl, const char *element);
+int smartlist_contains_string(const smartlist_t *sl, const char *element);
+int smartlist_pos(const smartlist_t *sl, const void *element);
+int smartlist_string_pos(const smartlist_t *, const char *elt);
+int smartlist_contains_string_case(const smartlist_t *sl, const char *element);
+int smartlist_contains_int_as_string(const smartlist_t *sl, int num);
+int smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2);
+int smartlist_contains_digest(const smartlist_t *sl, const char *element);
+int smartlist_ints_eq(const smartlist_t *sl1, const smartlist_t *sl2);
+int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2);
+void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2);
+void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2);
+
+void smartlist_sort(smartlist_t *sl,
+ int (*compare)(const void **a, const void **b));
+void *smartlist_get_most_frequent_(const smartlist_t *sl,
+ int (*compare)(const void **a, const void **b),
+ int *count_out);
+#define smartlist_get_most_frequent(sl, compare) \
+ smartlist_get_most_frequent_((sl), (compare), NULL)
+void smartlist_uniq(smartlist_t *sl,
+ int (*compare)(const void **a, const void **b),
+ void (*free_fn)(void *elt));
+
+void smartlist_sort_strings(smartlist_t *sl);
+void smartlist_sort_digests(smartlist_t *sl);
+void smartlist_sort_digests256(smartlist_t *sl);
+void smartlist_sort_pointers(smartlist_t *sl);
+
+const char *smartlist_get_most_frequent_string(smartlist_t *sl);
+const char *smartlist_get_most_frequent_string_(smartlist_t *sl,
+ int *count_out);
+const uint8_t *smartlist_get_most_frequent_digest256(smartlist_t *sl);
+
+void smartlist_uniq_strings(smartlist_t *sl);
+void smartlist_uniq_digests(smartlist_t *sl);
+void smartlist_uniq_digests256(smartlist_t *sl);
+void *smartlist_bsearch(smartlist_t *sl, const void *key,
+ int (*compare)(const void *key, const void **member));
+int smartlist_bsearch_idx(const smartlist_t *sl, const void *key,
+ int (*compare)(const void *key, const void **member),
+ int *found_out);
+
+void smartlist_pqueue_add(smartlist_t *sl,
+ int (*compare)(const void *a, const void *b),
+ int idx_field_offset,
+ void *item);
+void *smartlist_pqueue_pop(smartlist_t *sl,
+ int (*compare)(const void *a, const void *b),
+ int idx_field_offset);
+void smartlist_pqueue_remove(smartlist_t *sl,
+ int (*compare)(const void *a, const void *b),
+ int idx_field_offset,
+ void *item);
+void smartlist_pqueue_assert_ok(smartlist_t *sl,
+ int (*compare)(const void *a, const void *b),
+ int idx_field_offset);
+
+char *smartlist_join_strings(smartlist_t *sl, const char *join, int terminate,
+ size_t *len_out) ATTR_MALLOC;
+char *smartlist_join_strings2(smartlist_t *sl, const char *join,
+ size_t join_len, int terminate, size_t *len_out)
+ ATTR_MALLOC;
+
+/* Helper: Given two lists of items, possibly of different types, such that
+ * both lists are sorted on some common field (as determined by a comparison
+ * expression <b>cmpexpr</b>), and such that one list (<b>sl1</b>) has no
+ * duplicates on the common field, loop through the lists in lockstep, and
+ * execute <b>unmatched_var2</b> on items in var2 that do not appear in
+ * var1.
+ *
+ * WARNING: It isn't safe to add remove elements from either list while the
+ * loop is in progress.
+ *
+ * Example use:
+ * SMARTLIST_FOREACH_JOIN(routerstatus_list, routerstatus_t *, rs,
+ * routerinfo_list, routerinfo_t *, ri,
+ * tor_memcmp(rs->identity_digest, ri->identity_digest, 20),
+ * log_info(LD_GENERAL,"No match for %s", ri->nickname)) {
+ * log_info(LD_GENERAL, "%s matches routerstatus %p", ri->nickname, rs);
+ * } SMARTLIST_FOREACH_JOIN_END(rs, ri);
+ **/
+/* The example above unpacks (approximately) to:
+ * int rs_sl_idx = 0, rs_sl_len = smartlist_len(routerstatus_list);
+ * int ri_sl_idx, ri_sl_len = smartlist_len(routerinfo_list);
+ * int rs_ri_cmp;
+ * routerstatus_t *rs;
+ * routerinfo_t *ri;
+ * for (; ri_sl_idx < ri_sl_len; ++ri_sl_idx) {
+ * ri = smartlist_get(routerinfo_list, ri_sl_idx);
+ * while (rs_sl_idx < rs_sl_len) {
+ * rs = smartlist_get(routerstatus_list, rs_sl_idx);
+ * rs_ri_cmp = tor_memcmp(rs->identity_digest, ri->identity_digest, 20);
+ * if (rs_ri_cmp > 0) {
+ * break;
+ * } else if (rs_ri_cmp == 0) {
+ * goto matched_ri;
+ * } else {
+ * ++rs_sl_idx;
+ * }
+ * }
+ * log_info(LD_GENERAL,"No match for %s", ri->nickname);
+ * continue;
+ * matched_ri: {
+ * log_info(LD_GENERAL,"%s matches with routerstatus %p",ri->nickname,rs);
+ * }
+ * }
+ */
+#define SMARTLIST_FOREACH_JOIN(sl1, type1, var1, sl2, type2, var2, \
+ cmpexpr, unmatched_var2) \
+ STMT_BEGIN \
+ int var1 ## _sl_idx = 0, var1 ## _sl_len=(sl1)->num_used; \
+ int var2 ## _sl_idx = 0, var2 ## _sl_len=(sl2)->num_used; \
+ int var1 ## _ ## var2 ## _cmp; \
+ type1 var1; \
+ type2 var2; \
+ for (; var2##_sl_idx < var2##_sl_len; ++var2##_sl_idx) { \
+ var2 = (sl2)->list[var2##_sl_idx]; \
+ while (var1##_sl_idx < var1##_sl_len) { \
+ var1 = (sl1)->list[var1##_sl_idx]; \
+ var1##_##var2##_cmp = (cmpexpr); \
+ if (var1##_##var2##_cmp > 0) { \
+ break; \
+ } else if (var1##_##var2##_cmp == 0) { \
+ goto matched_##var2; \
+ } else { \
+ ++var1##_sl_idx; \
+ } \
+ } \
+ /* Ran out of v1, or no match for var2. */ \
+ unmatched_var2; \
+ continue; \
+ matched_##var2: ; \
+
+#define SMARTLIST_FOREACH_JOIN_END(var1, var2) \
+ } \
+ STMT_END
+
+#endif /* !defined(TOR_CONTAINER_H) */
diff --git a/src/lib/crypt_ops/.may_include b/src/lib/crypt_ops/.may_include
new file mode 100644
index 0000000000..a0fa4ec05c
--- /dev/null
+++ b/src/lib/crypt_ops/.may_include
@@ -0,0 +1,24 @@
+orconfig.h
+lib/arch/*.h
+lib/cc/*.h
+lib/container/*.h
+lib/crypt_ops/*.h
+lib/ctime/*.h
+lib/defs/*.h
+lib/encoding/*.h
+lib/fs/*.h
+lib/lock/*.h
+lib/malloc/*.h
+lib/intmath/*.h
+lib/sandbox/*.h
+lib/string/*.h
+lib/testsupport/testsupport.h
+lib/thread/*.h
+lib/log/*.h
+
+trunnel/pwbox.h
+
+keccak-tiny/*.h
+ed25519/*.h
+
+siphash.h
diff --git a/src/common/aes.c b/src/lib/crypt_ops/aes.c
index 86f3472bfd..a01b1e16b2 100644
--- a/src/common/aes.c
+++ b/src/lib/crypt_ops/aes.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,15 +10,17 @@
**/
#include "orconfig.h"
+#include "lib/crypt_ops/aes.h"
+#include "lib/log/util_bug.h"
#ifdef _WIN32 /*wrkard for dtls1.h >= 0.9.8m of "#include <winsock.h>"*/
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
-#include "compat_openssl.h"
+#include "lib/crypt_ops/compat_openssl.h"
#include <openssl/opensslv.h>
-#include "crypto_openssl_mgt.h"
+#include "lib/crypt_ops/crypto_openssl_mgt.h"
#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,0,0)
#error "We require OpenSSL >= 1.0.0"
@@ -26,7 +28,6 @@
DISABLE_GCC_WARNING(redundant-decls)
-#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/aes.h>
@@ -36,11 +37,9 @@ DISABLE_GCC_WARNING(redundant-decls)
ENABLE_GCC_WARNING(redundant-decls)
-#include "compat.h"
-#include "aes.h"
-#include "util.h"
-#include "torlog.h"
-#include "di_ops.h"
+#include "lib/crypt_ops/aes.h"
+#include "lib/log/torlog.h"
+#include "lib/ctime/di_ops.h"
#ifdef ANDROID
/* Android's OpenSSL seems to have removed all of its Engine support. */
@@ -407,4 +406,3 @@ aes_set_iv(aes_cnt_cipher_t *cipher, const uint8_t *iv)
}
#endif /* defined(USE_EVP_AES_CTR) */
-
diff --git a/src/common/aes.h b/src/lib/crypt_ops/aes.h
index 0b17cd55a4..a57654159a 100644
--- a/src/common/aes.h
+++ b/src/lib/crypt_ops/aes.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* Implements a minimal interface to counter-mode AES. */
@@ -13,6 +13,9 @@
* \brief Headers for aes.c
*/
+#include "lib/cc/torint.h"
+#include "lib/malloc/util_malloc.h"
+
typedef struct aes_cnt_cipher aes_cnt_cipher_t;
aes_cnt_cipher_t* aes_new_cipher(const uint8_t *key, const uint8_t *iv,
@@ -26,4 +29,3 @@ int evaluate_evp_for_aes(int force_value);
int evaluate_ctr_for_aes(void);
#endif /* !defined(TOR_AES_H) */
-
diff --git a/src/common/compat_openssl.h b/src/lib/crypt_ops/compat_openssl.h
index d1481fb46c..317c01134a 100644
--- a/src/common/compat_openssl.h
+++ b/src/lib/crypt_ops/compat_openssl.h
@@ -1,14 +1,14 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_COMPAT_OPENSSL_H
#define TOR_COMPAT_OPENSSL_H
#include <openssl/opensslv.h>
-#include "crypto_openssl_mgt.h"
+#include "lib/crypt_ops/crypto_openssl_mgt.h"
/**
* \file compat_openssl.h
diff --git a/src/lib/crypt_ops/crypto.c b/src/lib/crypt_ops/crypto.c
new file mode 100644
index 0000000000..48574016bf
--- /dev/null
+++ b/src/lib/crypt_ops/crypto.c
@@ -0,0 +1,509 @@
+/* Copyright (c) 2001, Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file crypto.c
+ * \brief Wrapper functions to present a consistent interface to
+ * public-key and symmetric cryptography operations from OpenSSL and
+ * other places.
+ **/
+
+#include "orconfig.h"
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <windows.h>
+#include <wincrypt.h>
+/* Windows defines this; so does OpenSSL 0.9.8h and later. We don't actually
+ * use either definition. */
+#undef OCSP_RESPONSE
+#endif /* defined(_WIN32) */
+
+#define CRYPTO_PRIVATE
+#include "lib/crypt_ops/compat_openssl.h"
+#include "lib/crypt_ops/crypto.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "lib/crypt_ops/crypto_digest.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_rsa.h"
+#include "lib/crypt_ops/crypto_util.h"
+
+DISABLE_GCC_WARNING(redundant-decls)
+
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/engine.h>
+#include <openssl/bn.h>
+#include <openssl/dh.h>
+#include <openssl/conf.h>
+#include <openssl/hmac.h>
+#include <openssl/ssl.h>
+
+ENABLE_GCC_WARNING(redundant-decls)
+
+#if __GNUC__ && GCC_VERSION >= 402
+#if GCC_VERSION >= 406
+#pragma GCC diagnostic pop
+#else
+#pragma GCC diagnostic warning "-Wredundant-decls"
+#endif
+#endif /* __GNUC__ && GCC_VERSION >= 402 */
+
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/cc/torint.h"
+#include "lib/crypt_ops/aes.h"
+#include "lib/encoding/binascii.h"
+
+#include "keccak-tiny/keccak-tiny.h"
+
+#include "siphash.h"
+
+#include <string.h>
+
+/** Boolean: has OpenSSL's crypto been initialized? */
+static int crypto_early_initialized_ = 0;
+
+/** Boolean: has OpenSSL's crypto been initialized? */
+static int crypto_global_initialized_ = 0;
+
+#ifndef DISABLE_ENGINES
+/** Log any OpenSSL engines we're using at NOTICE. */
+static void
+log_engine(const char *fn, ENGINE *e)
+{
+ if (e) {
+ const char *name, *id;
+ name = ENGINE_get_name(e);
+ id = ENGINE_get_id(e);
+ log_notice(LD_CRYPTO, "Default OpenSSL engine for %s is %s [%s]",
+ fn, name?name:"?", id?id:"?");
+ } else {
+ log_info(LD_CRYPTO, "Using default implementation for %s", fn);
+ }
+}
+#endif /* !defined(DISABLE_ENGINES) */
+
+#ifndef DISABLE_ENGINES
+/** Try to load an engine in a shared library via fully qualified path.
+ */
+static ENGINE *
+try_load_engine(const char *path, const char *engine)
+{
+ ENGINE *e = ENGINE_by_id("dynamic");
+ if (e) {
+ if (!ENGINE_ctrl_cmd_string(e, "ID", engine, 0) ||
+ !ENGINE_ctrl_cmd_string(e, "DIR_LOAD", "2", 0) ||
+ !ENGINE_ctrl_cmd_string(e, "DIR_ADD", path, 0) ||
+ !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
+ ENGINE_free(e);
+ e = NULL;
+ }
+ }
+ return e;
+}
+#endif /* !defined(DISABLE_ENGINES) */
+
+static int have_seeded_siphash = 0;
+
+/** Set up the siphash key if we haven't already done so. */
+int
+crypto_init_siphash_key(void)
+{
+ struct sipkey key;
+ if (have_seeded_siphash)
+ return 0;
+
+ crypto_rand((char*) &key, sizeof(key));
+ siphash_set_global_key(&key);
+ have_seeded_siphash = 1;
+ return 0;
+}
+
+/** Initialize the crypto library. Return 0 on success, -1 on failure.
+ */
+int
+crypto_early_init(void)
+{
+ if (!crypto_early_initialized_) {
+
+ crypto_early_initialized_ = 1;
+
+#ifdef OPENSSL_1_1_API
+ OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS |
+ OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
+ OPENSSL_INIT_ADD_ALL_CIPHERS |
+ OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
+#else
+ ERR_load_crypto_strings();
+ OpenSSL_add_all_algorithms();
+#endif
+
+ setup_openssl_threading();
+
+ unsigned long version_num = OpenSSL_version_num();
+ const char *version_str = OpenSSL_version(OPENSSL_VERSION);
+ if (version_num == OPENSSL_VERSION_NUMBER &&
+ !strcmp(version_str, OPENSSL_VERSION_TEXT)) {
+ log_info(LD_CRYPTO, "OpenSSL version matches version from headers "
+ "(%lx: %s).", version_num, version_str);
+ } else {
+ log_warn(LD_CRYPTO, "OpenSSL version from headers does not match the "
+ "version we're running with. If you get weird crashes, that "
+ "might be why. (Compiled with %lx: %s; running with %lx: %s).",
+ (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
+ version_num, version_str);
+ }
+
+ crypto_force_rand_ssleay();
+
+ if (crypto_seed_rng() < 0)
+ return -1;
+ if (crypto_init_siphash_key() < 0)
+ return -1;
+
+ curve25519_init();
+ ed25519_init();
+ }
+ return 0;
+}
+
+/** Initialize the crypto library. Return 0 on success, -1 on failure.
+ */
+int
+crypto_global_init(int useAccel, const char *accelName, const char *accelDir)
+{
+ if (!crypto_global_initialized_) {
+ if (crypto_early_init() < 0)
+ return -1;
+
+ crypto_global_initialized_ = 1;
+
+ if (useAccel > 0) {
+#ifdef DISABLE_ENGINES
+ (void)accelName;
+ (void)accelDir;
+ log_warn(LD_CRYPTO, "No OpenSSL hardware acceleration support enabled.");
+#else
+ ENGINE *e = NULL;
+
+ log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
+ ENGINE_load_builtin_engines();
+ ENGINE_register_all_complete();
+
+ if (accelName) {
+ if (accelDir) {
+ log_info(LD_CRYPTO, "Trying to load dynamic OpenSSL engine \"%s\""
+ " via path \"%s\".", accelName, accelDir);
+ e = try_load_engine(accelName, accelDir);
+ } else {
+ log_info(LD_CRYPTO, "Initializing dynamic OpenSSL engine \"%s\""
+ " acceleration support.", accelName);
+ e = ENGINE_by_id(accelName);
+ }
+ if (!e) {
+ log_warn(LD_CRYPTO, "Unable to load dynamic OpenSSL engine \"%s\".",
+ accelName);
+ } else {
+ log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".",
+ accelName);
+ }
+ }
+ if (e) {
+ log_info(LD_CRYPTO, "Loaded OpenSSL hardware acceleration engine,"
+ " setting default ciphers.");
+ ENGINE_set_default(e, ENGINE_METHOD_ALL);
+ }
+ /* Log, if available, the intersection of the set of algorithms
+ used by Tor and the set of algorithms available in the engine */
+ log_engine("RSA", ENGINE_get_default_RSA());
+ log_engine("DH", ENGINE_get_default_DH());
+#ifdef OPENSSL_1_1_API
+ log_engine("EC", ENGINE_get_default_EC());
+#else
+ log_engine("ECDH", ENGINE_get_default_ECDH());
+ log_engine("ECDSA", ENGINE_get_default_ECDSA());
+#endif /* defined(OPENSSL_1_1_API) */
+ log_engine("RAND", ENGINE_get_default_RAND());
+ log_engine("RAND (which we will not use)", ENGINE_get_default_RAND());
+ log_engine("SHA1", ENGINE_get_digest_engine(NID_sha1));
+ log_engine("3DES-CBC", ENGINE_get_cipher_engine(NID_des_ede3_cbc));
+ log_engine("AES-128-ECB", ENGINE_get_cipher_engine(NID_aes_128_ecb));
+ log_engine("AES-128-CBC", ENGINE_get_cipher_engine(NID_aes_128_cbc));
+#ifdef NID_aes_128_ctr
+ log_engine("AES-128-CTR", ENGINE_get_cipher_engine(NID_aes_128_ctr));
+#endif
+#ifdef NID_aes_128_gcm
+ log_engine("AES-128-GCM", ENGINE_get_cipher_engine(NID_aes_128_gcm));
+#endif
+ log_engine("AES-256-CBC", ENGINE_get_cipher_engine(NID_aes_256_cbc));
+#ifdef NID_aes_256_gcm
+ log_engine("AES-256-GCM", ENGINE_get_cipher_engine(NID_aes_256_gcm));
+#endif
+
+#endif /* defined(DISABLE_ENGINES) */
+ } else {
+ log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
+ }
+
+ if (crypto_force_rand_ssleay()) {
+ if (crypto_seed_rng() < 0)
+ return -1;
+ }
+
+ evaluate_evp_for_aes(-1);
+ evaluate_ctr_for_aes();
+ }
+ return 0;
+}
+
+/** Free crypto resources held by this thread. */
+void
+crypto_thread_cleanup(void)
+{
+#ifndef NEW_THREAD_API
+ ERR_remove_thread_state(NULL);
+#endif
+}
+
+/** Allocate and return a new symmetric cipher using the provided key and iv.
+ * The key is <b>bits</b> bits long; the IV is CIPHER_IV_LEN bytes. Both
+ * must be provided. Key length must be 128, 192, or 256 */
+crypto_cipher_t *
+crypto_cipher_new_with_iv_and_bits(const uint8_t *key,
+ const uint8_t *iv,
+ int bits)
+{
+ tor_assert(key);
+ tor_assert(iv);
+
+ return aes_new_cipher((const uint8_t*)key, (const uint8_t*)iv, bits);
+}
+
+/** Allocate and return a new symmetric cipher using the provided key and iv.
+ * The key is CIPHER_KEY_LEN bytes; the IV is CIPHER_IV_LEN bytes. Both
+ * must be provided.
+ */
+crypto_cipher_t *
+crypto_cipher_new_with_iv(const char *key, const char *iv)
+{
+ return crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)iv,
+ 128);
+}
+
+/** Return a new crypto_cipher_t with the provided <b>key</b> and an IV of all
+ * zero bytes and key length <b>bits</b>. Key length must be 128, 192, or
+ * 256. */
+crypto_cipher_t *
+crypto_cipher_new_with_bits(const char *key, int bits)
+{
+ char zeroiv[CIPHER_IV_LEN];
+ memset(zeroiv, 0, sizeof(zeroiv));
+ return crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)zeroiv,
+ bits);
+}
+
+/** Return a new crypto_cipher_t with the provided <b>key</b> (of
+ * CIPHER_KEY_LEN bytes) and an IV of all zero bytes. */
+crypto_cipher_t *
+crypto_cipher_new(const char *key)
+{
+ return crypto_cipher_new_with_bits(key, 128);
+}
+
+/** Free a symmetric cipher.
+ */
+void
+crypto_cipher_free_(crypto_cipher_t *env)
+{
+ if (!env)
+ return;
+
+ aes_cipher_free(env);
+}
+
+/** Copy <b>in</b> to the <b>outlen</b>-byte buffer <b>out</b>, adding spaces
+ * every four characters. */
+void
+crypto_add_spaces_to_fp(char *out, size_t outlen, const char *in)
+{
+ int n = 0;
+ char *end = out+outlen;
+ tor_assert(outlen < SIZE_T_CEILING);
+
+ while (*in && out<end) {
+ *out++ = *in++;
+ if (++n == 4 && *in && out<end) {
+ n = 0;
+ *out++ = ' ';
+ }
+ }
+ tor_assert(out<end);
+ *out = '\0';
+}
+
+/* symmetric crypto */
+
+/** Encrypt <b>fromlen</b> bytes from <b>from</b> using the cipher
+ * <b>env</b>; on success, store the result to <b>to</b> and return 0.
+ * Does not check for failure.
+ */
+int
+crypto_cipher_encrypt(crypto_cipher_t *env, char *to,
+ const char *from, size_t fromlen)
+{
+ tor_assert(env);
+ tor_assert(env);
+ tor_assert(from);
+ tor_assert(fromlen);
+ tor_assert(to);
+ tor_assert(fromlen < SIZE_T_CEILING);
+
+ memcpy(to, from, fromlen);
+ aes_crypt_inplace(env, to, fromlen);
+ return 0;
+}
+
+/** Decrypt <b>fromlen</b> bytes from <b>from</b> using the cipher
+ * <b>env</b>; on success, store the result to <b>to</b> and return 0.
+ * Does not check for failure.
+ */
+int
+crypto_cipher_decrypt(crypto_cipher_t *env, char *to,
+ const char *from, size_t fromlen)
+{
+ tor_assert(env);
+ tor_assert(from);
+ tor_assert(to);
+ tor_assert(fromlen < SIZE_T_CEILING);
+
+ memcpy(to, from, fromlen);
+ aes_crypt_inplace(env, to, fromlen);
+ return 0;
+}
+
+/** Encrypt <b>len</b> bytes on <b>from</b> using the cipher in <b>env</b>;
+ * on success. Does not check for failure.
+ */
+void
+crypto_cipher_crypt_inplace(crypto_cipher_t *env, char *buf, size_t len)
+{
+ tor_assert(len < SIZE_T_CEILING);
+ aes_crypt_inplace(env, buf, len);
+}
+
+/** Encrypt <b>fromlen</b> bytes (at least 1) from <b>from</b> with the key in
+ * <b>key</b> to the buffer in <b>to</b> of length
+ * <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> plus
+ * CIPHER_IV_LEN bytes for the initialization vector. On success, return the
+ * number of bytes written, on failure, return -1.
+ */
+int
+crypto_cipher_encrypt_with_iv(const char *key,
+ char *to, size_t tolen,
+ const char *from, size_t fromlen)
+{
+ crypto_cipher_t *cipher;
+ tor_assert(from);
+ tor_assert(to);
+ tor_assert(fromlen < INT_MAX);
+
+ if (fromlen < 1)
+ return -1;
+ if (tolen < fromlen + CIPHER_IV_LEN)
+ return -1;
+
+ char iv[CIPHER_IV_LEN];
+ crypto_rand(iv, sizeof(iv));
+ cipher = crypto_cipher_new_with_iv(key, iv);
+
+ memcpy(to, iv, CIPHER_IV_LEN);
+ crypto_cipher_encrypt(cipher, to+CIPHER_IV_LEN, from, fromlen);
+ crypto_cipher_free(cipher);
+ memwipe(iv, 0, sizeof(iv));
+ return (int)(fromlen + CIPHER_IV_LEN);
+}
+
+/** Decrypt <b>fromlen</b> bytes (at least 1+CIPHER_IV_LEN) from <b>from</b>
+ * with the key in <b>key</b> to the buffer in <b>to</b> of length
+ * <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> minus
+ * CIPHER_IV_LEN bytes for the initialization vector. On success, return the
+ * number of bytes written, on failure, return -1.
+ */
+int
+crypto_cipher_decrypt_with_iv(const char *key,
+ char *to, size_t tolen,
+ const char *from, size_t fromlen)
+{
+ crypto_cipher_t *cipher;
+ tor_assert(key);
+ tor_assert(from);
+ tor_assert(to);
+ tor_assert(fromlen < INT_MAX);
+
+ if (fromlen <= CIPHER_IV_LEN)
+ return -1;
+ if (tolen < fromlen - CIPHER_IV_LEN)
+ return -1;
+
+ cipher = crypto_cipher_new_with_iv(key, from);
+
+ crypto_cipher_encrypt(cipher, to, from+CIPHER_IV_LEN, fromlen-CIPHER_IV_LEN);
+ crypto_cipher_free(cipher);
+ return (int)(fromlen - CIPHER_IV_LEN);
+}
+
+/** @{ */
+/** Uninitialize the crypto library. Return 0 on success. Does not detect
+ * failure.
+ */
+int
+crypto_global_cleanup(void)
+{
+#ifndef OPENSSL_1_1_API
+ EVP_cleanup();
+#endif
+#ifndef NEW_THREAD_API
+ ERR_remove_thread_state(NULL);
+#endif
+#ifndef OPENSSL_1_1_API
+ ERR_free_strings();
+#endif
+
+ crypto_dh_free_all();
+
+#ifndef DISABLE_ENGINES
+#ifndef OPENSSL_1_1_API
+ ENGINE_cleanup();
+#endif
+#endif
+
+ CONF_modules_unload(1);
+#ifndef OPENSSL_1_1_API
+ CRYPTO_cleanup_all_ex_data();
+#endif
+
+ crypto_openssl_free_all();
+
+ crypto_early_initialized_ = 0;
+ crypto_global_initialized_ = 0;
+ have_seeded_siphash = 0;
+ siphash_unset_global_key();
+
+ return 0;
+}
+
+/** @} */
diff --git a/src/common/crypto.h b/src/lib/crypt_ops/crypto.h
index c773557310..3a0b330be6 100644
--- a/src/common/crypto.h
+++ b/src/lib/crypt_ops/crypto.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,10 +16,8 @@
#include "orconfig.h"
#include <stdio.h>
-#include "torint.h"
-#include "compat.h"
-#include "util.h"
-#include "crypto_rsa.h"
+#include "lib/cc/torint.h"
+#include "lib/crypt_ops/crypto_rsa.h"
/** Length of our symmetric cipher's keys of 128-bit. */
#define CIPHER_KEY_LEN 16
@@ -27,15 +25,12 @@
#define CIPHER_IV_LEN 16
/** Length of our symmetric cipher's keys of 256-bit. */
#define CIPHER256_KEY_LEN 32
-/** Length of our DH keys. */
-#define DH_BYTES (1024/8)
/** Length of encoded public key fingerprints, including space; but not
* including terminating NUL. */
#define FINGERPRINT_LEN 49
typedef struct aes_cnt_cipher crypto_cipher_t;
-typedef struct crypto_dh_t crypto_dh_t;
/* global state */
int crypto_init_siphash_key(void);
@@ -43,15 +38,11 @@ int crypto_early_init(void) ATTR_WUR;
int crypto_global_init(int hardwareAccel,
const char *accelName,
const char *accelPath) ATTR_WUR;
-#ifdef USE_DMALLOC
-int crypto_use_tor_alloc_functions(void);
-#endif
void crypto_thread_cleanup(void);
int crypto_global_cleanup(void);
/* environment setup */
-void crypto_set_tls_dh_prime(void);
crypto_cipher_t *crypto_cipher_new(const char *key);
crypto_cipher_t *crypto_cipher_new_with_bits(const char *key, int bits);
crypto_cipher_t *crypto_cipher_new_with_iv(const char *key, const char *iv);
@@ -78,37 +69,6 @@ int crypto_cipher_decrypt_with_iv(const char *key,
char *to, size_t tolen,
const char *from, size_t fromlen);
-/* Key negotiation */
-#define DH_TYPE_CIRCUIT 1
-#define DH_TYPE_REND 2
-#define DH_TYPE_TLS 3
-crypto_dh_t *crypto_dh_new(int dh_type);
-crypto_dh_t *crypto_dh_dup(const crypto_dh_t *dh);
-int crypto_dh_get_bytes(crypto_dh_t *dh);
-int crypto_dh_generate_public(crypto_dh_t *dh);
-int crypto_dh_get_public(crypto_dh_t *dh, char *pubkey_out,
- size_t pubkey_out_len);
-ssize_t crypto_dh_compute_secret(int severity, crypto_dh_t *dh,
- const char *pubkey, size_t pubkey_len,
- char *secret_out, size_t secret_out_len);
-void crypto_dh_free_(crypto_dh_t *dh);
-#define crypto_dh_free(dh) FREE_AND_NULL(crypto_dh_t, crypto_dh_free_, (dh))
-
-int crypto_expand_key_material_TAP(const uint8_t *key_in,
- size_t key_in_len,
- uint8_t *key_out, size_t key_out_len);
-int crypto_expand_key_material_rfc5869_sha256(
- const uint8_t *key_in, size_t key_in_len,
- const uint8_t *salt_in, size_t salt_in_len,
- const uint8_t *info_in, size_t info_in_len,
- uint8_t *key_out, size_t key_out_len);
-
-/* Prototypes for private functions only used by tortls.c, crypto.c, and the
- * unit tests. */
-struct dh_st;
-struct dh_st *crypto_dh_get_dh_(crypto_dh_t *dh);
-
void crypto_add_spaces_to_fp(char *out, size_t outlen, const char *in);
#endif /* !defined(TOR_CRYPTO_H) */
-
diff --git a/src/common/crypto_curve25519.c b/src/lib/crypt_ops/crypto_curve25519.c
index 996d94c6e2..09f492e544 100644
--- a/src/common/crypto_curve25519.c
+++ b/src/lib/crypt_ops/crypto_curve25519.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -20,17 +20,19 @@
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
-#include "container.h"
-#include "crypto_curve25519.h"
-#include "crypto_digest.h"
-#include "crypto_format.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "util.h"
-#include "torlog.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "lib/crypt_ops/crypto_digest.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
#include "ed25519/donna/ed25519_donna_tor.h"
+#include <string.h>
+
/* ==============================
Part 1: wrap a suitable curve25519 implementation as curve25519_impl
============================== */
@@ -356,4 +358,3 @@ curve25519_init(void)
{
pick_curve25519_basepoint_impl();
}
-
diff --git a/src/common/crypto_curve25519.h b/src/lib/crypt_ops/crypto_curve25519.h
index 4834fa0836..acb36fde3b 100644
--- a/src/common/crypto_curve25519.h
+++ b/src/lib/crypt_ops/crypto_curve25519.h
@@ -1,20 +1,14 @@
-/* Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_CRYPTO_CURVE25519_H
#define TOR_CRYPTO_CURVE25519_H
-#include "testsupport.h"
-#include "torint.h"
-#include "crypto_digest.h"
-#include "crypto_openssl_mgt.h"
-
-/** Length of a curve25519 public key when encoded. */
-#define CURVE25519_PUBKEY_LEN 32
-/** Length of a curve25519 secret key when encoded. */
-#define CURVE25519_SECKEY_LEN 32
-/** Length of the result of a curve25519 handshake. */
-#define CURVE25519_OUTPUT_LEN 32
+#include "lib/testsupport/testsupport.h"
+#include "lib/cc/torint.h"
+#include "lib/crypt_ops/crypto_digest.h"
+#include "lib/crypt_ops/crypto_openssl_mgt.h"
+#include "lib/defs/x25519_sizes.h"
/** Wrapper type for a curve25519 public key.
*
@@ -75,8 +69,6 @@ STATIC int curve25519_impl(uint8_t *output, const uint8_t *secret,
STATIC int curve25519_basepoint_impl(uint8_t *output, const uint8_t *secret);
#endif /* defined(CRYPTO_CURVE25519_PRIVATE) */
-#define CURVE25519_BASE64_PADDED_LEN 44
-
int curve25519_public_from_base64(curve25519_public_key_t *pkey,
const char *input);
int curve25519_public_to_base64(char *output,
@@ -86,4 +78,3 @@ void curve25519_set_impl_params(int use_ed);
void curve25519_init(void);
#endif /* !defined(TOR_CRYPTO_CURVE25519_H) */
-
diff --git a/src/lib/crypt_ops/crypto_dh.c b/src/lib/crypt_ops/crypto_dh.c
new file mode 100644
index 0000000000..c37e286daf
--- /dev/null
+++ b/src/lib/crypt_ops/crypto_dh.c
@@ -0,0 +1,511 @@
+/* Copyright (c) 2001, Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file crypto_dh.c
+ * \brief Block of functions related with DH utilities and operations.
+ **/
+
+#include "lib/crypt_ops/compat_openssl.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "lib/crypt_ops/crypto_digest.h"
+#include "lib/crypt_ops/crypto_hkdf.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+
+DISABLE_GCC_WARNING(redundant-decls)
+
+#include <openssl/dh.h>
+
+ENABLE_GCC_WARNING(redundant-decls)
+
+#include <openssl/bn.h>
+#include <string.h>
+
+/** A structure to hold the first half (x, g^x) of a Diffie-Hellman handshake
+ * while we're waiting for the second.*/
+struct crypto_dh_t {
+ DH *dh; /**< The openssl DH object */
+};
+
+static int tor_check_dh_key(int severity, const BIGNUM *bn);
+
+/** Used by tortls.c: Get the DH* from a crypto_dh_t.
+ */
+DH *
+crypto_dh_get_dh_(crypto_dh_t *dh)
+{
+ return dh->dh;
+}
+
+/** Our DH 'g' parameter */
+#define DH_GENERATOR 2
+
+/** Shared P parameter for our circuit-crypto DH key exchanges. */
+static BIGNUM *dh_param_p = NULL;
+/** Shared P parameter for our TLS DH key exchanges. */
+static BIGNUM *dh_param_p_tls = NULL;
+/** Shared G parameter for our DH key exchanges. */
+static BIGNUM *dh_param_g = NULL;
+
+/** Validate a given set of Diffie-Hellman parameters. This is moderately
+ * computationally expensive (milliseconds), so should only be called when
+ * the DH parameters change. Returns 0 on success, * -1 on failure.
+ */
+static int
+crypto_validate_dh_params(const BIGNUM *p, const BIGNUM *g)
+{
+ DH *dh = NULL;
+ int ret = -1;
+
+ /* Copy into a temporary DH object, just so that DH_check() can be called. */
+ if (!(dh = DH_new()))
+ goto out;
+#ifdef OPENSSL_1_1_API
+ BIGNUM *dh_p, *dh_g;
+ if (!(dh_p = BN_dup(p)))
+ goto out;
+ if (!(dh_g = BN_dup(g)))
+ goto out;
+ if (!DH_set0_pqg(dh, dh_p, NULL, dh_g))
+ goto out;
+#else /* !(defined(OPENSSL_1_1_API)) */
+ if (!(dh->p = BN_dup(p)))
+ goto out;
+ if (!(dh->g = BN_dup(g)))
+ goto out;
+#endif /* defined(OPENSSL_1_1_API) */
+
+ /* Perform the validation. */
+ int codes = 0;
+ if (!DH_check(dh, &codes))
+ goto out;
+ if (BN_is_word(g, DH_GENERATOR_2)) {
+ /* Per https://wiki.openssl.org/index.php/Diffie-Hellman_parameters
+ *
+ * OpenSSL checks the prime is congruent to 11 when g = 2; while the
+ * IETF's primes are congruent to 23 when g = 2.
+ */
+ BN_ULONG residue = BN_mod_word(p, 24);
+ if (residue == 11 || residue == 23)
+ codes &= ~DH_NOT_SUITABLE_GENERATOR;
+ }
+ if (codes != 0) /* Specifics on why the params suck is irrelevant. */
+ goto out;
+
+ /* Things are probably not evil. */
+ ret = 0;
+
+ out:
+ if (dh)
+ DH_free(dh);
+ return ret;
+}
+
+/** Set the global Diffie-Hellman generator, used for both TLS and internal
+ * DH stuff.
+ */
+static void
+crypto_set_dh_generator(void)
+{
+ BIGNUM *generator;
+ int r;
+
+ if (dh_param_g)
+ return;
+
+ generator = BN_new();
+ tor_assert(generator);
+
+ r = BN_set_word(generator, DH_GENERATOR);
+ tor_assert(r);
+
+ dh_param_g = generator;
+}
+
+/** Set the global TLS Diffie-Hellman modulus. Use the Apache mod_ssl DH
+ * modulus. */
+void
+crypto_set_tls_dh_prime(void)
+{
+ BIGNUM *tls_prime = NULL;
+ int r;
+
+ /* If the space is occupied, free the previous TLS DH prime */
+ if (BUG(dh_param_p_tls)) {
+ /* LCOV_EXCL_START
+ *
+ * We shouldn't be calling this twice.
+ */
+ BN_clear_free(dh_param_p_tls);
+ dh_param_p_tls = NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ tls_prime = BN_new();
+ tor_assert(tls_prime);
+
+ /* This is the 1024-bit safe prime that Apache uses for its DH stuff; see
+ * modules/ssl/ssl_engine_dh.c; Apache also uses a generator of 2 with this
+ * prime.
+ */
+ r = BN_hex2bn(&tls_prime,
+ "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98"
+ "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A"
+ "467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7"
+ "DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68"
+ "B0E7393E0F24218EB3");
+ tor_assert(r);
+
+ tor_assert(tls_prime);
+
+ dh_param_p_tls = tls_prime;
+ crypto_set_dh_generator();
+ tor_assert(0 == crypto_validate_dh_params(dh_param_p_tls, dh_param_g));
+}
+
+/** Initialize dh_param_p and dh_param_g if they are not already
+ * set. */
+static void
+init_dh_param(void)
+{
+ BIGNUM *circuit_dh_prime;
+ int r;
+ if (BUG(dh_param_p && dh_param_g))
+ return; // LCOV_EXCL_LINE This function isn't supposed to be called twice.
+
+ circuit_dh_prime = BN_new();
+ tor_assert(circuit_dh_prime);
+
+ /* This is from rfc2409, section 6.2. It's a safe prime, and
+ supposedly it equals:
+ 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }.
+ */
+ r = BN_hex2bn(&circuit_dh_prime,
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
+ "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
+ "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
+ "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
+ "49286651ECE65381FFFFFFFFFFFFFFFF");
+ tor_assert(r);
+
+ /* Set the new values as the global DH parameters. */
+ dh_param_p = circuit_dh_prime;
+ crypto_set_dh_generator();
+ tor_assert(0 == crypto_validate_dh_params(dh_param_p, dh_param_g));
+
+ if (!dh_param_p_tls) {
+ crypto_set_tls_dh_prime();
+ }
+}
+
+/** 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.
+ */
+#define DH_PRIVATE_KEY_BITS 320
+
+/** Allocate and return a new DH object for a key exchange. Returns NULL on
+ * failure.
+ */
+crypto_dh_t *
+crypto_dh_new(int dh_type)
+{
+ crypto_dh_t *res = tor_malloc_zero(sizeof(crypto_dh_t));
+
+ tor_assert(dh_type == DH_TYPE_CIRCUIT || dh_type == DH_TYPE_TLS ||
+ dh_type == DH_TYPE_REND);
+
+ if (!dh_param_p)
+ init_dh_param();
+
+ if (!(res->dh = DH_new()))
+ goto err;
+
+#ifdef OPENSSL_1_1_API
+ BIGNUM *dh_p = NULL, *dh_g = NULL;
+
+ if (dh_type == DH_TYPE_TLS) {
+ dh_p = BN_dup(dh_param_p_tls);
+ } else {
+ dh_p = BN_dup(dh_param_p);
+ }
+ if (!dh_p)
+ goto err;
+
+ dh_g = BN_dup(dh_param_g);
+ if (!dh_g) {
+ BN_free(dh_p);
+ goto err;
+ }
+
+ if (!DH_set0_pqg(res->dh, dh_p, NULL, dh_g)) {
+ goto err;
+ }
+
+ if (!DH_set_length(res->dh, DH_PRIVATE_KEY_BITS))
+ goto err;
+#else /* !(defined(OPENSSL_1_1_API)) */
+ if (dh_type == DH_TYPE_TLS) {
+ if (!(res->dh->p = BN_dup(dh_param_p_tls)))
+ goto err;
+ } else {
+ if (!(res->dh->p = BN_dup(dh_param_p)))
+ goto err;
+ }
+
+ if (!(res->dh->g = BN_dup(dh_param_g)))
+ goto err;
+
+ res->dh->length = DH_PRIVATE_KEY_BITS;
+#endif /* defined(OPENSSL_1_1_API) */
+
+ return res;
+
+ /* LCOV_EXCL_START
+ * This error condition is only reached when an allocation fails */
+ err:
+ crypto_log_errors(LOG_WARN, "creating DH object");
+ if (res->dh) DH_free(res->dh); /* frees p and g too */
+ tor_free(res);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+}
+
+/** Return a copy of <b>dh</b>, sharing its internal state. */
+crypto_dh_t *
+crypto_dh_dup(const crypto_dh_t *dh)
+{
+ crypto_dh_t *dh_new = tor_malloc_zero(sizeof(crypto_dh_t));
+ tor_assert(dh);
+ tor_assert(dh->dh);
+ dh_new->dh = dh->dh;
+ DH_up_ref(dh->dh);
+ return dh_new;
+}
+
+/** Return the length of the DH key in <b>dh</b>, in bytes.
+ */
+int
+crypto_dh_get_bytes(crypto_dh_t *dh)
+{
+ tor_assert(dh);
+ return DH_size(dh->dh);
+}
+
+/** Generate \<x,g^x\> for our part of the key exchange. Return 0 on
+ * success, -1 on failure.
+ */
+int
+crypto_dh_generate_public(crypto_dh_t *dh)
+{
+#ifndef OPENSSL_1_1_API
+ again:
+#endif
+ if (!DH_generate_key(dh->dh)) {
+ /* LCOV_EXCL_START
+ * To test this we would need some way to tell openssl to break DH. */
+ crypto_log_errors(LOG_WARN, "generating DH key");
+ return -1;
+ /* LCOV_EXCL_STOP */
+ }
+#ifdef OPENSSL_1_1_API
+ /* OpenSSL 1.1.x doesn't appear to let you regenerate a DH key, without
+ * recreating the DH object. I have no idea what sort of aliasing madness
+ * can occur here, so do the check, and just bail on failure.
+ */
+ const BIGNUM *pub_key, *priv_key;
+ DH_get0_key(dh->dh, &pub_key, &priv_key);
+ if (tor_check_dh_key(LOG_WARN, pub_key)<0) {
+ log_warn(LD_CRYPTO, "Weird! Our own DH key was invalid. I guess once-in-"
+ "the-universe chances really do happen. Treating as a failure.");
+ return -1;
+ }
+#else /* !(defined(OPENSSL_1_1_API)) */
+ if (tor_check_dh_key(LOG_WARN, dh->dh->pub_key)<0) {
+ /* LCOV_EXCL_START
+ * If this happens, then openssl's DH implementation is busted. */
+ log_warn(LD_CRYPTO, "Weird! Our own DH key was invalid. I guess once-in-"
+ "the-universe chances really do happen. Trying again.");
+ /* Free and clear the keys, so OpenSSL will actually try again. */
+ BN_clear_free(dh->dh->pub_key);
+ BN_clear_free(dh->dh->priv_key);
+ dh->dh->pub_key = dh->dh->priv_key = NULL;
+ goto again;
+ /* LCOV_EXCL_STOP */
+ }
+#endif /* defined(OPENSSL_1_1_API) */
+ return 0;
+}
+
+/** Generate g^x as necessary, and write the g^x for the key exchange
+ * as a <b>pubkey_len</b>-byte value into <b>pubkey</b>. Return 0 on
+ * success, -1 on failure. <b>pubkey_len</b> must be \>= DH1024_KEY_LEN.
+ */
+int
+crypto_dh_get_public(crypto_dh_t *dh, char *pubkey, size_t pubkey_len)
+{
+ int bytes;
+ tor_assert(dh);
+
+ const BIGNUM *dh_pub;
+
+#ifdef OPENSSL_1_1_API
+ const BIGNUM *dh_priv;
+ DH_get0_key(dh->dh, &dh_pub, &dh_priv);
+#else
+ dh_pub = dh->dh->pub_key;
+#endif /* defined(OPENSSL_1_1_API) */
+
+ if (!dh_pub) {
+ if (crypto_dh_generate_public(dh)<0)
+ return -1;
+ else {
+#ifdef OPENSSL_1_1_API
+ DH_get0_key(dh->dh, &dh_pub, &dh_priv);
+#else
+ dh_pub = dh->dh->pub_key;
+#endif
+ }
+ }
+
+ tor_assert(dh_pub);
+ bytes = BN_num_bytes(dh_pub);
+ tor_assert(bytes >= 0);
+ if (pubkey_len < (size_t)bytes) {
+ log_warn(LD_CRYPTO,
+ "Weird! pubkey_len (%d) was smaller than DH1024_KEY_LEN (%d)",
+ (int) pubkey_len, bytes);
+ return -1;
+ }
+
+ memset(pubkey, 0, pubkey_len);
+ BN_bn2bin(dh_pub, (unsigned char*)(pubkey+(pubkey_len-bytes)));
+
+ return 0;
+}
+
+/** Check for bad Diffie-Hellman public keys (g^x). Return 0 if the key is
+ * okay (in the subgroup [2,p-2]), or -1 if it's bad.
+ * See http://www.cl.cam.ac.uk/ftp/users/rja14/psandqs.ps.gz for some tips.
+ */
+static int
+tor_check_dh_key(int severity, const BIGNUM *bn)
+{
+ BIGNUM *x;
+ char *s;
+ tor_assert(bn);
+ x = BN_new();
+ tor_assert(x);
+ if (BUG(!dh_param_p))
+ init_dh_param(); //LCOV_EXCL_LINE we already checked whether we did this.
+ BN_set_word(x, 1);
+ if (BN_cmp(bn,x)<=0) {
+ log_fn(severity, LD_CRYPTO, "DH key must be at least 2.");
+ goto err;
+ }
+ BN_copy(x,dh_param_p);
+ BN_sub_word(x, 1);
+ if (BN_cmp(bn,x)>=0) {
+ log_fn(severity, LD_CRYPTO, "DH key must be at most p-2.");
+ goto err;
+ }
+ BN_clear_free(x);
+ return 0;
+ err:
+ BN_clear_free(x);
+ s = BN_bn2hex(bn);
+ log_fn(severity, LD_CRYPTO, "Rejecting insecure DH key [%s]", s);
+ OPENSSL_free(s);
+ return -1;
+}
+
+/** Given a DH key exchange object, and our peer's value of g^y (as a
+ * <b>pubkey_len</b>-byte value in <b>pubkey</b>) generate
+ * <b>secret_bytes_out</b> bytes of shared key material and write them
+ * to <b>secret_out</b>. Return the number of bytes generated on success,
+ * or -1 on failure.
+ *
+ * (We generate key material by computing
+ * SHA1( g^xy || "\x00" ) || SHA1( g^xy || "\x01" ) || ...
+ * where || is concatenation.)
+ */
+ssize_t
+crypto_dh_compute_secret(int severity, crypto_dh_t *dh,
+ const char *pubkey, size_t pubkey_len,
+ char *secret_out, size_t secret_bytes_out)
+{
+ char *secret_tmp = NULL;
+ BIGNUM *pubkey_bn = NULL;
+ size_t secret_len=0, secret_tmp_len=0;
+ int result=0;
+ tor_assert(dh);
+ tor_assert(secret_bytes_out/DIGEST_LEN <= 255);
+ tor_assert(pubkey_len < INT_MAX);
+
+ if (!(pubkey_bn = BN_bin2bn((const unsigned char*)pubkey,
+ (int)pubkey_len, NULL)))
+ goto error;
+ if (tor_check_dh_key(severity, pubkey_bn)<0) {
+ /* Check for invalid public keys. */
+ log_fn(severity, LD_CRYPTO,"Rejected invalid g^x");
+ goto error;
+ }
+ secret_tmp_len = crypto_dh_get_bytes(dh);
+ secret_tmp = tor_malloc(secret_tmp_len);
+ result = DH_compute_key((unsigned char*)secret_tmp, pubkey_bn, dh->dh);
+ if (result < 0) {
+ log_warn(LD_CRYPTO,"DH_compute_key() failed.");
+ goto error;
+ }
+ secret_len = result;
+ if (crypto_expand_key_material_TAP((uint8_t*)secret_tmp, secret_len,
+ (uint8_t*)secret_out, secret_bytes_out)<0)
+ goto error;
+ secret_len = secret_bytes_out;
+
+ goto done;
+ error:
+ result = -1;
+ done:
+ crypto_log_errors(LOG_WARN, "completing DH handshake");
+ if (pubkey_bn)
+ BN_clear_free(pubkey_bn);
+ if (secret_tmp) {
+ memwipe(secret_tmp, 0, secret_tmp_len);
+ tor_free(secret_tmp);
+ }
+ if (result < 0)
+ return result;
+ else
+ return secret_len;
+}
+
+/** Free a DH key exchange object.
+ */
+void
+crypto_dh_free_(crypto_dh_t *dh)
+{
+ if (!dh)
+ return;
+ tor_assert(dh->dh);
+ DH_free(dh->dh);
+ tor_free(dh);
+}
+
+void
+crypto_dh_free_all(void)
+{
+ if (dh_param_p)
+ BN_clear_free(dh_param_p);
+ if (dh_param_p_tls)
+ BN_clear_free(dh_param_p_tls);
+ if (dh_param_g)
+ BN_clear_free(dh_param_g);
+
+ dh_param_p = dh_param_p_tls = dh_param_g = NULL;
+}
diff --git a/src/lib/crypt_ops/crypto_dh.h b/src/lib/crypt_ops/crypto_dh.h
new file mode 100644
index 0000000000..88e8a919a8
--- /dev/null
+++ b/src/lib/crypt_ops/crypto_dh.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-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file crypto_dh.h
+ *
+ * \brief Headers for crypto_dh.c
+ **/
+
+#ifndef TOR_CRYPTO_DH_H
+#define TOR_CRYPTO_DH_H
+
+#include "orconfig.h"
+#include "lib/cc/torint.h"
+#include "lib/defs/dh_sizes.h"
+
+typedef struct crypto_dh_t crypto_dh_t;
+
+/* Key negotiation */
+#define DH_TYPE_CIRCUIT 1
+#define DH_TYPE_REND 2
+#define DH_TYPE_TLS 3
+void crypto_set_tls_dh_prime(void);
+crypto_dh_t *crypto_dh_new(int dh_type);
+crypto_dh_t *crypto_dh_dup(const crypto_dh_t *dh);
+int crypto_dh_get_bytes(crypto_dh_t *dh);
+int crypto_dh_generate_public(crypto_dh_t *dh);
+int crypto_dh_get_public(crypto_dh_t *dh, char *pubkey_out,
+ size_t pubkey_out_len);
+ssize_t crypto_dh_compute_secret(int severity, crypto_dh_t *dh,
+ const char *pubkey, size_t pubkey_len,
+ char *secret_out, size_t secret_out_len);
+void crypto_dh_free_(crypto_dh_t *dh);
+#define crypto_dh_free(dh) FREE_AND_NULL(crypto_dh_t, crypto_dh_free_, (dh))
+
+/* Crypto DH free */
+void crypto_dh_free_all(void);
+
+/* Prototypes for private functions only used by tortls.c, crypto.c, and the
+ * unit tests. */
+struct dh_st;
+struct dh_st *crypto_dh_get_dh_(crypto_dh_t *dh);
+
+#endif /* !defined(TOR_CRYPTO_DH_H) */
diff --git a/src/common/crypto_digest.c b/src/lib/crypt_ops/crypto_digest.c
index 9f9a1a1e2c..949e694053 100644
--- a/src/common/crypto_digest.c
+++ b/src/lib/crypt_ops/crypto_digest.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,14 +10,20 @@
* operations.
**/
-#include "container.h"
-#include "crypto_digest.h"
-#include "crypto_openssl_mgt.h"
-#include "crypto_util.h"
-#include "torlog.h"
+#include "lib/container/smartlist.h"
+#include "lib/crypt_ops/crypto_digest.h"
+#include "lib/crypt_ops/crypto_openssl_mgt.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
#include "keccak-tiny/keccak-tiny.h"
+#include <stdlib.h>
+#include <string.h>
+
+#include "lib/arch/bytes.h"
+
DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/hmac.h>
@@ -580,4 +586,3 @@ crypto_xof_free_(crypto_xof_t *xof)
memwipe(xof, 0, sizeof(crypto_xof_t));
tor_free(xof);
}
-
diff --git a/src/common/crypto_digest.h b/src/lib/crypt_ops/crypto_digest.h
index 3bd74acdfa..15bc5ad5b9 100644
--- a/src/common/crypto_digest.h
+++ b/src/lib/crypt_ops/crypto_digest.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,18 +13,9 @@
#ifndef TOR_CRYPTO_DIGEST_H
#define TOR_CRYPTO_DIGEST_H
-#include <stdio.h>
-
-#include "container.h"
-#include "torint.h"
-
-/** Length of the output of our message digest. */
-#define DIGEST_LEN 20
-/** Length of the output of our second (improved) message digests. (For now
- * this is just sha256, but it could be any other 256-bit digest.) */
-#define DIGEST256_LEN 32
-/** Length of the output of our 64-bit optimized message digests (SHA512). */
-#define DIGEST512_LEN 64
+#include "lib/cc/torint.h"
+#include "lib/defs/digest_sizes.h"
+#include "lib/malloc/util_malloc.h"
/** Length of a sha1 message digest when encoded in base32 with trailing =
* signs removed. */
@@ -78,6 +69,8 @@ typedef struct {
typedef struct crypto_digest_t crypto_digest_t;
typedef struct crypto_xof_t crypto_xof_t;
+struct smartlist_t;
+
/* SHA-1 and other digests */
int crypto_digest(char *digest, const char *m, size_t len);
int crypto_digest256(char *digest, const char *m, size_t len,
@@ -133,4 +126,3 @@ digest_algorithm_t crypto_digest_get_algorithm(crypto_digest_t *digest);
#endif
#endif /* !defined(TOR_CRYPTO_DIGEST_H) */
-
diff --git a/src/common/crypto_ed25519.c b/src/lib/crypt_ops/crypto_ed25519.c
index 9c13e3bdf0..985652ecba 100644
--- a/src/common/crypto_ed25519.c
+++ b/src/lib/crypt_ops/crypto_ed25519.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
+/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -21,19 +21,23 @@
#include <sys/stat.h>
#endif
-#include "crypto_curve25519.h"
-#include "crypto_digest.h"
-#include "crypto_ed25519.h"
-#include "crypto_format.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "torlog.h"
-#include "util.h"
-#include "util_format.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "lib/crypt_ops/crypto_digest.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/encoding/binascii.h"
+#include "lib/string/util_string.h"
#include "ed25519/ref10/ed25519_ref10.h"
#include "ed25519/donna/ed25519_donna_tor.h"
+#include <string.h>
+
static void pick_ed25519_impl(void);
/** An Ed25519 implementation, as a set of function pointers. */
@@ -814,4 +818,3 @@ ed25519_validate_pubkey(const ed25519_public_key_t *pubkey)
return 0;
}
-
diff --git a/src/common/crypto_ed25519.h b/src/lib/crypt_ops/crypto_ed25519.h
index 74269ccffd..5ecd4530d8 100644
--- a/src/common/crypto_ed25519.h
+++ b/src/lib/crypt_ops/crypto_ed25519.h
@@ -1,31 +1,26 @@
-/* Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_CRYPTO_ED25519_H
#define TOR_CRYPTO_ED25519_H
-#include "testsupport.h"
-#include "torint.h"
-#include "crypto_curve25519.h"
-#include "util.h"
-
-#define ED25519_PUBKEY_LEN 32
-#define ED25519_SECKEY_LEN 64
-#define ED25519_SECKEY_SEED_LEN 32
-#define ED25519_SIG_LEN 64
+#include "lib/testsupport/testsupport.h"
+#include "lib/cc/torint.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "lib/defs/x25519_sizes.h"
/** An Ed25519 signature. */
-typedef struct {
+typedef struct ed25519_signature_t {
uint8_t sig[ED25519_SIG_LEN];
} ed25519_signature_t;
/** An Ed25519 public key */
-typedef struct {
+typedef struct ed25519_public_key_t {
uint8_t pubkey[ED25519_PUBKEY_LEN];
} ed25519_public_key_t;
/** An Ed25519 secret key */
-typedef struct {
+typedef struct ed25519_secret_key_t {
/** Note that we store secret keys in an expanded format that doesn't match
* the format from standard ed25519. Ed25519 stores a 32-byte value k and
* expands it into a 64-byte H(k), using the first 32 bytes for a multiplier
@@ -36,7 +31,7 @@ typedef struct {
} ed25519_secret_key_t;
/** An Ed25519 keypair. */
-typedef struct {
+typedef struct ed25519_keypair_t {
ed25519_public_key_t pubkey;
ed25519_secret_key_t seckey;
} ed25519_keypair_t;
@@ -142,4 +137,3 @@ MOCK_DECL(STATIC int, ed25519_impl_spot_check, (void));
#endif
#endif /* !defined(TOR_CRYPTO_ED25519_H) */
-
diff --git a/src/common/crypto_format.c b/src/lib/crypt_ops/crypto_format.c
index 460e85bac1..8c71b265bf 100644
--- a/src/common/crypto_format.c
+++ b/src/lib/crypt_ops/crypto_format.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,15 +14,21 @@
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
-#include "container.h"
-#include "crypto_curve25519.h"
-#include "crypto_digest.h"
-#include "crypto_ed25519.h"
-#include "crypto_format.h"
-#include "crypto_util.h"
-#include "util.h"
-#include "util_format.h"
-#include "torlog.h"
+#include "lib/container/smartlist.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "lib/crypt_ops/crypto_digest.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/string/compat_string.h"
+#include "lib/string/util_string.h"
+#include "lib/string/printf.h"
+#include "lib/encoding/binascii.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/fs/files.h"
+
+#include <string.h>
/** Write the <b>datalen</b> bytes from <b>data</b> to the file named
* <b>fname</b> in the tagged-data format. This format contains a
@@ -296,4 +302,3 @@ digest256_from_base64(char *digest, const char *d64)
else
return -1;
}
-
diff --git a/src/common/crypto_format.h b/src/lib/crypt_ops/crypto_format.h
index bbd85dc720..4a29b07b3b 100644
--- a/src/common/crypto_format.h
+++ b/src/lib/crypt_ops/crypto_format.h
@@ -1,15 +1,18 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_CRYPTO_FORMAT_H
#define TOR_CRYPTO_FORMAT_H
-#include "testsupport.h"
-#include "torint.h"
-#include "crypto_ed25519.h"
+#include "lib/testsupport/testsupport.h"
+#include "lib/cc/torint.h"
+#include "lib/defs/x25519_sizes.h"
+
+struct ed25519_public_key_t;
+struct ed25519_signature_t;
int crypto_write_tagged_contents_to_file(const char *fname,
const char *typestring,
@@ -23,20 +26,16 @@ ssize_t crypto_read_tagged_contents_from_file(const char *fname,
uint8_t *data_out,
ssize_t data_out_len);
-#define ED25519_BASE64_LEN 43
-int ed25519_public_from_base64(ed25519_public_key_t *pkey,
+int ed25519_public_from_base64(struct ed25519_public_key_t *pkey,
const char *input);
int ed25519_public_to_base64(char *output,
- const ed25519_public_key_t *pkey);
-const char *ed25519_fmt(const ed25519_public_key_t *pkey);
-
-/* XXXX move these to crypto_format.h */
-#define ED25519_SIG_BASE64_LEN 86
+ const struct ed25519_public_key_t *pkey);
+const char *ed25519_fmt(const struct ed25519_public_key_t *pkey);
-int ed25519_signature_from_base64(ed25519_signature_t *sig,
+int ed25519_signature_from_base64(struct ed25519_signature_t *sig,
const char *input);
int ed25519_signature_to_base64(char *output,
- const ed25519_signature_t *sig);
+ const struct ed25519_signature_t *sig);
int digest_to_base64(char *d64, const char *digest);
int digest_from_base64(char *digest, const char *d64);
@@ -44,4 +43,3 @@ int digest256_to_base64(char *d64, const char *digest);
int digest256_from_base64(char *digest, const char *d64);
#endif /* !defined(TOR_CRYPTO_FORMAT_H) */
-
diff --git a/src/lib/crypt_ops/crypto_hkdf.c b/src/lib/crypt_ops/crypto_hkdf.c
new file mode 100644
index 0000000000..0200d0fe9c
--- /dev/null
+++ b/src/lib/crypt_ops/crypto_hkdf.c
@@ -0,0 +1,198 @@
+/* Copyright (c) 2001, Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file crypto_hkdf.c
+ * \brief Block of functions related with HKDF utilities and operations.
+ **/
+
+#include "lib/crypt_ops/crypto_hkdf.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/crypt_ops/crypto_digest.h"
+
+#include "lib/crypt_ops/crypto_openssl_mgt.h"
+#include "lib/intmath/cmp.h"
+#include "lib/log/util_bug.h"
+
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0)
+#define HAVE_OPENSSL_HKDF 1
+#include <openssl/kdf.h>
+#endif
+
+#include <string.h>
+
+/** Given <b>key_in_len</b> bytes of negotiated randomness in <b>key_in</b>
+ * ("K"), expand it into <b>key_out_len</b> bytes of negotiated key material in
+ * <b>key_out</b> by taking the first <b>key_out_len</b> bytes of
+ * H(K | [00]) | H(K | [01]) | ....
+ *
+ * This is the key expansion algorithm used in the "TAP" circuit extension
+ * mechanism; it shouldn't be used for new protocols.
+ *
+ * Return 0 on success, -1 on failure.
+ */
+int
+crypto_expand_key_material_TAP(const uint8_t *key_in, size_t key_in_len,
+ uint8_t *key_out, size_t key_out_len)
+{
+ int i, r = -1;
+ uint8_t *cp, *tmp = tor_malloc(key_in_len+1);
+ uint8_t digest[DIGEST_LEN];
+
+ /* If we try to get more than this amount of key data, we'll repeat blocks.*/
+ tor_assert(key_out_len <= DIGEST_LEN*256);
+
+ memcpy(tmp, key_in, key_in_len);
+ for (cp = key_out, i=0; cp < key_out+key_out_len;
+ ++i, cp += DIGEST_LEN) {
+ tmp[key_in_len] = i;
+ if (crypto_digest((char*)digest, (const char *)tmp, key_in_len+1) < 0)
+ goto exit;
+ memcpy(cp, digest, MIN(DIGEST_LEN, key_out_len-(cp-key_out)));
+ }
+
+ r = 0;
+ exit:
+ memwipe(tmp, 0, key_in_len+1);
+ tor_free(tmp);
+ memwipe(digest, 0, sizeof(digest));
+ return r;
+}
+
+#ifdef HAVE_OPENSSL_HKDF
+/**
+ * Perform RFC5869 HKDF computation using OpenSSL (only to be called from
+ * crypto_expand_key_material_rfc5869_sha256_openssl). Note that OpenSSL
+ * requires input key to be nonempty and salt length to be equal or less
+ * than 1024.
+ */
+static int
+crypto_expand_key_material_rfc5869_sha256_openssl(
+ const uint8_t *key_in, size_t key_in_len,
+ const uint8_t *salt_in, size_t salt_in_len,
+ const uint8_t *info_in, size_t info_in_len,
+ uint8_t *key_out, size_t key_out_len)
+{
+ int r;
+ EVP_PKEY_CTX *evp_pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
+ tor_assert(evp_pkey_ctx);
+ tor_assert(key_in_len != 0);
+ tor_assert(salt_in_len <= 1024);
+
+ r = EVP_PKEY_derive_init(evp_pkey_ctx);
+ tor_assert(r == 1);
+
+ r = EVP_PKEY_CTX_set_hkdf_md(evp_pkey_ctx, EVP_sha256());
+ tor_assert(r == 1);
+
+ r = EVP_PKEY_CTX_set1_hkdf_salt(evp_pkey_ctx, salt_in, (int)salt_in_len);
+ tor_assert(r == 1);
+
+ r = EVP_PKEY_CTX_set1_hkdf_key(evp_pkey_ctx, key_in, (int)key_in_len);
+ tor_assert(r == 1);
+
+ r = EVP_PKEY_CTX_add1_hkdf_info(evp_pkey_ctx, info_in, (int)info_in_len);
+ tor_assert(r == 1);
+
+ r = EVP_PKEY_derive(evp_pkey_ctx, key_out, &key_out_len);
+ tor_assert(r == 1);
+
+ EVP_PKEY_CTX_free(evp_pkey_ctx);
+ return 0;
+}
+
+#else
+
+/**
+ * Perform RFC5869 HKDF computation using our own legacy implementation.
+ * Only to be called from crypto_expand_key_material_rfc5869_sha256_openssl.
+ */
+static int
+crypto_expand_key_material_rfc5869_sha256_legacy(
+ const uint8_t *key_in, size_t key_in_len,
+ const uint8_t *salt_in, size_t salt_in_len,
+ const uint8_t *info_in, size_t info_in_len,
+ uint8_t *key_out, size_t key_out_len)
+{
+ uint8_t prk[DIGEST256_LEN];
+ uint8_t tmp[DIGEST256_LEN + 128 + 1];
+ uint8_t mac[DIGEST256_LEN];
+ int i;
+ uint8_t *outp;
+ size_t tmp_len;
+
+ crypto_hmac_sha256((char*)prk,
+ (const char*)salt_in, salt_in_len,
+ (const char*)key_in, key_in_len);
+
+ /* If we try to get more than this amount of key data, we'll repeat blocks.*/
+ tor_assert(key_out_len <= DIGEST256_LEN * 256);
+ tor_assert(info_in_len <= 128);
+ memset(tmp, 0, sizeof(tmp));
+ outp = key_out;
+ i = 1;
+
+ while (key_out_len) {
+ size_t n;
+ if (i > 1) {
+ memcpy(tmp, mac, DIGEST256_LEN);
+ memcpy(tmp+DIGEST256_LEN, info_in, info_in_len);
+ tmp[DIGEST256_LEN+info_in_len] = i;
+ tmp_len = DIGEST256_LEN + info_in_len + 1;
+ } else {
+ memcpy(tmp, info_in, info_in_len);
+ tmp[info_in_len] = i;
+ tmp_len = info_in_len + 1;
+ }
+ crypto_hmac_sha256((char*)mac,
+ (const char*)prk, DIGEST256_LEN,
+ (const char*)tmp, tmp_len);
+ n = key_out_len < DIGEST256_LEN ? key_out_len : DIGEST256_LEN;
+ memcpy(outp, mac, n);
+ key_out_len -= n;
+ outp += n;
+ ++i;
+ }
+
+ memwipe(tmp, 0, sizeof(tmp));
+ memwipe(mac, 0, sizeof(mac));
+ return 0;
+}
+#endif
+
+/** Expand some secret key material according to RFC5869, using SHA256 as the
+ * underlying hash. The <b>key_in_len</b> bytes at <b>key_in</b> are the
+ * secret key material; the <b>salt_in_len</b> bytes at <b>salt_in</b> and the
+ * <b>info_in_len</b> bytes in <b>info_in_len</b> are the algorithm's "salt"
+ * and "info" parameters respectively. On success, write <b>key_out_len</b>
+ * bytes to <b>key_out</b> and return 0. Assert on failure.
+ */
+int
+crypto_expand_key_material_rfc5869_sha256(
+ const uint8_t *key_in, size_t key_in_len,
+ const uint8_t *salt_in, size_t salt_in_len,
+ const uint8_t *info_in, size_t info_in_len,
+ uint8_t *key_out, size_t key_out_len)
+{
+ tor_assert(key_in);
+ tor_assert(key_in_len > 0);
+
+#ifdef HAVE_OPENSSL_HKDF
+ return crypto_expand_key_material_rfc5869_sha256_openssl(key_in,
+ key_in_len, salt_in,
+ salt_in_len, info_in,
+ info_in_len,
+ key_out, key_out_len);
+#else
+ return crypto_expand_key_material_rfc5869_sha256_legacy(key_in,
+ key_in_len, salt_in,
+ salt_in_len, info_in,
+ info_in_len,
+ key_out, key_out_len);
+#endif
+}
diff --git a/src/lib/crypt_ops/crypto_hkdf.h b/src/lib/crypt_ops/crypto_hkdf.h
new file mode 100644
index 0000000000..4c42584277
--- /dev/null
+++ b/src/lib/crypt_ops/crypto_hkdf.h
@@ -0,0 +1,27 @@
+/* Copyright (c) 2001, Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file crypto_hkdf.h
+ *
+ * \brief Headers for crypto_hkdf.h
+ **/
+
+#ifndef TOR_CRYPTO_HKDF_H
+#define TOR_CRYPTO_HKDF_H
+
+#include "lib/cc/torint.h"
+
+int crypto_expand_key_material_TAP(const uint8_t *key_in,
+ size_t key_in_len,
+ uint8_t *key_out, size_t key_out_len);
+int crypto_expand_key_material_rfc5869_sha256(
+ const uint8_t *key_in, size_t key_in_len,
+ const uint8_t *salt_in, size_t salt_in_len,
+ const uint8_t *info_in, size_t info_in_len,
+ uint8_t *key_out, size_t key_out_len);
+
+#endif /* !defined(TOR_CRYPTO_HKDF_H) */
diff --git a/src/common/crypto_openssl_mgt.c b/src/lib/crypt_ops/crypto_openssl_mgt.c
index ea3519efa2..d1affa7258 100644
--- a/src/common/crypto_openssl_mgt.c
+++ b/src/lib/crypt_ops/crypto_openssl_mgt.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,8 +10,12 @@
* \brief Block of functions related to operations from OpenSSL.
**/
-#include "compat_openssl.h"
-#include "crypto_openssl_mgt.h"
+#include "lib/crypt_ops/compat_openssl.h"
+#include "lib/crypt_ops/crypto_openssl_mgt.h"
+#include "lib/string/util_string.h"
+#include "lib/lock/compat_mutex.h"
+#include "lib/testsupport/testsupport.h"
+#include "lib/thread/threads.h"
DISABLE_GCC_WARNING(redundant-decls)
@@ -29,6 +33,8 @@ DISABLE_GCC_WARNING(redundant-decls)
ENABLE_GCC_WARNING(redundant-decls)
+#include <string.h>
+
#ifndef NEW_THREAD_API
/** A number of preallocated mutexes for use by OpenSSL. */
static tor_mutex_t **openssl_mutexes_ = NULL;
@@ -158,4 +164,3 @@ crypto_openssl_free_all(void)
}
#endif /* !defined(NEW_THREAD_API) */
}
-
diff --git a/src/common/crypto_openssl_mgt.h b/src/lib/crypt_ops/crypto_openssl_mgt.h
index 09b6737962..8251f65ecf 100644
--- a/src/common/crypto_openssl_mgt.h
+++ b/src/lib/crypt_ops/crypto_openssl_mgt.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,9 +13,7 @@
#ifndef TOR_CRYPTO_OPENSSL_H
#define TOR_CRYPTO_OPENSSL_H
-#include <stdio.h>
-#include "util.h"
-
+#include "orconfig.h"
#include <openssl/engine.h>
/*
@@ -82,4 +80,3 @@ int setup_openssl_threading(void);
void crypto_openssl_free_all(void);
#endif /* !defined(TOR_CRYPTO_OPENSSL_H) */
-
diff --git a/src/common/crypto_pwbox.c b/src/lib/crypt_ops/crypto_pwbox.c
index c2bd1d26cb..c001e295da 100644
--- a/src/common/crypto_pwbox.c
+++ b/src/lib/crypt_ops/crypto_pwbox.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -8,15 +8,19 @@
* them to disk.
*/
-#include "crypto.h"
-#include "crypto_digest.h"
-#include "crypto_pwbox.h"
-#include "crypto_rand.h"
-#include "crypto_s2k.h"
-#include "crypto_util.h"
-#include "di_ops.h"
-#include "util.h"
-#include "pwbox.h"
+#include <string.h>
+
+#include "lib/arch/bytes.h"
+#include "lib/crypt_ops/crypto.h"
+#include "lib/crypt_ops/crypto_digest.h"
+#include "lib/crypt_ops/crypto_pwbox.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_s2k.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/intmath/muldiv.h"
+#include "trunnel/pwbox.h"
+#include "lib/log/util_bug.h"
/* 8 bytes "TORBOX00"
1 byte: header len (H)
@@ -74,7 +78,7 @@ crypto_pwbox(uint8_t **out, size_t *outlen_out,
pwbox_encoded_setlen_data(enc, encrypted_len);
encrypted_portion = pwbox_encoded_getarray_data(enc);
- set_uint32(encrypted_portion, htonl((uint32_t)input_len));
+ set_uint32(encrypted_portion, tor_htonl((uint32_t)input_len));
memcpy(encrypted_portion+4, input, input_len);
/* Now that all the data is in position, derive some keys, encrypt, and
@@ -189,7 +193,7 @@ crypto_unpwbox(uint8_t **out, size_t *outlen_out,
cipher = crypto_cipher_new_with_iv((char*)keys, (char*)enc->iv);
crypto_cipher_decrypt(cipher, (char*)&result_len, (char*)encrypted, 4);
- result_len = ntohl(result_len);
+ result_len = tor_ntohl(result_len);
if (encrypted_len < result_len + 4)
goto err;
@@ -212,4 +216,3 @@ crypto_unpwbox(uint8_t **out, size_t *outlen_out,
memwipe(keys, 0, sizeof(keys));
return rv;
}
-
diff --git a/src/common/crypto_pwbox.h b/src/lib/crypt_ops/crypto_pwbox.h
index a26b6d2c17..00fabd0913 100644
--- a/src/common/crypto_pwbox.h
+++ b/src/lib/crypt_ops/crypto_pwbox.h
@@ -1,10 +1,16 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file crypto_pwbox.h
+ *
+ * \brief Header for crypto_pwbox.c
+ **/
+
#ifndef CRYPTO_PWBOX_H_INCLUDED_
#define CRYPTO_PWBOX_H_INCLUDED_
-#include "torint.h"
+#include "lib/cc/torint.h"
#define UNPWBOX_OKAY 0
#define UNPWBOX_BAD_SECRET -1
@@ -20,4 +26,3 @@ int crypto_unpwbox(uint8_t **out, size_t *outlen_out,
const char *secret, size_t secret_len);
#endif /* !defined(CRYPTO_PWBOX_H_INCLUDED_) */
-
diff --git a/src/common/crypto_rand.c b/src/lib/crypt_ops/crypto_rand.c
index df2e2f65d3..6f479b013b 100644
--- a/src/common/crypto_rand.c
+++ b/src/lib/crypt_ops/crypto_rand.c
@@ -14,22 +14,26 @@
#ifndef CRYPTO_RAND_PRIVATE
#define CRYPTO_RAND_PRIVATE
-#include "crypto_rand.h"
+#include "lib/crypt_ops/crypto_rand.h"
#ifdef _WIN32
#include <windows.h>
#include <wincrypt.h>
#endif /* defined(_WIN32) */
-#include "container.h"
-#include "compat.h"
-#include "compat_openssl.h"
-#include "crypto_util.h"
-#include "sandbox.h"
-#include "testsupport.h"
-#include "torlog.h"
-#include "util.h"
-#include "util_format.h"
+#include "lib/container/smartlist.h"
+#include "lib/crypt_ops/compat_openssl.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/encoding/binascii.h"
+#include "lib/intmath/weakrng.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/sandbox/sandbox.h"
+#include "lib/string/compat_string.h"
+#include "lib/string/util_string.h"
+#include "lib/testsupport/testsupport.h"
+#include "lib/fs/files.h"
DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/rand.h>
@@ -62,6 +66,8 @@ ENABLE_GCC_WARNING(redundant-decls)
#include <sys/random.h>
#endif
+#include <string.h>
+
/**
* How many bytes of entropy we add at once.
*
@@ -237,7 +243,7 @@ crypto_strongest_rand_fallback(uint8_t *out, size_t out_len)
fd = open(sandbox_intern_string(filenames[i]), O_RDONLY, 0);
if (fd<0) continue;
log_info(LD_CRYPTO, "Reading entropy from \"%s\"", filenames[i]);
- n = read_all(fd, (char*)out, out_len, 0);
+ n = read_all_from_fd(fd, (char*)out, out_len);
close(fd);
if (n != out_len) {
/* LCOV_EXCL_START
@@ -612,4 +618,3 @@ crypto_force_rand_ssleay(void)
}
#endif /* !defined(CRYPTO_RAND_PRIVATE) */
-
diff --git a/src/common/crypto_rand.h b/src/lib/crypt_ops/crypto_rand.h
index bb02e51001..938f11909e 100644
--- a/src/common/crypto_rand.h
+++ b/src/lib/crypt_ops/crypto_rand.h
@@ -13,8 +13,9 @@
#ifndef TOR_CRYPTO_RAND_H
#define TOR_CRYPTO_RAND_H
-#include "torint.h"
-#include "util.h"
+#include "lib/cc/compat_compiler.h"
+#include "lib/cc/torint.h"
+#include "lib/testsupport/testsupport.h"
/* random numbers */
int crypto_seed_rng(void) ATTR_WUR;
@@ -49,4 +50,3 @@ extern int break_strongest_rng_fallback;
#endif /* defined(CRYPTO_RAND_PRIVATE) */
#endif /* !defined(TOR_CRYPTO_RAND_H) */
-
diff --git a/src/common/crypto_rsa.c b/src/lib/crypt_ops/crypto_rsa.c
index f66cdef3c5..9290414de0 100644
--- a/src/common/crypto_rsa.c
+++ b/src/lib/crypt_ops/crypto_rsa.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,14 +9,17 @@
* \brief Block of functions related with RSA utilities and operations.
**/
-#include "crypto.h"
-#include "crypto_curve25519.h"
-#include "crypto_digest.h"
-#include "crypto_format.h"
-#include "compat_openssl.h"
-#include "crypto_rand.h"
-#include "crypto_rsa.h"
-#include "crypto_util.h"
+#include "lib/crypt_ops/crypto.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "lib/crypt_ops/crypto_digest.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/compat_openssl.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_rsa.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/log/util_bug.h"
+#include "lib/fs/files.h"
DISABLE_GCC_WARNING(redundant-decls)
@@ -33,9 +36,10 @@ DISABLE_GCC_WARNING(redundant-decls)
ENABLE_GCC_WARNING(redundant-decls)
-#include "torlog.h"
-#include "util.h"
-#include "util_format.h"
+#include "lib/log/torlog.h"
+#include "lib/encoding/binascii.h"
+
+#include <string.h>
/** Declaration for crypto_pk_t structure. */
struct crypto_pk_t
@@ -44,27 +48,6 @@ struct crypto_pk_t
RSA *key; /**< The key itself */
};
-/** Log all pending crypto errors at level <b>severity</b>. Use
- * <b>doing</b> to describe our current activities.
- */
-static void
-crypto_log_errors(int severity, const char *doing)
-{
- unsigned long err;
- const char *msg, *lib, *func;
- while ((err = ERR_get_error()) != 0) {
- msg = (const char*)ERR_reason_error_string(err);
- lib = (const char*)ERR_lib_error_string(err);
- func = (const char*)ERR_func_error_string(err);
- if (!msg) msg = "(null)";
- if (!lib) lib = "(null)";
- if (!func) func = "(null)";
- if (BUG(!doing)) doing = "(null)";
- tor_log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)",
- doing, msg, lib, func);
- }
-}
-
/** Return the number of bytes added by padding method <b>padding</b>.
*/
int
@@ -1180,4 +1163,3 @@ crypto_pk_base64_decode(const char *str, size_t len)
tor_free(der);
return pk;
}
-
diff --git a/src/common/crypto_rsa.h b/src/lib/crypt_ops/crypto_rsa.h
index e952089318..093f2cec6c 100644
--- a/src/common/crypto_rsa.h
+++ b/src/lib/crypt_ops/crypto_rsa.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,13 +15,10 @@
#include "orconfig.h"
-#include "crypto_digest.h"
-#include <stdio.h>
-#include "torint.h"
-#include "testsupport.h"
-#include "compat.h"
-#include "util.h"
-#include "torlog.h"
+#include "lib/crypt_ops/crypto_digest.h"
+#include "lib/cc/torint.h"
+#include "lib/testsupport/testsupport.h"
+#include "lib/log/torlog.h"
/** Length of our public keys. */
#define PK_BYTES (1024/8)
@@ -116,4 +113,3 @@ void crypto_pk_assign_(crypto_pk_t *dest, const crypto_pk_t *src);
#endif
#endif
-
diff --git a/src/common/crypto_s2k.c b/src/lib/crypt_ops/crypto_s2k.c
index 8543760ec5..ab91d92f0e 100644
--- a/src/common/crypto_s2k.c
+++ b/src/lib/crypt_ops/crypto_s2k.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,13 +12,14 @@
#define CRYPTO_S2K_PRIVATE
-#include "compat.h"
-#include "crypto.h"
-#include "crypto_digest.h"
-#include "crypto_rand.h"
-#include "crypto_s2k.h"
-#include "crypto_util.h"
-#include "util.h"
+#include "lib/crypt_ops/crypto.h"
+#include "lib/crypt_ops/crypto_digest.h"
+#include "lib/crypt_ops/crypto_hkdf.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_s2k.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/log/util_bug.h"
#include <openssl/evp.h>
@@ -27,6 +28,8 @@
#include <libscrypt.h>
#endif
+#include <string.h>
+
/* Encoded secrets take the form:
u8 type;
@@ -472,4 +475,3 @@ secret_to_key_check(const uint8_t *spec_and_key, size_t spec_and_key_len,
memwipe(buf, 0, sizeof(buf));
return rv;
}
-
diff --git a/src/common/crypto_s2k.h b/src/lib/crypt_ops/crypto_s2k.h
index 849ff59ce8..2429185b52 100644
--- a/src/common/crypto_s2k.h
+++ b/src/lib/crypt_ops/crypto_s2k.h
@@ -1,14 +1,20 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file crypto_s2k.h
+ *
+ * \brief Header for crypto_s2k.c
+ **/
+
#ifndef TOR_CRYPTO_S2K_H_INCLUDED
#define TOR_CRYPTO_S2K_H_INCLUDED
#include <stdio.h>
-#include "torint.h"
+#include "lib/cc/torint.h"
/** Length of RFC2440-style S2K specifier: the first 8 bytes are a salt, the
* 9th describes how much iteration to do. */
@@ -70,4 +76,3 @@ STATIC int secret_to_key_compute_key(uint8_t *key_out, size_t key_out_len,
#endif /* defined(CRYPTO_S2K_PRIVATE) */
#endif /* !defined(TOR_CRYPTO_S2K_H_INCLUDED) */
-
diff --git a/src/common/crypto_util.c b/src/lib/crypt_ops/crypto_util.c
index b0d5b6b2f7..19b0885256 100644
--- a/src/common/crypto_util.c
+++ b/src/lib/crypt_ops/crypto_util.c
@@ -13,7 +13,8 @@
#ifndef CRYPTO_UTIL_PRIVATE
#define CRYPTO_UTIL_PRIVATE
-#include "crypto_util.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/cc/compat_compiler.h"
#include <string.h>
@@ -23,14 +24,16 @@
#include <wincrypt.h>
#endif /* defined(_WIN32) */
-#include "util.h"
-
DISABLE_GCC_WARNING(redundant-decls)
+#include <openssl/err.h>
#include <openssl/crypto.h>
ENABLE_GCC_WARNING(redundant-decls)
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+
/**
* Destroy the <b>sz</b> bytes of data stored at <b>mem</b>, setting them to
* the value <b>byte</b>.
@@ -103,5 +106,24 @@ memwipe(void *mem, uint8_t byte, size_t sz)
memset(mem, byte, sz);
}
+/** Log all pending crypto errors at level <b>severity</b>. Use
+ * <b>doing</b> to describe our current activities.
+ */
+void
+crypto_log_errors(int severity, const char *doing)
+{
+ unsigned long err;
+ const char *msg, *lib, *func;
+ while ((err = ERR_get_error()) != 0) {
+ msg = (const char*)ERR_reason_error_string(err);
+ lib = (const char*)ERR_lib_error_string(err);
+ func = (const char*)ERR_func_error_string(err);
+ if (!msg) msg = "(null)";
+ if (!lib) lib = "(null)";
+ if (!func) func = "(null)";
+ if (BUG(!doing)) doing = "(null)";
+ tor_log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)",
+ doing, msg, lib, func);
+ }
+}
#endif /* !defined(CRYPTO_UTIL_PRIVATE) */
-
diff --git a/src/common/crypto_util.h b/src/lib/crypt_ops/crypto_util.h
index 922942b371..3ce34e6f23 100644
--- a/src/common/crypto_util.h
+++ b/src/lib/crypt_ops/crypto_util.h
@@ -13,11 +13,14 @@
#ifndef TOR_CRYPTO_UTIL_H
#define TOR_CRYPTO_UTIL_H
-#include "torint.h"
+#include "lib/cc/torint.h"
/** OpenSSL-based utility functions. */
void memwipe(void *mem, uint8_t byte, size_t sz);
+/** Log utility function */
+void crypto_log_errors(int severity, const char *doing);
+
#ifdef CRYPTO_UTIL_PRIVATE
#ifdef TOR_UNIT_TESTS
#endif /* defined(TOR_UNIT_TESTS) */
diff --git a/src/lib/crypt_ops/digestset.c b/src/lib/crypt_ops/digestset.c
new file mode 100644
index 0000000000..89dd377a9c
--- /dev/null
+++ b/src/lib/crypt_ops/digestset.c
@@ -0,0 +1,58 @@
+/* Copyright (c) 2018-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file digestset.c
+ * \brief Implementation for a set of digests
+ **/
+
+#include "orconfig.h"
+#include "lib/container/bloomfilt.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/defs/digest_sizes.h"
+#include "lib/crypt_ops/digestset.h"
+#include "siphash.h"
+
+/* Wrap our hash function to have the signature that the bloom filter
+ * needs. */
+static uint64_t
+bloomfilt_digest_hash(const struct sipkey *key,
+ const void *item)
+{
+ return siphash24(item, DIGEST_LEN, key);
+}
+
+/**
+ * Allocate and return an digestset, suitable for holding up to
+ * <b>max_guess</b> distinct values.
+ */
+digestset_t *
+digestset_new(int max_guess)
+{
+ uint8_t k[BLOOMFILT_KEY_LEN];
+ crypto_rand((void*)k, sizeof(k));
+ return bloomfilt_new(max_guess, bloomfilt_digest_hash, k);
+}
+
+/**
+ * Add <b>digest</b> to <b>set</b>.
+ *
+ * All future queries for <b>digest</b> in set will return true. Removing
+ * items is not possible.
+ */
+void
+digestset_add(digestset_t *set, const char *digest)
+{
+ bloomfilt_add(set, digest);
+}
+
+/**
+ * Return true if <b>digest</b> is a member of <b>set</b>. (And probably,
+ * return false if <b>digest</b> is not a member of set.)
+ */
+int
+digestset_probably_contains(const digestset_t *set,
+ const char *digest)
+{
+ return bloomfilt_probably_contains(set, digest);
+}
diff --git a/src/lib/crypt_ops/digestset.h b/src/lib/crypt_ops/digestset.h
new file mode 100644
index 0000000000..328979ae0d
--- /dev/null
+++ b/src/lib/crypt_ops/digestset.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file digestset.h
+ * \brief Types to handle sets of digests, based on bloom filters.
+ **/
+
+#ifndef TOR_DIGESTSET_H
+#define TOR_DIGESTSET_H
+
+#include "orconfig.h"
+#include "lib/cc/torint.h"
+#include "lib/container/bloomfilt.h"
+
+/**
+ * An digestset_t represents a set of 20-byte digest values. The
+ * implementation is probabilistic: false negatives cannot occur but false
+ * positives are possible.
+ */
+typedef struct bloomfilt_t digestset_t;
+
+digestset_t *digestset_new(int max_addresses_guess);
+#define digestset_free(set) bloomfilt_free(set)
+void digestset_add(digestset_t *set, const char *addr);
+int digestset_probably_contains(const digestset_t *set,
+ const char *addr);
+
+#endif
diff --git a/src/lib/crypt_ops/include.am b/src/lib/crypt_ops/include.am
new file mode 100644
index 0000000000..1b88b880d0
--- /dev/null
+++ b/src/lib/crypt_ops/include.am
@@ -0,0 +1,46 @@
+
+noinst_LIBRARIES += src/lib/libtor-crypt-ops.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-crypt-ops-testing.a
+endif
+
+src_lib_libtor_crypt_ops_a_SOURCES = \
+ src/lib/crypt_ops/aes.c \
+ src/lib/crypt_ops/crypto.c \
+ src/lib/crypt_ops/crypto_curve25519.c \
+ src/lib/crypt_ops/crypto_dh.c \
+ src/lib/crypt_ops/crypto_digest.c \
+ src/lib/crypt_ops/crypto_ed25519.c \
+ src/lib/crypt_ops/crypto_format.c \
+ src/lib/crypt_ops/crypto_hkdf.c \
+ src/lib/crypt_ops/crypto_openssl_mgt.c \
+ src/lib/crypt_ops/crypto_pwbox.c \
+ src/lib/crypt_ops/crypto_rand.c \
+ src/lib/crypt_ops/crypto_rsa.c \
+ src/lib/crypt_ops/crypto_s2k.c \
+ src/lib/crypt_ops/crypto_util.c \
+ src/lib/crypt_ops/digestset.c
+
+src_lib_libtor_crypt_ops_testing_a_SOURCES = \
+ $(src_lib_libtor_crypt_ops_a_SOURCES)
+src_lib_libtor_crypt_ops_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_crypt_ops_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/crypt_ops/aes.h \
+ src/lib/crypt_ops/compat_openssl.h \
+ src/lib/crypt_ops/crypto_curve25519.h \
+ src/lib/crypt_ops/crypto_dh.h \
+ src/lib/crypt_ops/crypto_digest.h \
+ src/lib/crypt_ops/crypto_ed25519.h \
+ src/lib/crypt_ops/crypto_format.h \
+ src/lib/crypt_ops/crypto.h \
+ src/lib/crypt_ops/crypto_hkdf.h \
+ src/lib/crypt_ops/crypto_openssl_mgt.h \
+ src/lib/crypt_ops/crypto_pwbox.h \
+ src/lib/crypt_ops/crypto_rand.h \
+ src/lib/crypt_ops/crypto_rsa.h \
+ src/lib/crypt_ops/crypto_s2k.h \
+ src/lib/crypt_ops/crypto_util.h \
+ src/lib/crypt_ops/digestset.h
diff --git a/src/lib/ctime/.may_include b/src/lib/ctime/.may_include
new file mode 100644
index 0000000000..e74669bce1
--- /dev/null
+++ b/src/lib/ctime/.may_include
@@ -0,0 +1,5 @@
+orconfig.h
+lib/cc/*.h
+lib/ctime/*.h
+lib/err/*.h
+lib/malloc/*.h
diff --git a/src/common/di_ops.c b/src/lib/ctime/di_ops.c
index 90e9357c8e..287ff6080a 100644
--- a/src/common/di_ops.c
+++ b/src/lib/ctime/di_ops.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Tor Project, Inc. */
+/* Copyright (c) 2011-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -7,9 +7,11 @@
**/
#include "orconfig.h"
-#include "di_ops.h"
-#include "torlog.h"
-#include "util.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/err/torerr.h"
+#include "lib/malloc/util_malloc.h"
+
+#include <string.h>
/**
* Timing-safe version of memcmp. As memcmp, compare the <b>sz</b> bytes at
@@ -171,8 +173,8 @@ dimap_add_entry(di_digest256_map_t **map,
di_digest256_map_t *new_ent;
{
void *old_val = dimap_search(*map, key, NULL);
- tor_assert(! old_val);
- tor_assert(val);
+ raw_assert(! old_val);
+ raw_assert(val);
}
new_ent = tor_malloc_zero(sizeof(di_digest256_map_t));
new_ent->next = *map;
@@ -264,11 +266,10 @@ select_array_member_cumulative_timei(const uint64_t *entries, int n_entries,
rand_val = INT64_MAX;
}
}
- tor_assert(total_so_far == total);
- tor_assert(n_chosen == 1);
- tor_assert(i_chosen >= 0);
- tor_assert(i_chosen < n_entries);
+ raw_assert(total_so_far == total);
+ raw_assert(n_chosen == 1);
+ raw_assert(i_chosen >= 0);
+ raw_assert(i_chosen < n_entries);
return i_chosen;
}
-
diff --git a/src/common/di_ops.h b/src/lib/ctime/di_ops.h
index 67d9c9f0df..92af7ae278 100644
--- a/src/common/di_ops.h
+++ b/src/lib/ctime/di_ops.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,7 @@
#define TOR_DI_OPS_H
#include "orconfig.h"
-#include "torint.h"
+#include "lib/cc/torint.h"
int tor_memcmp(const void *a, const void *b, size_t sz);
int tor_memeq(const void *a, const void *b, size_t sz);
diff --git a/src/lib/ctime/include.am b/src/lib/ctime/include.am
new file mode 100644
index 0000000000..b46c43ba0c
--- /dev/null
+++ b/src/lib/ctime/include.am
@@ -0,0 +1,25 @@
+
+noinst_LIBRARIES += src/lib/libtor-ctime.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-ctime-testing.a
+endif
+
+if ADD_MULODI4
+mulodi4_source=src/ext/mulodi/mulodi4.c
+else
+mulodi4_source=
+endif
+
+src_lib_libtor_ctime_a_SOURCES = \
+ $(mulodi4_source) \
+ src/ext/csiphash.c \
+ src/lib/ctime/di_ops.c
+
+src_lib_libtor_ctime_testing_a_SOURCES = \
+ $(src_lib_libtor_ctime_a_SOURCES)
+src_lib_libtor_ctime_a_CFLAGS = @CFLAGS_CONSTTIME@
+src_lib_libtor_ctime_testing_a_CFLAGS = @CFLAGS_CONSTTIME@ $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/ctime/di_ops.h
diff --git a/src/lib/defs/.may_include b/src/lib/defs/.may_include
new file mode 100644
index 0000000000..2b06e8519c
--- /dev/null
+++ b/src/lib/defs/.may_include
@@ -0,0 +1 @@
+orconfig.h
diff --git a/src/lib/defs/dh_sizes.h b/src/lib/defs/dh_sizes.h
new file mode 100644
index 0000000000..b60957281c
--- /dev/null
+++ b/src/lib/defs/dh_sizes.h
@@ -0,0 +1,13 @@
+/* Copyright (c) 2001, Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_DH_SIZES_H
+#define TOR_DH_SIZES_H
+
+/** Length of our legacy DH keys. */
+#define DH1024_KEY_LEN (1024/8)
+
+#endif
diff --git a/src/lib/defs/digest_sizes.h b/src/lib/defs/digest_sizes.h
new file mode 100644
index 0000000000..dd772cae07
--- /dev/null
+++ b/src/lib/defs/digest_sizes.h
@@ -0,0 +1,27 @@
+/* Copyright (c) 2001, Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_DIGEST_SIZES_H
+#define TOR_DIGEST_SIZES_H
+
+/**
+ * \file digest_sizes.h
+ *
+ * \brief Definitions for common sizes of cryptographic digests.
+ *
+ * Tor uses digests throughout its codebase, even in parts that don't actually
+ * calculate the digests.
+ **/
+
+/** Length of the output of our message digest. */
+#define DIGEST_LEN 20
+/** Length of the output of our second (improved) message digests. (For now
+ * this is just sha256, but it could be any other 256-bit digest.) */
+#define DIGEST256_LEN 32
+/** Length of the output of our 64-bit optimized message digests (SHA512). */
+#define DIGEST512_LEN 64
+
+#endif
diff --git a/src/lib/defs/include.am b/src/lib/defs/include.am
new file mode 100644
index 0000000000..48ee7f29fc
--- /dev/null
+++ b/src/lib/defs/include.am
@@ -0,0 +1,5 @@
+
+noinst_HEADERS += \
+ src/lib/defs/dh_sizes.h \
+ src/lib/defs/digest_sizes.h \
+ src/lib/defs/x25519_sizes.h
diff --git a/src/lib/defs/x25519_sizes.h b/src/lib/defs/x25519_sizes.h
new file mode 100644
index 0000000000..adaaab8c4d
--- /dev/null
+++ b/src/lib/defs/x25519_sizes.h
@@ -0,0 +1,27 @@
+/* Copyright (c) 2001, Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_X25519_SIZES_H
+#define TOR_X25519_SIZES_H
+
+/** Length of a curve25519 public key when encoded. */
+#define CURVE25519_PUBKEY_LEN 32
+/** Length of a curve25519 secret key when encoded. */
+#define CURVE25519_SECKEY_LEN 32
+/** Length of the result of a curve25519 handshake. */
+#define CURVE25519_OUTPUT_LEN 32
+
+#define ED25519_PUBKEY_LEN 32
+#define ED25519_SECKEY_LEN 64
+#define ED25519_SECKEY_SEED_LEN 32
+#define ED25519_SIG_LEN 64
+
+#define CURVE25519_BASE64_PADDED_LEN 44
+
+#define ED25519_BASE64_LEN 43
+#define ED25519_SIG_BASE64_LEN 86
+
+#endif
diff --git a/src/lib/encoding/.may_include b/src/lib/encoding/.may_include
new file mode 100644
index 0000000000..92231b5133
--- /dev/null
+++ b/src/lib/encoding/.may_include
@@ -0,0 +1,9 @@
+orconfig.h
+lib/cc/*.h
+lib/encoding/*.h
+lib/intmath/*.h
+lib/log/*.h
+lib/malloc/*.h
+lib/string/*.h
+lib/testsupport/*.h
+lib/wallclock/*.h
diff --git a/src/common/util_format.c b/src/lib/encoding/binascii.c
index e51757a4e8..df9bb4a813 100644
--- a/src/common/util_format.c
+++ b/src/lib/encoding/binascii.c
@@ -1,26 +1,45 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file util_format.c
+ * \file binascii.c
*
* \brief Miscellaneous functions for encoding and decoding various things
* in base{16,32,64}.
*/
#include "orconfig.h"
-#include "torlog.h"
-#include "util.h"
-#include "util_format.h"
-#include "torint.h"
+
+#include "lib/encoding/binascii.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/cc/torint.h"
+#include "lib/string/compat_ctype.h"
+#include "lib/intmath/muldiv.h"
+#include "lib/malloc/util_malloc.h"
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
+/** Return a pointer to a NUL-terminated hexadecimal string encoding
+ * the first <b>fromlen</b> bytes of <b>from</b>. (fromlen must be \<= 32.) The
+ * result does not need to be deallocated, but repeated calls to
+ * hex_str will trash old results.
+ */
+const char *
+hex_str(const char *from, size_t fromlen)
+{
+ static char buf[65];
+ if (fromlen>(sizeof(buf)-1)/2)
+ fromlen = (sizeof(buf)-1)/2;
+ base16_encode(buf,sizeof(buf),from,fromlen);
+ return buf;
+}
+
/* Return the base32 encoded size in bytes using the source length srclen.
*
* (WATCH OUT: This API counts the terminating NUL byte, but
@@ -464,39 +483,6 @@ base16_encode(char *dest, size_t destlen, const char *src, size_t srclen)
*cp = '\0';
}
-/** Helper: given a hex digit, return its value, or -1 if it isn't hex. */
-static inline int
-hex_decode_digit_(char c)
-{
- switch (c) {
- case '0': return 0;
- case '1': return 1;
- case '2': return 2;
- case '3': return 3;
- case '4': return 4;
- case '5': return 5;
- case '6': return 6;
- case '7': return 7;
- case '8': return 8;
- case '9': return 9;
- case 'A': case 'a': return 10;
- case 'B': case 'b': return 11;
- case 'C': case 'c': return 12;
- case 'D': case 'd': return 13;
- case 'E': case 'e': return 14;
- case 'F': case 'f': return 15;
- default:
- return -1;
- }
-}
-
-/** Helper: given a hex digit, return its value, or -1 if it isn't hex. */
-int
-hex_decode_digit(char c)
-{
- return hex_decode_digit_(c);
-}
-
/** Given a hexadecimal string of <b>srclen</b> bytes in <b>src</b>, decode
* it and store the result in the <b>destlen</b>-byte buffer at <b>dest</b>.
* Return the number of bytes decoded on success, -1 on failure. If
@@ -519,8 +505,8 @@ base16_decode(char *dest, size_t destlen, const char *src, size_t srclen)
end = src+srclen;
while (src<end) {
- v1 = hex_decode_digit_(*src);
- v2 = hex_decode_digit_(*(src+1));
+ v1 = hex_decode_digit(*src);
+ v2 = hex_decode_digit(*(src+1));
if (v1<0||v2<0)
return -1;
*(uint8_t*)dest = (v1<<4)|v2;
@@ -532,4 +518,3 @@ base16_decode(char *dest, size_t destlen, const char *src, size_t srclen)
return (int) (dest-dest_orig);
}
-
diff --git a/src/common/util_format.h b/src/lib/encoding/binascii.h
index 0aefe3a44e..23cbaa7070 100644
--- a/src/common/util_format.h
+++ b/src/lib/encoding/binascii.h
@@ -1,14 +1,24 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#ifndef TOR_UTIL_FORMAT_H
-#define TOR_UTIL_FORMAT_H
+/**
+ * \file binascii.h
+ *
+ * \brief Header for binascii.c
+ **/
-#include "testsupport.h"
-#include "torint.h"
+#ifndef TOR_BINASCII_H
+#define TOR_BINASCII_H
+
+#include "orconfig.h"
+#include <stddef.h>
+#include "lib/testsupport/testsupport.h"
+#include "lib/cc/torint.h"
+
+const char *hex_str(const char *from, size_t fromlen);
/** @{ */
/** These macros don't check for overflow. Use them only for constant inputs
@@ -44,9 +54,7 @@ void base32_encode(char *dest, size_t destlen, const char *src, size_t srclen);
int base32_decode(char *dest, size_t destlen, const char *src, size_t srclen);
size_t base32_encoded_size(size_t srclen);
-int hex_decode_digit(char c);
void base16_encode(char *dest, size_t destlen, const char *src, size_t srclen);
int base16_decode(char *dest, size_t destlen, const char *src, size_t srclen);
#endif /* !defined(TOR_UTIL_FORMAT_H) */
-
diff --git a/src/common/confline.c b/src/lib/encoding/confline.c
index bf613ab742..3486b6a82b 100644
--- a/src/common/confline.c
+++ b/src/lib/encoding/confline.c
@@ -1,29 +1,30 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "compat.h"
-#include "confline.h"
-#include "torlog.h"
-#include "util.h"
-#include "container.h"
-
-static int config_get_lines_aux(const char *string, config_line_t **result,
- int extended, int allow_include,
- int *has_include, smartlist_t *opened_lst,
- int recursion_level, config_line_t **last);
-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,
- int extended, config_line_t **config,
- config_line_t **config_last,
- smartlist_t *opened_lst);
-static int config_process_include(const char *path, int recursion_level,
- int extended, config_line_t **list,
- config_line_t **list_last,
- smartlist_t *opened_lst);
+/**
+ * \file confline.c
+ *
+ * \brief Functions to manipulate a linked list of key-value pairs, of the
+ * type used in Tor's configuration files.
+ *
+ * Tor uses the config_line_t type and its associated serialized format for
+ * human-readable key-value pairs in many places, including its configuration,
+ * its state files, its consensus cache, and so on.
+ **/
+
+#include "lib/encoding/confline.h"
+#include "lib/encoding/cstring.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/string/compat_ctype.h"
+#include "lib/string/compat_string.h"
+#include "lib/string/util_string.h"
+
+#include <string.h>
/** Helper: allocate a new configuration option mapping 'key' to 'val',
* append it to *<b>lst</b>. */
@@ -86,11 +87,12 @@ config_line_find(const config_line_t *lines,
* <b>opened_lst</b> will have a list of opened files if provided.
* Returns the a pointer to the last element of the <b>result</b> in
* <b>last</b>. */
-static int
+int
config_get_lines_aux(const char *string, config_line_t **result, int extended,
int allow_include, int *has_include,
- smartlist_t *opened_lst, int recursion_level,
- config_line_t **last)
+ struct smartlist_t *opened_lst, int recursion_level,
+ config_line_t **last,
+ include_handler_fn handle_include)
{
config_line_t *list = NULL, **next, *list_last = NULL;
char *k, *v;
@@ -133,13 +135,13 @@ config_get_lines_aux(const char *string, config_line_t **result, int extended,
}
}
- if (allow_include && !strcmp(k, "%include")) {
+ if (allow_include && !strcmp(k, "%include") && handle_include) {
tor_free(k);
include_used = 1;
config_line_t *include_list;
- if (config_process_include(v, recursion_level, extended, &include_list,
- &list_last, opened_lst) < 0) {
+ if (handle_include(v, recursion_level, extended, &include_list,
+ &list_last, opened_lst) < 0) {
log_warn(LD_CONFIG, "Error reading included configuration "
"file or directory: \"%s\".", v);
config_free_lines(list);
@@ -178,152 +180,12 @@ config_get_lines_aux(const char *string, config_line_t **result, int extended,
return 0;
}
-/** Helper: parse the config string and strdup into key/value
- * strings. Set *result to the list, or NULL if parsing the string
- * failed. Set *has_include to 1 if <b>result</b> has values from
- * %included files. <b>opened_lst</b> will have a list of opened files if
- * provided. Return 0 on success, -1 on failure. Warn and ignore any
- * misformatted lines.
- *
- * If <b>extended</b> is set, then treat keys beginning with / and with + as
- * indicating "clear" and "append" respectively. */
-int
-config_get_lines_include(const char *string, config_line_t **result,
- int extended, int *has_include,
- smartlist_t *opened_lst)
-{
- return config_get_lines_aux(string, result, extended, 1, has_include,
- opened_lst, 1, NULL);
-}
-
/** Same as config_get_lines_include but does not allow %include */
int
config_get_lines(const char *string, config_line_t **result, int extended)
{
return config_get_lines_aux(string, result, extended, 0, NULL, NULL, 1,
- NULL);
-}
-
-/** 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.
- */
-static smartlist_t *
-config_get_file_list(const char *path, smartlist_t *opened_files)
-{
- smartlist_t *file_list = smartlist_new();
-
- if (opened_files) {
- smartlist_add_strdup(opened_files, path);
- }
-
- 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);
- return NULL;
- }
- smartlist_sort_strings(all_files);
- SMARTLIST_FOREACH_BEGIN(all_files, char *, f) {
- if (f[0] == '.') {
- tor_free(f);
- continue;
- }
-
- char *fullname;
- tor_asprintf(&fullname, "%s"PATH_SEPARATOR"%s", path, f);
- tor_free(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_free(all_files);
- return file_list;
- } else if (file_type == FN_EMPTY) {
- return file_list;
- } else {
- smartlist_free(file_list);
- return NULL;
- }
-}
-
-/** Creates a list of config lines present on included <b>path</b>.
- * Set <b>config</b> to the list and <b>config_last</b> to the last element of
- * <b>config</b>. <b>opened_lst</b> will have a list of opened files if
- * provided. Return 0 on success, -1 on failure. */
-static int
-config_get_included_config(const char *path, int recursion_level, int extended,
- config_line_t **config, config_line_t **config_last,
- smartlist_t *opened_lst)
-{
- char *included_conf = read_file_to_str(path, 0, NULL);
- if (!included_conf) {
- return -1;
- }
-
- if (config_get_lines_aux(included_conf, config, extended, 1, NULL,
- opened_lst, recursion_level+1, config_last) < 0) {
- tor_free(included_conf);
- return -1;
- }
-
- tor_free(included_conf);
- return 0;
-}
-
-/** Process an %include <b>path</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_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);
- if (!config_files) {
- return -1;
- }
-
- int rv = -1;
- SMARTLIST_FOREACH_BEGIN(config_files, const char *, config_file) {
- config_line_t *included_config = NULL;
- if (config_get_included_config(config_file, recursion_level, extended,
- &included_config, list_last,
- opened_lst) < 0) {
- goto done;
- }
-
- *next = included_config;
- if (*list_last)
- next = &(*list_last)->next;
-
- } SMARTLIST_FOREACH_END(config_file);
- *list = ret_list;
- rv = 0;
-
- done:
- SMARTLIST_FOREACH(config_files, char *, f, tor_free(f));
- smartlist_free(config_files);
- return rv;
+ NULL, NULL);
}
/**
@@ -535,4 +397,3 @@ parse_config_line_from_str_verbose(const char *line, char **key_out,
return line;
}
-
diff --git a/src/common/confline.h b/src/lib/encoding/confline.h
index 772a9bbbdc..41f1200947 100644
--- a/src/common/confline.h
+++ b/src/lib/encoding/confline.h
@@ -1,13 +1,19 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file confline.h
+ *
+ * \brief Header for confline.c
+ **/
+
#ifndef TOR_CONFLINE_H
#define TOR_CONFLINE_H
-#include "container.h"
+struct smartlist_t;
/** Ordinary configuration line. */
#define CONFIG_LINE_NORMAL 0
@@ -44,10 +50,6 @@ const config_line_t *config_line_find(const config_line_t *lines,
const char *key);
int config_lines_eq(config_line_t *a, config_line_t *b);
int config_count_key(const config_line_t *a, const char *key);
-int config_get_lines(const char *string, config_line_t **result, int extended);
-int config_get_lines_include(const char *string, config_line_t **result,
- int extended, int *has_include,
- smartlist_t *opened_lst);
void config_free_lines_(config_line_t *front);
#define config_free_lines(front) \
do { \
@@ -57,5 +59,20 @@ void config_free_lines_(config_line_t *front);
const char *parse_config_line_from_str_verbose(const char *line,
char **key_out, char **value_out,
const char **err_out);
-#endif /* !defined(TOR_CONFLINE_H) */
+int config_get_lines(const char *string, struct config_line_t **result,
+ int extended);
+
+typedef int (*include_handler_fn)(const char *, int, int,
+ struct config_line_t **,
+ struct config_line_t **,
+ struct smartlist_t *);
+
+int config_get_lines_aux(const char *string, struct config_line_t **result,
+ int extended,
+ int allow_include, int *has_include,
+ struct smartlist_t *opened_lst, int recursion_level,
+ config_line_t **last,
+ include_handler_fn handle_include);
+
+#endif /* !defined(TOR_CONFLINE_H) */
diff --git a/src/lib/encoding/cstring.c b/src/lib/encoding/cstring.c
new file mode 100644
index 0000000000..994a52e70c
--- /dev/null
+++ b/src/lib/encoding/cstring.c
@@ -0,0 +1,138 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file cstring.c
+ *
+ * \brief Decode data that has been written as a C literal.
+ **/
+
+#include "lib/encoding/cstring.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/string/compat_ctype.h"
+
+#include <string.h>
+
+#define TOR_ISODIGIT(c) ('0' <= (c) && (c) <= '7')
+
+/** Given a c-style double-quoted escaped string in <b>s</b>, extract and
+ * decode its contents into a newly allocated string. On success, assign this
+ * string to *<b>result</b>, assign its length to <b>size_out</b> (if
+ * provided), and return a pointer to the position in <b>s</b> immediately
+ * after the string. On failure, return NULL.
+ */
+const char *
+unescape_string(const char *s, char **result, size_t *size_out)
+{
+ const char *cp;
+ char *out;
+ if (s[0] != '\"')
+ return NULL;
+ cp = s+1;
+ while (1) {
+ switch (*cp) {
+ case '\0':
+ case '\n':
+ return NULL;
+ case '\"':
+ goto end_of_loop;
+ case '\\':
+ if (cp[1] == 'x' || cp[1] == 'X') {
+ if (!(TOR_ISXDIGIT(cp[2]) && TOR_ISXDIGIT(cp[3])))
+ return NULL;
+ cp += 4;
+ } else if (TOR_ISODIGIT(cp[1])) {
+ cp += 2;
+ if (TOR_ISODIGIT(*cp)) ++cp;
+ if (TOR_ISODIGIT(*cp)) ++cp;
+ } else if (cp[1] == 'n' || cp[1] == 'r' || cp[1] == 't' || cp[1] == '"'
+ || cp[1] == '\\' || cp[1] == '\'') {
+ cp += 2;
+ } else {
+ return NULL;
+ }
+ break;
+ default:
+ ++cp;
+ break;
+ }
+ }
+ end_of_loop:
+ out = *result = tor_malloc(cp-s + 1);
+ cp = s+1;
+ while (1) {
+ switch (*cp)
+ {
+ case '\"':
+ *out = '\0';
+ if (size_out) *size_out = out - *result;
+ return cp+1;
+
+ /* LCOV_EXCL_START -- we caught this in parse_config_from_line. */
+ case '\0':
+ tor_fragile_assert();
+ tor_free(*result);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ case '\\':
+ switch (cp[1])
+ {
+ case 'n': *out++ = '\n'; cp += 2; break;
+ case 'r': *out++ = '\r'; cp += 2; break;
+ case 't': *out++ = '\t'; cp += 2; break;
+ case 'x': case 'X':
+ {
+ int x1, x2;
+
+ x1 = hex_decode_digit(cp[2]);
+ x2 = hex_decode_digit(cp[3]);
+ if (x1 == -1 || x2 == -1) {
+ /* LCOV_EXCL_START */
+ /* we caught this above in the initial loop. */
+ tor_assert_nonfatal_unreached();
+ tor_free(*result);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ *out++ = ((x1<<4) + x2);
+ cp += 4;
+ }
+ break;
+ case '0': case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7':
+ {
+ int n = cp[1]-'0';
+ cp += 2;
+ if (TOR_ISODIGIT(*cp)) { n = n*8 + *cp-'0'; cp++; }
+ if (TOR_ISODIGIT(*cp)) { n = n*8 + *cp-'0'; cp++; }
+ if (n > 255) { tor_free(*result); return NULL; }
+ *out++ = (char)n;
+ }
+ break;
+ case '\'':
+ case '\"':
+ case '\\':
+ case '\?':
+ *out++ = cp[1];
+ cp += 2;
+ break;
+
+ /* LCOV_EXCL_START */
+ default:
+ /* we caught this above in the initial loop. */
+ tor_assert_nonfatal_unreached();
+ tor_free(*result); return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+ break;
+ default:
+ *out++ = *cp++;
+ }
+ }
+}
diff --git a/src/lib/encoding/cstring.h b/src/lib/encoding/cstring.h
new file mode 100644
index 0000000000..2da109d958
--- /dev/null
+++ b/src/lib/encoding/cstring.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-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file cstring.h
+ *
+ * \brief Header for cstring.c
+ **/
+
+#ifndef TOR_CSTRING_H
+#define TOR_CSTRING_H
+
+#include <stddef.h>
+const char *unescape_string(const char *s, char **result, size_t *size_out);
+
+#endif /* !defined(TOR_CSTRING_H) */
diff --git a/src/lib/encoding/include.am b/src/lib/encoding/include.am
new file mode 100644
index 0000000000..868e531b6b
--- /dev/null
+++ b/src/lib/encoding/include.am
@@ -0,0 +1,24 @@
+noinst_LIBRARIES += src/lib/libtor-encoding.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-encoding-testing.a
+endif
+
+src_lib_libtor_encoding_a_SOURCES = \
+ src/lib/encoding/binascii.c \
+ src/lib/encoding/confline.c \
+ src/lib/encoding/cstring.c \
+ src/lib/encoding/keyval.c \
+ src/lib/encoding/time_fmt.c
+
+src_lib_libtor_encoding_testing_a_SOURCES = \
+ $(src_lib_libtor_encoding_a_SOURCES)
+src_lib_libtor_encoding_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_encoding_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/encoding/binascii.h \
+ src/lib/encoding/confline.h \
+ src/lib/encoding/cstring.h \
+ src/lib/encoding/keyval.h \
+ src/lib/encoding/time_fmt.h
diff --git a/src/lib/encoding/keyval.c b/src/lib/encoding/keyval.c
new file mode 100644
index 0000000000..53ee776fe7
--- /dev/null
+++ b/src/lib/encoding/keyval.c
@@ -0,0 +1,52 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file keyval.c
+ *
+ * \brief Handle data encoded as a key=value pair.
+ **/
+
+#include "orconfig.h"
+#include "lib/encoding/keyval.h"
+#include "lib/log/escape.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/** Return true if <b>string</b> is a valid 'key=[value]' string.
+ * "value" is optional, to indicate the empty string. Log at logging
+ * <b>severity</b> if something ugly happens. */
+int
+string_is_key_value(int severity, const char *string)
+{
+ /* position of equal sign in string */
+ const char *equal_sign_pos = NULL;
+
+ tor_assert(string);
+
+ if (strlen(string) < 2) { /* "x=" is shortest args string */
+ tor_log(severity, LD_GENERAL, "'%s' is too short to be a k=v value.",
+ escaped(string));
+ return 0;
+ }
+
+ equal_sign_pos = strchr(string, '=');
+ if (!equal_sign_pos) {
+ tor_log(severity, LD_GENERAL, "'%s' is not a k=v value.", escaped(string));
+ return 0;
+ }
+
+ /* validate that the '=' is not in the beginning of the string. */
+ if (equal_sign_pos == string) {
+ tor_log(severity, LD_GENERAL, "'%s' is not a valid k=v value.",
+ escaped(string));
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/src/lib/encoding/keyval.h b/src/lib/encoding/keyval.h
new file mode 100644
index 0000000000..8bf0797627
--- /dev/null
+++ b/src/lib/encoding/keyval.h
@@ -0,0 +1,17 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file keyval.h
+ *
+ * \brief Header for keyval.c
+ **/
+
+#ifndef TOR_KEYVAL_H
+#define TOR_KEYVAL_H
+
+int string_is_key_value(int severity, const char *string);
+
+#endif
diff --git a/src/lib/encoding/time_fmt.c b/src/lib/encoding/time_fmt.c
new file mode 100644
index 0000000000..ea9c8e9fd1
--- /dev/null
+++ b/src/lib/encoding/time_fmt.c
@@ -0,0 +1,503 @@
+/* Copyright (c) 2001, Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file time_fmt.c
+ *
+ * \brief Encode and decode time in various formats.
+ *
+ * This module is higher-level than the conversion functions in "wallclock",
+ * and handles a larger variety of types. It converts between different time
+ * formats, and encodes and decodes them from strings.
+ **/
+
+#include "lib/encoding/time_fmt.h"
+#include "lib/log/torlog.h"
+#include "lib/log/escape.h"
+#include "lib/log/util_bug.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/string/printf.h"
+#include "lib/string/scanf.h"
+#include "lib/wallclock/tm_cvt.h"
+
+#include <string.h>
+#include <time.h>
+
+/** As localtime_r, but defined for platforms that don't have it:
+ *
+ * Convert *<b>timep</b> to a struct tm in local time, and store the value in
+ * *<b>result</b>. Return the result on success, or NULL on failure.
+ */
+struct tm *
+tor_localtime_r(const time_t *timep, struct tm *result)
+{
+ char *err = NULL;
+ struct tm *r = tor_localtime_r_msg(timep, result, &err);
+ if (err) {
+ log_warn(LD_BUG, "%s", err);
+ tor_free(err);
+ }
+ return r;
+}
+
+/** As gmtime_r, but defined for platforms that don't have it:
+ *
+ * Convert *<b>timep</b> to a struct tm in UTC, and store the value in
+ * *<b>result</b>. Return the result on success, or NULL on failure.
+ */
+struct tm *
+tor_gmtime_r(const time_t *timep, struct tm *result)
+{
+ char *err = NULL;
+ struct tm *r = tor_gmtime_r_msg(timep, result, &err);
+ if (err) {
+ log_warn(LD_BUG, "%s", err);
+ tor_free(err);
+ }
+ return r;
+}
+
+/** Yield true iff <b>y</b> is a leap-year. */
+#define IS_LEAPYEAR(y) (!(y % 4) && ((y % 100) || !(y % 400)))
+/** Helper: Return the number of leap-days between Jan 1, y1 and Jan 1, y2. */
+static int
+n_leapdays(int year1, int year2)
+{
+ --year1;
+ --year2;
+ return (year2/4 - year1/4) - (year2/100 - year1/100)
+ + (year2/400 - year1/400);
+}
+/** Number of days per month in non-leap year; used by tor_timegm and
+ * parse_rfc1123_time. */
+static const int days_per_month[] =
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+/** Compute a time_t given a struct tm. The result is given in UTC, and
+ * does not account for leap seconds. Return 0 on success, -1 on failure.
+ */
+int
+tor_timegm(const struct tm *tm, time_t *time_out)
+{
+ /* This is a pretty ironclad timegm implementation, snarfed from Python2.2.
+ * It's way more brute-force than fiddling with tzset().
+ *
+ * We use int64_t rather than time_t to avoid overflow on multiplication on
+ * platforms with 32-bit time_t. Since year is clipped to INT32_MAX, and
+ * since 365 * 24 * 60 * 60 is approximately 31 million, it's not possible
+ * for INT32_MAX years to overflow int64_t when converted to seconds. */
+ int64_t year, days, hours, minutes, seconds;
+ int i, invalid_year, dpm;
+
+ /* Initialize time_out to 0 for now, to avoid bad usage in case this function
+ fails and the caller ignores the return value. */
+ tor_assert(time_out);
+ *time_out = 0;
+
+ /* avoid int overflow on addition */
+ if (tm->tm_year < INT32_MAX-1900) {
+ year = tm->tm_year + 1900;
+ } else {
+ /* clamp year */
+ year = INT32_MAX;
+ }
+ invalid_year = (year < 1970 || tm->tm_year >= INT32_MAX-1900);
+
+ if (tm->tm_mon >= 0 && tm->tm_mon <= 11) {
+ dpm = days_per_month[tm->tm_mon];
+ if (tm->tm_mon == 1 && !invalid_year && IS_LEAPYEAR(tm->tm_year)) {
+ dpm = 29;
+ }
+ } else {
+ /* invalid month - default to 0 days per month */
+ dpm = 0;
+ }
+
+ if (invalid_year ||
+ tm->tm_mon < 0 || tm->tm_mon > 11 ||
+ tm->tm_mday < 1 || tm->tm_mday > dpm ||
+ tm->tm_hour < 0 || tm->tm_hour > 23 ||
+ tm->tm_min < 0 || tm->tm_min > 59 ||
+ tm->tm_sec < 0 || tm->tm_sec > 60) {
+ log_warn(LD_BUG, "Out-of-range argument to tor_timegm");
+ return -1;
+ }
+ days = 365 * (year-1970) + n_leapdays(1970,(int)year);
+ for (i = 0; i < tm->tm_mon; ++i)
+ days += days_per_month[i];
+ if (tm->tm_mon > 1 && IS_LEAPYEAR(year))
+ ++days;
+ days += tm->tm_mday - 1;
+ hours = days*24 + tm->tm_hour;
+
+ minutes = hours*60 + tm->tm_min;
+ seconds = minutes*60 + tm->tm_sec;
+ /* Check that "seconds" will fit in a time_t. On platforms where time_t is
+ * 32-bit, this check will fail for dates in and after 2038.
+ *
+ * We already know that "seconds" can't be negative because "year" >= 1970 */
+#if SIZEOF_TIME_T < 8
+ if (seconds < TIME_MIN || seconds > TIME_MAX) {
+ log_warn(LD_BUG, "Result does not fit in tor_timegm");
+ return -1;
+ }
+#endif /* SIZEOF_TIME_T < 8 */
+ *time_out = (time_t)seconds;
+ return 0;
+}
+
+/* strftime is locale-specific, so we need to replace those parts */
+
+/** A c-locale array of 3-letter names of weekdays, starting with Sun. */
+static const char *WEEKDAY_NAMES[] =
+ { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+/** A c-locale array of 3-letter names of months, starting with Jan. */
+static const char *MONTH_NAMES[] =
+ { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+/** Set <b>buf</b> to the RFC1123 encoding of the UTC value of <b>t</b>.
+ * The buffer must be at least RFC1123_TIME_LEN+1 bytes long.
+ *
+ * (RFC1123 format is "Fri, 29 Sep 2006 15:54:20 GMT". Note the "GMT"
+ * rather than "UTC".)
+ */
+void
+format_rfc1123_time(char *buf, time_t t)
+{
+ struct tm tm;
+
+ tor_gmtime_r(&t, &tm);
+
+ strftime(buf, RFC1123_TIME_LEN+1, "___, %d ___ %Y %H:%M:%S GMT", &tm);
+ tor_assert(tm.tm_wday >= 0);
+ tor_assert(tm.tm_wday <= 6);
+ memcpy(buf, WEEKDAY_NAMES[tm.tm_wday], 3);
+ tor_assert(tm.tm_mon >= 0);
+ tor_assert(tm.tm_mon <= 11);
+ memcpy(buf+8, MONTH_NAMES[tm.tm_mon], 3);
+}
+
+/** Parse the (a subset of) the RFC1123 encoding of some time (in UTC) from
+ * <b>buf</b>, and store the result in *<b>t</b>.
+ *
+ * Note that we only accept the subset generated by format_rfc1123_time above,
+ * not the full range of formats suggested by RFC 1123.
+ *
+ * Return 0 on success, -1 on failure.
+*/
+int
+parse_rfc1123_time(const char *buf, time_t *t)
+{
+ struct tm tm;
+ char month[4];
+ char weekday[4];
+ int i, m, invalid_year;
+ unsigned tm_mday, tm_year, tm_hour, tm_min, tm_sec;
+ unsigned dpm;
+
+ if (strlen(buf) != RFC1123_TIME_LEN)
+ return -1;
+ memset(&tm, 0, sizeof(tm));
+ if (tor_sscanf(buf, "%3s, %2u %3s %u %2u:%2u:%2u GMT", weekday,
+ &tm_mday, month, &tm_year, &tm_hour,
+ &tm_min, &tm_sec) < 7) {
+ char *esc = esc_for_log(buf);
+ log_warn(LD_GENERAL, "Got invalid RFC1123 time %s", esc);
+ tor_free(esc);
+ return -1;
+ }
+
+ m = -1;
+ for (i = 0; i < 12; ++i) {
+ if (!strcmp(month, MONTH_NAMES[i])) {
+ m = i;
+ break;
+ }
+ }
+ if (m<0) {
+ char *esc = esc_for_log(buf);
+ log_warn(LD_GENERAL, "Got invalid RFC1123 time %s: No such month", esc);
+ tor_free(esc);
+ return -1;
+ }
+ tm.tm_mon = m;
+
+ invalid_year = (tm_year >= INT32_MAX || tm_year < 1970);
+ tor_assert(m >= 0 && m <= 11);
+ dpm = days_per_month[m];
+ if (m == 1 && !invalid_year && IS_LEAPYEAR(tm_year)) {
+ dpm = 29;
+ }
+
+ if (invalid_year || tm_mday < 1 || tm_mday > dpm ||
+ tm_hour > 23 || tm_min > 59 || tm_sec > 60) {
+ char *esc = esc_for_log(buf);
+ log_warn(LD_GENERAL, "Got invalid RFC1123 time %s", esc);
+ tor_free(esc);
+ return -1;
+ }
+ tm.tm_mday = (int)tm_mday;
+ tm.tm_year = (int)tm_year;
+ tm.tm_hour = (int)tm_hour;
+ tm.tm_min = (int)tm_min;
+ tm.tm_sec = (int)tm_sec;
+
+ if (tm.tm_year < 1970) {
+ /* LCOV_EXCL_START
+ * XXXX I think this is dead code; we already checked for
+ * invalid_year above. */
+ tor_assert_nonfatal_unreached();
+ char *esc = esc_for_log(buf);
+ log_warn(LD_GENERAL,
+ "Got invalid RFC1123 time %s. (Before 1970)", esc);
+ tor_free(esc);
+ return -1;
+ /* LCOV_EXCL_STOP */
+ }
+ tm.tm_year -= 1900;
+
+ return tor_timegm(&tm, t);
+}
+
+/** Set <b>buf</b> to the ISO8601 encoding of the local value of <b>t</b>.
+ * The buffer must be at least ISO_TIME_LEN+1 bytes long.
+ *
+ * (ISO8601 format is 2006-10-29 10:57:20)
+ */
+void
+format_local_iso_time(char *buf, time_t t)
+{
+ struct tm tm;
+ strftime(buf, ISO_TIME_LEN+1, "%Y-%m-%d %H:%M:%S", tor_localtime_r(&t, &tm));
+}
+
+/** Set <b>buf</b> to the ISO8601 encoding of the GMT value of <b>t</b>.
+ * The buffer must be at least ISO_TIME_LEN+1 bytes long.
+ */
+void
+format_iso_time(char *buf, time_t t)
+{
+ struct tm tm;
+ strftime(buf, ISO_TIME_LEN+1, "%Y-%m-%d %H:%M:%S", tor_gmtime_r(&t, &tm));
+}
+
+/** As format_local_iso_time, but use the yyyy-mm-ddThh:mm:ss format to avoid
+ * embedding an internal space. */
+void
+format_local_iso_time_nospace(char *buf, time_t t)
+{
+ format_local_iso_time(buf, t);
+ buf[10] = 'T';
+}
+
+/** As format_iso_time, but use the yyyy-mm-ddThh:mm:ss format to avoid
+ * embedding an internal space. */
+void
+format_iso_time_nospace(char *buf, time_t t)
+{
+ format_iso_time(buf, t);
+ buf[10] = 'T';
+}
+
+/** As format_iso_time_nospace, but include microseconds in decimal
+ * fixed-point format. Requires that buf be at least ISO_TIME_USEC_LEN+1
+ * bytes long. */
+void
+format_iso_time_nospace_usec(char *buf, const struct timeval *tv)
+{
+ tor_assert(tv);
+ format_iso_time_nospace(buf, (time_t)tv->tv_sec);
+ tor_snprintf(buf+ISO_TIME_LEN, 8, ".%06d", (int)tv->tv_usec);
+}
+
+/** Given an ISO-formatted UTC time value (after the epoch) in <b>cp</b>,
+ * parse it and store its value in *<b>t</b>. Return 0 on success, -1 on
+ * failure. Ignore extraneous stuff in <b>cp</b> after the end of the time
+ * string, unless <b>strict</b> is set. If <b>nospace</b> is set,
+ * expect the YYYY-MM-DDTHH:MM:SS format. */
+int
+parse_iso_time_(const char *cp, time_t *t, int strict, int nospace)
+{
+ struct tm st_tm;
+ unsigned int year=0, month=0, day=0, hour=0, minute=0, second=0;
+ int n_fields;
+ char extra_char, separator_char;
+ n_fields = tor_sscanf(cp, "%u-%2u-%2u%c%2u:%2u:%2u%c",
+ &year, &month, &day,
+ &separator_char,
+ &hour, &minute, &second, &extra_char);
+ if (strict ? (n_fields != 7) : (n_fields < 7)) {
+ char *esc = esc_for_log(cp);
+ log_warn(LD_GENERAL, "ISO time %s was unparseable", esc);
+ tor_free(esc);
+ return -1;
+ }
+ if (separator_char != (nospace ? 'T' : ' ')) {
+ char *esc = esc_for_log(cp);
+ log_warn(LD_GENERAL, "ISO time %s was unparseable", esc);
+ tor_free(esc);
+ return -1;
+ }
+ if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
+ hour > 23 || minute > 59 || second > 60 || year >= INT32_MAX) {
+ char *esc = esc_for_log(cp);
+ log_warn(LD_GENERAL, "ISO time %s was nonsensical", esc);
+ tor_free(esc);
+ return -1;
+ }
+ st_tm.tm_year = (int)year-1900;
+ st_tm.tm_mon = month-1;
+ st_tm.tm_mday = day;
+ st_tm.tm_hour = hour;
+ st_tm.tm_min = minute;
+ st_tm.tm_sec = second;
+ st_tm.tm_wday = 0; /* Should be ignored. */
+
+ if (st_tm.tm_year < 70) {
+ /* LCOV_EXCL_START
+ * XXXX I think this is dead code; we already checked for
+ * year < 1970 above. */
+ tor_assert_nonfatal_unreached();
+ char *esc = esc_for_log(cp);
+ log_warn(LD_GENERAL, "Got invalid ISO time %s. (Before 1970)", esc);
+ tor_free(esc);
+ return -1;
+ /* LCOV_EXCL_STOP */
+ }
+ return tor_timegm(&st_tm, t);
+}
+
+/** Given an ISO-formatted UTC time value (after the epoch) in <b>cp</b>,
+ * parse it and store its value in *<b>t</b>. Return 0 on success, -1 on
+ * failure. Reject the string if any characters are present after the time.
+ */
+int
+parse_iso_time(const char *cp, time_t *t)
+{
+ return parse_iso_time_(cp, t, 1, 0);
+}
+
+/**
+ * As parse_iso_time, but parses a time encoded by format_iso_time_nospace().
+ */
+int
+parse_iso_time_nospace(const char *cp, time_t *t)
+{
+ return parse_iso_time_(cp, t, 1, 1);
+}
+
+/** Given a <b>date</b> in one of the three formats allowed by HTTP (ugh),
+ * parse it into <b>tm</b>. Return 0 on success, negative on failure. */
+int
+parse_http_time(const char *date, struct tm *tm)
+{
+ const char *cp;
+ char month[4];
+ char wkday[4];
+ int i;
+ unsigned tm_mday, tm_year, tm_hour, tm_min, tm_sec;
+
+ tor_assert(tm);
+ memset(tm, 0, sizeof(*tm));
+
+ /* First, try RFC1123 or RFC850 format: skip the weekday. */
+ if ((cp = strchr(date, ','))) {
+ ++cp;
+ if (*cp != ' ')
+ return -1;
+ ++cp;
+ if (tor_sscanf(cp, "%2u %3s %4u %2u:%2u:%2u GMT",
+ &tm_mday, month, &tm_year,
+ &tm_hour, &tm_min, &tm_sec) == 6) {
+ /* rfc1123-date */
+ tm_year -= 1900;
+ } else if (tor_sscanf(cp, "%2u-%3s-%2u %2u:%2u:%2u GMT",
+ &tm_mday, month, &tm_year,
+ &tm_hour, &tm_min, &tm_sec) == 6) {
+ /* rfc850-date */
+ } else {
+ return -1;
+ }
+ } else {
+ /* No comma; possibly asctime() format. */
+ if (tor_sscanf(date, "%3s %3s %2u %2u:%2u:%2u %4u",
+ wkday, month, &tm_mday,
+ &tm_hour, &tm_min, &tm_sec, &tm_year) == 7) {
+ tm_year -= 1900;
+ } else {
+ return -1;
+ }
+ }
+ tm->tm_mday = (int)tm_mday;
+ tm->tm_year = (int)tm_year;
+ tm->tm_hour = (int)tm_hour;
+ tm->tm_min = (int)tm_min;
+ tm->tm_sec = (int)tm_sec;
+ tm->tm_wday = 0; /* Leave this unset. */
+
+ month[3] = '\0';
+ /* Okay, now decode the month. */
+ /* set tm->tm_mon to dummy value so the check below fails. */
+ tm->tm_mon = -1;
+ for (i = 0; i < 12; ++i) {
+ if (!strcasecmp(MONTH_NAMES[i], month)) {
+ tm->tm_mon = i;
+ }
+ }
+
+ if (tm->tm_year < 0 ||
+ tm->tm_mon < 0 || tm->tm_mon > 11 ||
+ tm->tm_mday < 1 || tm->tm_mday > 31 ||
+ tm->tm_hour < 0 || tm->tm_hour > 23 ||
+ tm->tm_min < 0 || tm->tm_min > 59 ||
+ tm->tm_sec < 0 || tm->tm_sec > 60)
+ return -1; /* Out of range, or bad month. */
+
+ return 0;
+}
+
+/** Given an <b>interval</b> in seconds, try to write it to the
+ * <b>out_len</b>-byte buffer in <b>out</b> in a human-readable form.
+ * Returns a non-negative integer on success, -1 on failure.
+ */
+int
+format_time_interval(char *out, size_t out_len, long interval)
+{
+ /* We only report seconds if there's no hours. */
+ long sec = 0, min = 0, hour = 0, day = 0;
+
+ /* -LONG_MIN is LONG_MAX + 1, which causes signed overflow */
+ if (interval < -LONG_MAX)
+ interval = LONG_MAX;
+ else if (interval < 0)
+ interval = -interval;
+
+ if (interval >= 86400) {
+ day = interval / 86400;
+ interval %= 86400;
+ }
+ if (interval >= 3600) {
+ hour = interval / 3600;
+ interval %= 3600;
+ }
+ if (interval >= 60) {
+ min = interval / 60;
+ interval %= 60;
+ }
+ sec = interval;
+
+ if (day) {
+ return tor_snprintf(out, out_len, "%ld days, %ld hours, %ld minutes",
+ day, hour, min);
+ } else if (hour) {
+ return tor_snprintf(out, out_len, "%ld hours, %ld minutes", hour, min);
+ } else if (min) {
+ return tor_snprintf(out, out_len, "%ld minutes, %ld seconds", min, sec);
+ } else {
+ return tor_snprintf(out, out_len, "%ld seconds", sec);
+ }
+}
diff --git a/src/lib/encoding/time_fmt.h b/src/lib/encoding/time_fmt.h
new file mode 100644
index 0000000000..2892442adf
--- /dev/null
+++ b/src/lib/encoding/time_fmt.h
@@ -0,0 +1,44 @@
+/* Copyright (c) 2001, Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file time_fmt.h
+ *
+ * \brief Header for time_fmt.c
+ **/
+
+#ifndef TOR_TIME_FMT_H
+#define TOR_TIME_FMT_H
+
+#include "orconfig.h"
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+struct tm;
+struct timeval;
+
+struct tm *tor_localtime_r(const time_t *timep, struct tm *result);
+struct tm *tor_gmtime_r(const time_t *timep, struct tm *result);
+int tor_timegm(const struct tm *tm, time_t *time_out);
+
+#define RFC1123_TIME_LEN 29
+void format_rfc1123_time(char *buf, time_t t);
+int parse_rfc1123_time(const char *buf, time_t *t);
+#define ISO_TIME_LEN 19
+#define ISO_TIME_USEC_LEN (ISO_TIME_LEN+7)
+void format_local_iso_time(char *buf, time_t t);
+void format_iso_time(char *buf, time_t t);
+void format_local_iso_time_nospace(char *buf, time_t t);
+void format_iso_time_nospace(char *buf, time_t t);
+void format_iso_time_nospace_usec(char *buf, const struct timeval *tv);
+int parse_iso_time_(const char *cp, time_t *t, int strict, int nospace);
+int parse_iso_time(const char *buf, time_t *t);
+int parse_iso_time_nospace(const char *cp, time_t *t);
+int parse_http_time(const char *buf, struct tm *tm);
+int format_time_interval(char *out, size_t out_len, long interval);
+
+#endif
diff --git a/src/lib/err/.may_include b/src/lib/err/.may_include
new file mode 100644
index 0000000000..48cc0ef088
--- /dev/null
+++ b/src/lib/err/.may_include
@@ -0,0 +1,3 @@
+orconfig.h
+lib/cc/*.h
+lib/err/*.h
diff --git a/src/common/backtrace.c b/src/lib/err/backtrace.c
index f2498b2aa6..d18a595c34 100644
--- a/src/common/backtrace.c
+++ b/src/lib/err/backtrace.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
+/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -11,12 +11,14 @@
* family of functions, which are sometimes provided by libc and sometimes
* provided by libexecinfo. We tie into the sigaction() backend in order to
* detect crashes.
+ *
+ * This is one of the lowest-level modules, since nearly everything needs to
+ * be able to log an error. As such, it doesn't call the log module or any
+ * other higher-level modules directly.
*/
#include "orconfig.h"
-#include "compat.h"
-#include "util.h"
-#include "torlog.h"
+#include "lib/err/torerr.h"
#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
@@ -30,6 +32,10 @@
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
#ifdef HAVE_CYGWIN_SIGNAL_H
#include <cygwin/signal.h>
@@ -39,8 +45,13 @@
#include <ucontext.h>
#endif /* defined(HAVE_CYGWIN_SIGNAL_H) || ... */
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
#define EXPOSE_CLEAN_BACKTRACE
-#include "backtrace.h"
+#include "lib/err/backtrace.h"
+#include "lib/err/torerr.h"
#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
@@ -51,17 +62,21 @@
#define NO_BACKTRACE_IMPL
#endif
-/** Version of Tor to report in backtrace messages. */
-static char *bt_version = NULL;
+// Redundant with util.h, but doing it here so we can avoid that dependency.
+#define raw_free free
#ifdef USE_BACKTRACE
+/** Version of Tor to report in backtrace messages. */
+static char bt_version[128] = "";
+
/** Largest stack depth to try to dump. */
#define MAX_DEPTH 256
/** Static allocation of stack to dump. This is static so we avoid stack
* pressure. */
static void *cb_buf[MAX_DEPTH];
-/** Protects cb_buf from concurrent access */
-static tor_mutex_t cb_buf_mutex;
+/** Protects cb_buf from concurrent access. Pthreads, since this code
+ * is Unix-only, and since this code needs to be lowest-level. */
+static pthread_mutex_t cb_buf_mutex = PTHREAD_MUTEX_INITIALIZER;
/** Change a stacktrace in <b>stack</b> of depth <b>depth</b> so that it will
* log the correct function from which a signal was received with context
@@ -94,33 +109,35 @@ clean_backtrace(void **stack, size_t depth, const ucontext_t *ctx)
}
/** Log a message <b>msg</b> at <b>severity</b> in <b>domain</b>, and follow
- * that with a backtrace log. */
+ * that with a backtrace log. Send messages via the tor_log function at
+ * logger". */
void
-log_backtrace(int severity, int domain, const char *msg)
+log_backtrace_impl(int severity, int domain, const char *msg,
+ tor_log_fn logger)
{
size_t depth;
char **symbols;
size_t i;
- tor_mutex_acquire(&cb_buf_mutex);
+ pthread_mutex_lock(&cb_buf_mutex);
depth = backtrace(cb_buf, MAX_DEPTH);
symbols = backtrace_symbols(cb_buf, (int)depth);
- tor_log(severity, domain, "%s. Stack trace:", msg);
+ logger(severity, domain, "%s. Stack trace:", msg);
if (!symbols) {
/* LCOV_EXCL_START -- we can't provoke this. */
- tor_log(severity, domain, " Unable to generate backtrace.");
+ logger(severity, domain, " Unable to generate backtrace.");
goto done;
/* LCOV_EXCL_STOP */
}
for (i=0; i < depth; ++i) {
- tor_log(severity, domain, " %s", symbols[i]);
+ logger(severity, domain, " %s", symbols[i]);
}
raw_free(symbols);
done:
- tor_mutex_release(&cb_buf_mutex);
+ pthread_mutex_unlock(&cb_buf_mutex);
}
static void crash_handler(int sig, siginfo_t *si, void *ctx_)
@@ -155,18 +172,34 @@ crash_handler(int sig, siginfo_t *si, void *ctx_)
abort();
}
+/** Write a backtrace to all of the emergency-error fds. */
+void
+dump_stack_symbols_to_error_fds(void)
+{
+ int n_fds, i;
+ const int *fds = NULL;
+ size_t depth;
+
+ depth = backtrace(cb_buf, MAX_DEPTH);
+
+ n_fds = tor_log_get_sigsafe_err_fds(&fds);
+ for (i=0; i < n_fds; ++i)
+ backtrace_symbols_fd(cb_buf, (int)depth, fds[i]);
+}
+
/** Install signal handlers as needed so that when we crash, we produce a
- * useful stack trace. Return 0 on success, -1 on failure. */
+ * useful stack trace. Return 0 on success, -errno on failure. */
static int
-install_bt_handler(void)
+install_bt_handler(const char *software)
{
int trap_signals[] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGSYS,
SIGIO, -1 };
int i, rv=0;
- struct sigaction sa;
+ strncpy(bt_version, software, sizeof(bt_version) - 1);
+ bt_version[sizeof(bt_version) - 1] = 0;
- tor_mutex_init(&cb_buf_mutex);
+ struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = crash_handler;
@@ -176,8 +209,7 @@ install_bt_handler(void)
for (i = 0; trap_signals[i] >= 0; ++i) {
if (sigaction(trap_signals[i], &sa, NULL) == -1) {
/* LCOV_EXCL_START */
- log_warn(LD_BUG, "Sigaction failed: %s", strerror(errno));
- rv = -1;
+ rv = -errno;
/* LCOV_EXCL_STOP */
}
}
@@ -200,20 +232,21 @@ install_bt_handler(void)
static void
remove_bt_handler(void)
{
- tor_mutex_uninit(&cb_buf_mutex);
}
#endif /* defined(USE_BACKTRACE) */
#ifdef NO_BACKTRACE_IMPL
void
-log_backtrace(int severity, int domain, const char *msg)
+log_backtrace_impl(int severity, int domain, const char *msg,
+ tor_log_fn logger)
{
- tor_log(severity, domain, "%s. (Stack trace not available)", msg);
+ logger(severity, domain, "%s. (Stack trace not available)", msg);
}
static int
-install_bt_handler(void)
+install_bt_handler(const char *software)
{
+ (void) software;
return 0;
}
@@ -221,19 +254,24 @@ static void
remove_bt_handler(void)
{
}
+
+void
+dump_stack_symbols_to_error_fds(void)
+{
+}
#endif /* defined(NO_BACKTRACE_IMPL) */
/** Set up code to handle generating error messages on crashes. */
int
configure_backtrace_handler(const char *tor_version)
{
- tor_free(bt_version);
- if (tor_version)
- tor_asprintf(&bt_version, "Tor %s", tor_version);
- else
- tor_asprintf(&bt_version, "Tor");
+ char version[128] = "Tor\0";
- return install_bt_handler();
+ if (tor_version) {
+ snprintf(version, sizeof(version), "Tor %s", tor_version);
+ }
+
+ return install_bt_handler(version);
}
/** Perform end-of-process cleanup for code that generates error messages on
@@ -242,7 +280,4 @@ void
clean_up_backtrace_handler(void)
{
remove_bt_handler();
-
- tor_free(bt_version);
}
-
diff --git a/src/common/backtrace.h b/src/lib/err/backtrace.h
index 3d0ab8a90a..70c43484f5 100644
--- a/src/common/backtrace.h
+++ b/src/lib/err/backtrace.h
@@ -1,14 +1,29 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
+/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_BACKTRACE_H
#define TOR_BACKTRACE_H
+/**
+ * \file backtrace.h
+ *
+ * \brief Header for backtrace.c
+ **/
+
#include "orconfig.h"
+#include "lib/cc/compat_compiler.h"
+
+typedef void (*tor_log_fn)(int, unsigned, const char *fmt, ...)
+ CHECK_PRINTF(3,4);
-void log_backtrace(int severity, int domain, const char *msg);
+void log_backtrace_impl(int severity, int domain, const char *msg,
+ tor_log_fn logger);
int configure_backtrace_handler(const char *tor_version);
void clean_up_backtrace_handler(void);
+void dump_stack_symbols_to_error_fds(void);
+
+#define log_backtrace(sev, dom, msg) \
+ log_backtrace_impl((sev), (dom), (msg), tor_log)
#ifdef EXPOSE_CLEAN_BACKTRACE
#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
@@ -18,4 +33,3 @@ void clean_backtrace(void **stack, size_t depth, const ucontext_t *ctx);
#endif /* defined(EXPOSE_CLEAN_BACKTRACE) */
#endif /* !defined(TOR_BACKTRACE_H) */
-
diff --git a/src/lib/err/include.am b/src/lib/err/include.am
new file mode 100644
index 0000000000..f2a409c51e
--- /dev/null
+++ b/src/lib/err/include.am
@@ -0,0 +1,19 @@
+
+noinst_LIBRARIES += src/lib/libtor-err.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-err-testing.a
+endif
+
+src_lib_libtor_err_a_SOURCES = \
+ src/lib/err/backtrace.c \
+ src/lib/err/torerr.c
+
+src_lib_libtor_err_testing_a_SOURCES = \
+ $(src_lib_libtor_err_a_SOURCES)
+src_lib_libtor_err_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_err_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/err/backtrace.h \
+ src/lib/err/torerr.h
diff --git a/src/lib/err/torerr.c b/src/lib/err/torerr.c
new file mode 100644
index 0000000000..f9e139f967
--- /dev/null
+++ b/src/lib/err/torerr.c
@@ -0,0 +1,238 @@
+/* Copyright (c) 2001, Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file torerr.c
+ *
+ * \brief Handling code for unrecoverable emergencies, at a lower level
+ * than the logging code.
+ *
+ * There are plenty of places that things can go wrong in Tor's backend
+ * libraries: the allocator can fail, the locking subsystem can fail, and so
+ * on. But since these subsystems are used themselves by the logging module,
+ * they can't use the logging code directly to report their errors.
+ *
+ * As a workaround, the logging code provides this module with a set of raw
+ * fds to be used for reporting errors in the lowest-level Tor code.
+ */
+
+#include "orconfig.h"
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "lib/err/torerr.h"
+#include "lib/err/backtrace.h"
+
+/** Array of fds to log crash-style warnings to. */
+static int sigsafe_log_fds[TOR_SIGSAFE_LOG_MAX_FDS] = { STDERR_FILENO };
+/** The number of elements used in sigsafe_log_fds */
+static int n_sigsafe_log_fds = 1;
+/** Log granularity in milliseconds. */
+static int log_granularity = 1000;
+
+/** Write <b>s</b> to each element of sigsafe_log_fds. Return 0 on success, -1
+ * on failure. */
+static int
+tor_log_err_sigsafe_write(const char *s)
+{
+ int i;
+ ssize_t r;
+ size_t len = strlen(s);
+ int err = 0;
+ for (i=0; i < n_sigsafe_log_fds; ++i) {
+ r = write(sigsafe_log_fds[i], s, len);
+ err += (r != (ssize_t)len);
+ }
+ return err ? -1 : 0;
+}
+
+/** Given a list of string arguments ending with a NULL, writes them
+ * to our logs and to stderr (if possible). This function is safe to call
+ * from within a signal handler. */
+void
+tor_log_err_sigsafe(const char *m, ...)
+{
+ va_list ap;
+ const char *x;
+ char timebuf[33];
+ time_t now = time(NULL);
+
+ if (!m)
+ return;
+ if (log_granularity >= 2000) {
+ int g = log_granularity / 1000;
+ now -= now % g;
+ }
+ timebuf[0] = now < 0 ? '-' : ' ';
+ if (now < 0) now = -now;
+ timebuf[1] = '\0';
+ format_dec_number_sigsafe(now, timebuf+1, sizeof(timebuf)-1);
+ tor_log_err_sigsafe_write("\n=========================================="
+ "================== T=");
+ tor_log_err_sigsafe_write(timebuf);
+ tor_log_err_sigsafe_write("\n");
+ tor_log_err_sigsafe_write(m);
+ va_start(ap, m);
+ while ((x = va_arg(ap, const char*))) {
+ tor_log_err_sigsafe_write(x);
+ }
+ va_end(ap);
+}
+
+/** Set *<b>out</b> to a pointer to an array of the fds to log errors to from
+ * inside a signal handler or other emergency condition. Return the number of
+ * elements in the array. */
+int
+tor_log_get_sigsafe_err_fds(const int **out)
+{
+ *out = sigsafe_log_fds;
+ return n_sigsafe_log_fds;
+}
+
+/**
+ * Update the list of fds that get errors from inside a signal handler or
+ * other emergency condition. Ignore any beyond the first
+ * TOR_SIGSAFE_LOG_MAX_FDS.
+ */
+void
+tor_log_set_sigsafe_err_fds(const int *fds, int n)
+{
+ if (n > TOR_SIGSAFE_LOG_MAX_FDS) {
+ n = TOR_SIGSAFE_LOG_MAX_FDS;
+ }
+
+ memcpy(sigsafe_log_fds, fds, n * sizeof(int));
+ n_sigsafe_log_fds = n;
+}
+
+/**
+ * Set the granularity (in ms) to use when reporting fatal errors outside
+ * the logging system.
+ */
+void
+tor_log_sigsafe_err_set_granularity(int ms)
+{
+ log_granularity = ms;
+}
+
+/**
+ * Log an emergency assertion failure message.
+ *
+ * This kind of message is safe to send from within a log handler,
+ * a signal handler, or other emergency situation.
+ */
+void
+tor_raw_assertion_failed_msg_(const char *file, int line, const char *expr,
+ const char *msg)
+{
+ char linebuf[16];
+ format_dec_number_sigsafe(line, linebuf, sizeof(linebuf));
+ tor_log_err_sigsafe("INTERNAL ERROR: Raw assertion failed at ",
+ file, ":", linebuf, ": ", expr, NULL);
+ if (msg) {
+ tor_log_err_sigsafe_write(msg);
+ tor_log_err_sigsafe_write("\n");
+ }
+
+ dump_stack_symbols_to_error_fds();
+}
+
+/* As format_{hex,dex}_number_sigsafe, but takes a <b>radix</b> argument
+ * in range 2..16 inclusive. */
+static int
+format_number_sigsafe(unsigned long x, char *buf, int buf_len,
+ unsigned int radix)
+{
+ unsigned long tmp;
+ int len;
+ char *cp;
+
+ /* NOT tor_assert. This needs to be safe to run from within a signal
+ * handler, and from within the 'tor_assert() has failed' code. Not even
+ * raw_assert(), since raw_assert() calls this function on failure. */
+ if (radix < 2 || radix > 16)
+ return 0;
+
+ /* Count how many digits we need. */
+ tmp = x;
+ len = 1;
+ while (tmp >= radix) {
+ tmp /= radix;
+ ++len;
+ }
+
+ /* Not long enough */
+ if (!buf || len >= buf_len)
+ return 0;
+
+ cp = buf + len;
+ *cp = '\0';
+ do {
+ unsigned digit = (unsigned) (x % radix);
+ if (cp <= buf) {
+ /* Not tor_assert(); see above. */
+ abort();
+ }
+ --cp;
+ *cp = "0123456789ABCDEF"[digit];
+ x /= radix;
+ } while (x);
+
+ /* NOT tor_assert; see above. */
+ if (cp != buf) {
+ abort(); // LCOV_EXCL_LINE
+ }
+
+ return len;
+}
+
+/**
+ * Helper function to output hex numbers from within a signal handler.
+ *
+ * Writes the nul-terminated hexadecimal digits of <b>x</b> into a buffer
+ * <b>buf</b> of size <b>buf_len</b>, and return the actual number of digits
+ * written, not counting the terminal NUL.
+ *
+ * If there is insufficient space, write nothing and return 0.
+ *
+ * This accepts an unsigned int because format_helper_exit_status() needs to
+ * call it with a signed int and an unsigned char, and since the C standard
+ * does not guarantee that an int is wider than a char (an int must be at
+ * least 16 bits but it is permitted for a char to be that wide as well), we
+ * can't assume a signed int is sufficient to accommodate an unsigned char.
+ * Thus, format_helper_exit_status() will still need to emit any require '-'
+ * on its own.
+ *
+ * For most purposes, you'd want to use tor_snprintf("%x") instead of this
+ * function; it's designed to be used in code paths where you can't call
+ * arbitrary C functions.
+ */
+int
+format_hex_number_sigsafe(unsigned long x, char *buf, int buf_len)
+{
+ return format_number_sigsafe(x, buf, buf_len, 16);
+}
+
+/** As format_hex_number_sigsafe, but format the number in base 10. */
+int
+format_dec_number_sigsafe(unsigned long x, char *buf, int buf_len)
+{
+ return format_number_sigsafe(x, buf, buf_len, 10);
+}
diff --git a/src/lib/err/torerr.h b/src/lib/err/torerr.h
new file mode 100644
index 0000000000..d4bba6916f
--- /dev/null
+++ b/src/lib/err/torerr.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-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file torerr.h
+ *
+ * \brief Headers for torerr.c.
+ **/
+
+#ifndef TOR_TORERR_H
+#define TOR_TORERR_H
+
+#include "lib/cc/compat_compiler.h"
+
+/* The raw_assert...() variants are for use within code that can't call
+ * tor_assertion_failed_() because of call circularity issues. */
+#define raw_assert(expr) STMT_BEGIN \
+ if (!(expr)) { \
+ tor_raw_assertion_failed_msg_(__FILE__, __LINE__, #expr, NULL); \
+ abort(); \
+ } \
+ STMT_END
+#define raw_assert_unreached(expr) raw_assert(0)
+#define raw_assert_unreached_msg(msg) STMT_BEGIN \
+ tor_raw_assertion_failed_msg_(__FILE__, __LINE__, "0", (msg)); \
+ abort(); \
+ STMT_END
+
+void tor_raw_assertion_failed_msg_(const char *file, int line,
+ const char *expr,
+ const char *msg);
+
+/** Maximum number of fds that will get notifications if we crash */
+#define TOR_SIGSAFE_LOG_MAX_FDS 8
+
+void tor_log_err_sigsafe(const char *m, ...);
+int tor_log_get_sigsafe_err_fds(const int **out);
+void tor_log_set_sigsafe_err_fds(const int *fds, int n);
+void tor_log_sigsafe_err_set_granularity(int ms);
+
+int format_hex_number_sigsafe(unsigned long x, char *buf, int max_len);
+int format_dec_number_sigsafe(unsigned long x, char *buf, int max_len);
+
+#endif /* !defined(TOR_TORLOG_H) */
diff --git a/src/lib/evloop/.may_include b/src/lib/evloop/.may_include
new file mode 100644
index 0000000000..30af508914
--- /dev/null
+++ b/src/lib/evloop/.may_include
@@ -0,0 +1,16 @@
+orconfig.h
+
+lib/cc/*.h
+lib/crypt_ops/*.h
+lib/evloop/*.h
+lib/intmath/*.h
+lib/log/*.h
+lib/malloc/*.h
+lib/net/*.h
+lib/string/*.h
+lib/testsupport/*.h
+lib/thread/*.h
+lib/time/*.h
+
+src/ext/timeouts/timeout.c
+tor_queue.h \ No newline at end of file
diff --git a/src/common/compat_libevent.c b/src/lib/evloop/compat_libevent.c
index e60eb148d8..5e5faf163c 100644
--- a/src/common/compat_libevent.c
+++ b/src/lib/evloop/compat_libevent.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2017, The Tor Project, Inc. */
+/* Copyright (c) 2009-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -7,17 +7,17 @@
*/
#include "orconfig.h"
-#include "compat.h"
#define COMPAT_LIBEVENT_PRIVATE
-#include "compat_libevent.h"
+#include "lib/evloop/compat_libevent.h"
-#include "crypto_rand.h"
-
-#include "util.h"
-#include "torlog.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/string/compat_string.h"
#include <event2/event.h>
#include <event2/thread.h>
+#include <string.h>
/** A string which, if it appears in a libevent log, should be ignored. */
static const char *suppress_msg = NULL;
@@ -533,4 +533,3 @@ tor_libevent_postfork(void)
tor_assert(r == 0);
}
#endif /* defined(TOR_UNIT_TESTS) */
-
diff --git a/src/common/compat_libevent.h b/src/lib/evloop/compat_libevent.h
index 286a268122..0a50cfa667 100644
--- a/src/common/compat_libevent.h
+++ b/src/lib/evloop/compat_libevent.h
@@ -1,11 +1,12 @@
-/* Copyright (c) 2009-2017, The Tor Project, Inc. */
+/* Copyright (c) 2009-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_COMPAT_LIBEVENT_H
#define TOR_COMPAT_LIBEVENT_H
#include "orconfig.h"
-#include "testsupport.h"
+#include "lib/testsupport/testsupport.h"
+#include "lib/malloc/util_malloc.h"
void configure_libevent_logging(void);
void suppress_libevent_log_msg(const char *msg);
@@ -19,6 +20,7 @@ void suppress_libevent_log_msg(const char *msg);
struct event;
struct event_base;
+struct timeval;
void tor_event_free_(struct event *ev);
#define tor_event_free(ev) \
@@ -95,4 +97,3 @@ libevent_logging_callback(int severity, const char *msg);
#endif /* defined(COMPAT_LIBEVENT_PRIVATE) */
#endif /* !defined(TOR_COMPAT_LIBEVENT_H) */
-
diff --git a/src/lib/evloop/include.am b/src/lib/evloop/include.am
new file mode 100644
index 0000000000..6b0076272a
--- /dev/null
+++ b/src/lib/evloop/include.am
@@ -0,0 +1,26 @@
+
+noinst_LIBRARIES += src/lib/libtor-evloop.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-evloop-testing.a
+endif
+
+src_lib_libtor_evloop_a_SOURCES = \
+ src/lib/evloop/compat_libevent.c \
+ src/lib/evloop/procmon.c \
+ src/lib/evloop/timers.c \
+ src/lib/evloop/token_bucket.c \
+ src/lib/evloop/workqueue.c
+
+
+src_lib_libtor_evloop_testing_a_SOURCES = \
+ $(src_lib_libtor_evloop_a_SOURCES)
+src_lib_libtor_evloop_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_evloop_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/evloop/compat_libevent.h \
+ src/lib/evloop/procmon.h \
+ src/lib/evloop/timers.h \
+ src/lib/evloop/token_bucket.h \
+ src/lib/evloop/workqueue.h
diff --git a/src/common/procmon.c b/src/lib/evloop/procmon.c
index 73c14cd584..a923fbad74 100644
--- a/src/common/procmon.c
+++ b/src/lib/evloop/procmon.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Tor Project, Inc. */
+/* Copyright (c) 2011-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -6,9 +6,13 @@
* \brief Process-termination monitor functions
**/
-#include "procmon.h"
+#include "lib/evloop/procmon.h"
-#include "util.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/log/win32err.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/string/parse_int.h"
#ifdef HAVE_SIGNAL_H
#include <signal.h>
@@ -18,6 +22,7 @@
#endif
#ifdef _WIN32
+#include <winsock2.h>
#include <windows.h>
#endif
@@ -30,8 +35,8 @@ typedef int pid_t;
#define PID_T_FORMAT "%d"
#elif (SIZEOF_PID_T == SIZEOF_LONG)
#define PID_T_FORMAT "%ld"
-#elif (SIZEOF_PID_T == SIZEOF_INT64_T)
-#define PID_T_FORMAT I64_FORMAT
+#elif (SIZEOF_PID_T == 8)
+#define PID_T_FORMAT "%"PRId64
#else
#error Unknown: SIZEOF_PID_T
#endif /* (0 == SIZEOF_PID_T) && defined(_WIN32) || ... */
@@ -329,4 +334,3 @@ tor_process_monitor_free_(tor_process_monitor_t *procmon)
tor_free(procmon);
}
-
diff --git a/src/common/procmon.h b/src/lib/evloop/procmon.h
index 63777e4111..b596e5cc6d 100644
--- a/src/common/procmon.h
+++ b/src/lib/evloop/procmon.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Tor Project, Inc. */
+/* Copyright (c) 2011-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,10 +9,9 @@
#ifndef TOR_PROCMON_H
#define TOR_PROCMON_H
-#include "compat.h"
-#include "compat_libevent.h"
+#include "lib/evloop/compat_libevent.h"
-#include "torlog.h"
+#include "lib/log/torlog.h"
typedef struct tor_process_monitor_t tor_process_monitor_t;
diff --git a/src/common/timers.c b/src/lib/evloop/timers.c
index 6f6236ed3b..c07bd2e726 100644
--- a/src/common/timers.c
+++ b/src/lib/evloop/timers.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -31,11 +31,18 @@
#define TOR_TIMERS_PRIVATE
-#include "compat.h"
-#include "compat_libevent.h"
-#include "timers.h"
-#include "torlog.h"
-#include "util.h"
+#include "lib/evloop/compat_libevent.h"
+#include "lib/evloop/timers.h"
+#include "lib/intmath/muldiv.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/time/compat_time.h"
+
+#ifdef _WIN32
+// For struct timeval.
+#include <winsock2.h>
+#endif
struct timeout_cb {
timer_cb_fn_t cb;
@@ -315,4 +322,3 @@ timer_disable(tor_timer_t *t)
/* We don't reschedule the libevent timer here, since it's okay if it fires
* early. */
}
-
diff --git a/src/common/timers.h b/src/lib/evloop/timers.h
index 6d27f3e01e..2348c7b7c1 100644
--- a/src/common/timers.h
+++ b/src/lib/evloop/timers.h
@@ -1,11 +1,11 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TIMERS_H
#define TOR_TIMERS_H
#include "orconfig.h"
-#include "testsupport.h"
+#include "lib/testsupport/testsupport.h"
struct monotime_t;
typedef struct timeout tor_timer_t;
diff --git a/src/common/token_bucket.c b/src/lib/evloop/token_bucket.c
index f2396ec58a..f7cd05c6c5 100644
--- a/src/common/token_bucket.c
+++ b/src/lib/evloop/token_bucket.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -18,8 +18,12 @@
#define TOKEN_BUCKET_PRIVATE
-#include "token_bucket.h"
-#include "util_bug.h"
+#include "lib/evloop/token_bucket.h"
+#include "lib/log/util_bug.h"
+#include "lib/intmath/cmp.h"
+#include "lib/time/compat_time.h"
+
+#include <string.h>
/**
* Set the <b>rate</b> and <b>burst</b> value in a token_bucket_cfg.
@@ -252,4 +256,3 @@ token_bucket_rw_dec(token_bucket_rw_t *bucket,
flags |= TB_WRITE;
return flags;
}
-
diff --git a/src/common/token_bucket.h b/src/lib/evloop/token_bucket.h
index 0e7832e838..787317fa1f 100644
--- a/src/common/token_bucket.h
+++ b/src/lib/evloop/token_bucket.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,8 +9,8 @@
#ifndef TOR_TOKEN_BUCKET_H
#define TOR_TOKEN_BUCKET_H
-#include "torint.h"
-#include "testsupport.h"
+#include "lib/cc/torint.h"
+#include "lib/testsupport/testsupport.h"
/** Largest allowable burst value for a token buffer. */
#define TOKEN_BUCKET_MAX_BURST INT32_MAX
diff --git a/src/common/workqueue.c b/src/lib/evloop/workqueue.c
index 563a98af96..4d36f352e3 100644
--- a/src/common/workqueue.c
+++ b/src/lib/evloop/workqueue.c
@@ -24,16 +24,21 @@
*/
#include "orconfig.h"
-#include "compat.h"
-#include "compat_libevent.h"
-#include "compat_threads.h"
-#include "crypto_rand.h"
-#include "util.h"
-#include "workqueue.h"
-#include "tor_queue.h"
-#include "torlog.h"
+#include "lib/evloop/compat_libevent.h"
+#include "lib/evloop/workqueue.h"
+
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/intmath/weakrng.h"
+#include "lib/log/ratelim.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/net/alertsock.h"
+#include "lib/net/socket.h"
+#include "lib/thread/threads.h"
+#include "tor_queue.h"
#include <event2/event.h>
+#include <string.h>
#define WORKQUEUE_PRIORITY_FIRST WQ_PRI_HIGH
#define WORKQUEUE_PRIORITY_LAST WQ_PRI_LOW
@@ -675,4 +680,3 @@ replyqueue_process(replyqueue_t *queue)
tor_mutex_release(&queue->lock);
}
-
diff --git a/src/common/workqueue.h b/src/lib/evloop/workqueue.h
index e1fe612e2b..4e5c424be6 100644
--- a/src/common/workqueue.h
+++ b/src/lib/evloop/workqueue.h
@@ -1,10 +1,10 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
+/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_WORKQUEUE_H
#define TOR_WORKQUEUE_H
-#include "compat.h"
+#include "lib/cc/torint.h"
/** A replyqueue is used to tell the main thread about the outcome of
* work that we queued for the workers. */
@@ -63,4 +63,3 @@ int threadpool_register_reply_event(threadpool_t *tp,
void (*cb)(threadpool_t *tp));
#endif /* !defined(TOR_WORKQUEUE_H) */
-
diff --git a/src/lib/fdio/.may_include b/src/lib/fdio/.may_include
new file mode 100644
index 0000000000..30fd277b81
--- /dev/null
+++ b/src/lib/fdio/.may_include
@@ -0,0 +1,4 @@
+orconfig.h
+lib/cc/*.h
+lib/err/*.h
+lib/fdio/*.h
diff --git a/src/lib/fdio/fdio.c b/src/lib/fdio/fdio.c
new file mode 100644
index 0000000000..afb57e03dd
--- /dev/null
+++ b/src/lib/fdio/fdio.c
@@ -0,0 +1,115 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file fdio.c
+ *
+ * \brief Low-level compatibility wrappers for fd-based IO.
+ **/
+
+#include "orconfig.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include "lib/fdio/fdio.h"
+#include "lib/cc/torint.h"
+#include "lib/err/torerr.h"
+
+#include <stdlib.h>
+
+/** @{ */
+/** Some old versions of Unix didn't define constants for these values,
+ * and instead expect you to say 0, 1, or 2. */
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif
+/** @} */
+
+/** Return the position of <b>fd</b> with respect to the start of the file. */
+off_t
+tor_fd_getpos(int fd)
+{
+#ifdef _WIN32
+ return (off_t) _lseek(fd, 0, SEEK_CUR);
+#else
+ return (off_t) lseek(fd, 0, SEEK_CUR);
+#endif
+}
+
+/** Move <b>fd</b> to the end of the file. Return -1 on error, 0 on success.
+ * If the file is a pipe, do nothing and succeed.
+ **/
+int
+tor_fd_seekend(int fd)
+{
+#ifdef _WIN32
+ return _lseek(fd, 0, SEEK_END) < 0 ? -1 : 0;
+#else
+ off_t rc = lseek(fd, 0, SEEK_END) < 0 ? -1 : 0;
+#ifdef ESPIPE
+ /* If we get an error and ESPIPE, then it's a pipe or a socket of a fifo:
+ * no need to worry. */
+ if (rc < 0 && errno == ESPIPE)
+ rc = 0;
+#endif /* defined(ESPIPE) */
+ return (rc < 0) ? -1 : 0;
+#endif /* defined(_WIN32) */
+}
+
+/** Move <b>fd</b> to position <b>pos</b> in the file. Return -1 on error, 0
+ * on success. */
+int
+tor_fd_setpos(int fd, off_t pos)
+{
+#ifdef _WIN32
+ return _lseek(fd, pos, SEEK_SET) < 0 ? -1 : 0;
+#else
+ return lseek(fd, pos, SEEK_SET) < 0 ? -1 : 0;
+#endif
+}
+
+/** Replacement for ftruncate(fd, 0): move to the front of the file and remove
+ * all the rest of the file. Return -1 on error, 0 on success. */
+int
+tor_ftruncate(int fd)
+{
+ /* Rumor has it that some versions of ftruncate do not move the file pointer.
+ */
+ if (tor_fd_setpos(fd, 0) < 0)
+ return -1;
+
+#ifdef _WIN32
+ return _chsize(fd, 0);
+#else
+ return ftruncate(fd, 0);
+#endif
+}
+
+/** Minimal version of write_all, for use by logging. */
+int
+write_all_to_fd_minimal(int fd, const char *buf, size_t count)
+{
+ size_t written = 0;
+ raw_assert(count < SSIZE_MAX);
+
+ while (written < count) {
+ ssize_t result = write(fd, buf+written, count-written);
+ if (result<0)
+ return -1;
+ written += result;
+ }
+ return 0;
+}
diff --git a/src/lib/fdio/fdio.h b/src/lib/fdio/fdio.h
new file mode 100644
index 0000000000..c8f05455b7
--- /dev/null
+++ b/src/lib/fdio/fdio.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file fdio.h
+ *
+ * \brief Header for fdio.c
+ **/
+
+#ifndef TOR_FDIO_H
+#define TOR_FDIO_H
+
+#include <stddef.h>
+
+off_t tor_fd_getpos(int fd);
+int tor_fd_setpos(int fd, off_t pos);
+int tor_fd_seekend(int fd);
+int tor_ftruncate(int fd);
+int write_all_to_fd_minimal(int fd, const char *buf, size_t count);
+
+#endif /* !defined(TOR_FDIO_H) */
diff --git a/src/lib/fdio/include.am b/src/lib/fdio/include.am
new file mode 100644
index 0000000000..6c18f00a0d
--- /dev/null
+++ b/src/lib/fdio/include.am
@@ -0,0 +1,17 @@
+
+noinst_LIBRARIES += src/lib/libtor-fdio.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-fdio-testing.a
+endif
+
+src_lib_libtor_fdio_a_SOURCES = \
+ src/lib/fdio/fdio.c
+
+src_lib_libtor_fdio_testing_a_SOURCES = \
+ $(src_lib_libtor_fdio_a_SOURCES)
+src_lib_libtor_fdio_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_fdio_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/fdio/fdio.h
diff --git a/src/lib/fs/.may_include b/src/lib/fs/.may_include
new file mode 100644
index 0000000000..6c9ce6ca04
--- /dev/null
+++ b/src/lib/fs/.may_include
@@ -0,0 +1,13 @@
+orconfig.h
+lib/cc/*.h
+lib/container/*.h
+lib/encoding/*.h
+lib/err/*.h
+lib/fdio/*.h
+lib/fs/*.h
+lib/log/*.h
+lib/malloc/*.h
+lib/memarea/*.h
+lib/sandbox/*.h
+lib/string/*.h
+lib/testsupport/testsupport.h
diff --git a/src/lib/fs/conffile.c b/src/lib/fs/conffile.c
new file mode 100644
index 0000000000..600c7f6b70
--- /dev/null
+++ b/src/lib/fs/conffile.c
@@ -0,0 +1,174 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file conffile.h
+ *
+ * \brief Read configuration files from disk, with full `%include` support.
+ **/
+
+#include "lib/fs/conffile.h"
+
+#include "lib/container/smartlist.h"
+#include "lib/encoding/confline.h"
+#include "lib/fs/dir.h"
+#include "lib/fs/files.h"
+#include "lib/fs/path.h"
+#include "lib/log/torlog.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/string/printf.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,
+ int extended, config_line_t **config,
+ config_line_t **config_last,
+ smartlist_t *opened_lst);
+static int config_process_include(const char *path, int recursion_level,
+ int extended, config_line_t **list,
+ config_line_t **list_last,
+ smartlist_t *opened_lst);
+
+/** Helper: parse the config string and strdup into key/value
+ * strings. Set *result to the list, or NULL if parsing the string
+ * failed. Set *has_include to 1 if <b>result</b> has values from
+ * %included files. <b>opened_lst</b> will have a list of opened files if
+ * provided. Return 0 on success, -1 on failure. Warn and ignore any
+ * misformatted lines.
+ *
+ * If <b>extended</b> is set, then treat keys beginning with / and with + as
+ * indicating "clear" and "append" respectively. */
+int
+config_get_lines_include(const char *string, config_line_t **result,
+ int extended, int *has_include,
+ smartlist_t *opened_lst)
+{
+ return config_get_lines_aux(string, result, extended, 1, has_include,
+ 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.
+ */
+static smartlist_t *
+config_get_file_list(const char *path, smartlist_t *opened_files)
+{
+ smartlist_t *file_list = smartlist_new();
+
+ if (opened_files) {
+ smartlist_add_strdup(opened_files, path);
+ }
+
+ 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);
+ return NULL;
+ }
+ smartlist_sort_strings(all_files);
+ SMARTLIST_FOREACH_BEGIN(all_files, char *, f) {
+ if (f[0] == '.') {
+ tor_free(f);
+ continue;
+ }
+
+ char *fullname;
+ tor_asprintf(&fullname, "%s"PATH_SEPARATOR"%s", path, f);
+ tor_free(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_free(all_files);
+ return file_list;
+ } else if (file_type == FN_EMPTY) {
+ return file_list;
+ } else {
+ smartlist_free(file_list);
+ return NULL;
+ }
+}
+
+/** Creates a list of config lines present on included <b>path</b>.
+ * Set <b>config</b> to the list and <b>config_last</b> to the last element of
+ * <b>config</b>. <b>opened_lst</b> will have a list of opened files if
+ * provided. Return 0 on success, -1 on failure. */
+static int
+config_get_included_config(const char *path, int recursion_level, int extended,
+ config_line_t **config, config_line_t **config_last,
+ smartlist_t *opened_lst)
+{
+ char *included_conf = read_file_to_str(path, 0, NULL);
+ if (!included_conf) {
+ return -1;
+ }
+
+ if (config_get_lines_aux(included_conf, config, extended, 1, NULL,
+ opened_lst, recursion_level+1, config_last,
+ config_process_include) < 0) {
+ tor_free(included_conf);
+ return -1;
+ }
+
+ tor_free(included_conf);
+ return 0;
+}
+
+/** Process an %include <b>path</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_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);
+ if (!config_files) {
+ return -1;
+ }
+
+ int rv = -1;
+ SMARTLIST_FOREACH_BEGIN(config_files, const char *, config_file) {
+ config_line_t *included_config = NULL;
+ if (config_get_included_config(config_file, recursion_level, extended,
+ &included_config, list_last,
+ opened_lst) < 0) {
+ goto done;
+ }
+
+ *next = included_config;
+ if (*list_last)
+ next = &(*list_last)->next;
+
+ } SMARTLIST_FOREACH_END(config_file);
+ *list = ret_list;
+ rv = 0;
+
+ done:
+ SMARTLIST_FOREACH(config_files, char *, f, tor_free(f));
+ smartlist_free(config_files);
+ return rv;
+}
diff --git a/src/lib/fs/conffile.h b/src/lib/fs/conffile.h
new file mode 100644
index 0000000000..a926f4ac05
--- /dev/null
+++ b/src/lib/fs/conffile.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_CONFFILE_H
+#define TOR_CONFFILE_H
+
+/**
+ * \file conffile.h
+ *
+ * \brief Header for conffile.c
+ **/
+
+struct smartlist_t;
+struct config_line_t;
+
+int config_get_lines_include(const char *string, struct config_line_t **result,
+ int extended, int *has_include,
+ struct smartlist_t *opened_lst);
+
+#endif /* !defined(TOR_CONFLINE_H) */
diff --git a/src/lib/fs/dir.c b/src/lib/fs/dir.c
new file mode 100644
index 0000000000..cc339f747e
--- /dev/null
+++ b/src/lib/fs/dir.c
@@ -0,0 +1,367 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file dir.c
+ *
+ * \brief Read directories, and create directories with restrictive
+ * permissions.
+ **/
+
+#include "lib/fs/dir.h"
+#include "lib/fs/path.h"
+#include "lib/fs/userdb.h"
+
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/log/win32err.h"
+#include "lib/container/smartlist.h"
+#include "lib/sandbox/sandbox.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/string/printf.h"
+#include "lib/string/compat_string.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 HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef _WIN32
+#include <io.h>
+#include <direct.h>
+#include <windows.h>
+#else /* !(defined(_WIN32)) */
+#include <dirent.h>
+#include <pwd.h>
+#include <grp.h>
+#endif /* defined(_WIN32) */
+
+#include <errno.h>
+#include <string.h>
+
+/** Check whether <b>dirname</b> exists and is private. If yes return 0.
+ * If <b>dirname</b> does not exist:
+ * - if <b>check</b>&CPD_CREATE, try to create it and return 0 on success.
+ * - if <b>check</b>&CPD_CHECK, and we think we can create it, return 0.
+ * - if <b>check</b>&CPD_CHECK is false, and the directory exists, return 0.
+ * - otherwise, return -1.
+ * If CPD_GROUP_OK is set, then it's okay if the directory
+ * is group-readable, but in all cases we create the directory mode 0700.
+ * If CPD_GROUP_READ is set, existing directory behaves as CPD_GROUP_OK and
+ * if the directory is created it will use mode 0750 with group read
+ * permission. Group read privileges also assume execute permission
+ * as norm for directories. If CPD_CHECK_MODE_ONLY is set, then we don't
+ * alter the directory permissions if they are too permissive:
+ * we just return -1.
+ * When effective_user is not NULL, check permissions against the given user
+ * and its primary group.
+ */
+MOCK_IMPL(int,
+check_private_dir,(const char *dirname, cpd_check_t check,
+ const char *effective_user))
+{
+ int r;
+ struct stat st;
+
+ tor_assert(dirname);
+
+#ifndef _WIN32
+ int fd;
+ const struct passwd *pw = NULL;
+ uid_t running_uid;
+ gid_t running_gid;
+
+ /*
+ * Goal is to harden the implementation by removing any
+ * potential for race between stat() and chmod().
+ * chmod() accepts filename as argument. If an attacker can move
+ * the file between stat() and chmod(), a potential race exists.
+ *
+ * Several suggestions taken from:
+ * https://developer.apple.com/library/mac/documentation/
+ * Security/Conceptual/SecureCodingGuide/Articles/RaceConditions.html
+ */
+
+ /* Open directory.
+ * O_NOFOLLOW to ensure that it does not follow symbolic links */
+ fd = open(sandbox_intern_string(dirname), O_NOFOLLOW);
+
+ /* Was there an error? Maybe the directory does not exist? */
+ if (fd == -1) {
+
+ if (errno != ENOENT) {
+ /* Other directory error */
+ log_warn(LD_FS, "Directory %s cannot be read: %s", dirname,
+ strerror(errno));
+ return -1;
+ }
+
+ /* Received ENOENT: Directory does not exist */
+
+ /* Should we create the directory? */
+ if (check & CPD_CREATE) {
+ log_info(LD_GENERAL, "Creating directory %s", dirname);
+ if (check & CPD_GROUP_READ) {
+ r = mkdir(dirname, 0750);
+ } else {
+ r = mkdir(dirname, 0700);
+ }
+
+ /* check for mkdir() error */
+ if (r) {
+ log_warn(LD_FS, "Error creating directory %s: %s", dirname,
+ strerror(errno));
+ return -1;
+ }
+
+ /* we just created the directory. try to open it again.
+ * permissions on the directory will be checked again below.*/
+ fd = open(sandbox_intern_string(dirname), O_NOFOLLOW);
+
+ if (fd == -1) {
+ log_warn(LD_FS, "Could not reopen recently created directory %s: %s",
+ dirname,
+ strerror(errno));
+ return -1;
+ } else {
+ close(fd);
+ }
+
+ } else if (!(check & CPD_CHECK)) {
+ log_warn(LD_FS, "Directory %s does not exist.", dirname);
+ return -1;
+ }
+
+ /* XXXX In the case where check==CPD_CHECK, we should look at the
+ * parent directory a little harder. */
+ return 0;
+ }
+
+ tor_assert(fd >= 0);
+
+ //f = tor_strdup(dirname);
+ //clean_name_for_stat(f);
+ log_debug(LD_FS, "stat()ing %s", dirname);
+ //r = stat(sandbox_intern_string(f), &st);
+ r = fstat(fd, &st);
+ if (r == -1) {
+ log_warn(LD_FS, "fstat() on directory %s failed.", dirname);
+ close(fd);
+ return -1;
+ }
+ //tor_free(f);
+
+ /* check that dirname is a directory */
+ if (!(st.st_mode & S_IFDIR)) {
+ log_warn(LD_FS, "%s is not a directory", dirname);
+ close(fd);
+ return -1;
+ }
+
+ if (effective_user) {
+ /* Look up the user and group information.
+ * If we have a problem, bail out. */
+ pw = tor_getpwnam(effective_user);
+ if (pw == NULL) {
+ log_warn(LD_CONFIG, "Error setting configured user: %s not found",
+ effective_user);
+ close(fd);
+ return -1;
+ }
+ running_uid = pw->pw_uid;
+ running_gid = pw->pw_gid;
+ } else {
+ running_uid = getuid();
+ running_gid = getgid();
+ }
+ if (st.st_uid != running_uid) {
+ char *process_ownername = NULL, *file_ownername = NULL;
+
+ {
+ const struct passwd *pw_running = tor_getpwuid(running_uid);
+ process_ownername = pw_running ? tor_strdup(pw_running->pw_name) :
+ tor_strdup("<unknown>");
+ }
+
+ {
+ const struct passwd *pw_stat = tor_getpwuid(st.st_uid);
+ file_ownername = pw_stat ? tor_strdup(pw_stat->pw_name) :
+ tor_strdup("<unknown>");
+ }
+
+ log_warn(LD_FS, "%s is not owned by this user (%s, %d) but by "
+ "%s (%d). Perhaps you are running Tor as the wrong user?",
+ dirname, process_ownername, (int)running_uid,
+ file_ownername, (int)st.st_uid);
+
+ tor_free(process_ownername);
+ tor_free(file_ownername);
+ close(fd);
+ return -1;
+ }
+ if ( (check & (CPD_GROUP_OK|CPD_GROUP_READ))
+ && (st.st_gid != running_gid) && (st.st_gid != 0)) {
+ struct group *gr;
+ char *process_groupname = NULL;
+ gr = getgrgid(running_gid);
+ process_groupname = gr ? tor_strdup(gr->gr_name) : tor_strdup("<unknown>");
+ gr = getgrgid(st.st_gid);
+
+ log_warn(LD_FS, "%s is not owned by this group (%s, %d) but by group "
+ "%s (%d). Are you running Tor as the wrong user?",
+ dirname, process_groupname, (int)running_gid,
+ gr ? gr->gr_name : "<unknown>", (int)st.st_gid);
+
+ tor_free(process_groupname);
+ close(fd);
+ return -1;
+ }
+ unsigned unwanted_bits = 0;
+ if (check & (CPD_GROUP_OK|CPD_GROUP_READ)) {
+ unwanted_bits = 0027;
+ } else {
+ unwanted_bits = 0077;
+ }
+ unsigned check_bits_filter = ~0;
+ if (check & CPD_RELAX_DIRMODE_CHECK) {
+ check_bits_filter = 0022;
+ }
+ if ((st.st_mode & unwanted_bits & check_bits_filter) != 0) {
+ unsigned new_mode;
+ if (check & CPD_CHECK_MODE_ONLY) {
+ log_warn(LD_FS, "Permissions on directory %s are too permissive.",
+ dirname);
+ close(fd);
+ return -1;
+ }
+ log_warn(LD_FS, "Fixing permissions on directory %s", dirname);
+ new_mode = st.st_mode;
+ new_mode |= 0700; /* Owner should have rwx */
+ if (check & CPD_GROUP_READ) {
+ new_mode |= 0050; /* Group should have rx */
+ }
+ new_mode &= ~unwanted_bits; /* Clear the bits that we didn't want set...*/
+ if (fchmod(fd, new_mode)) {
+ log_warn(LD_FS, "Could not chmod directory %s: %s", dirname,
+ strerror(errno));
+ close(fd);
+ return -1;
+ } else {
+ close(fd);
+ return 0;
+ }
+ }
+ close(fd);
+#else /* !(!defined(_WIN32)) */
+ /* Win32 case: we can't open() a directory. */
+ (void)effective_user;
+
+ char *f = tor_strdup(dirname);
+ clean_fname_for_stat(f);
+ log_debug(LD_FS, "stat()ing %s", f);
+ r = stat(sandbox_intern_string(f), &st);
+ tor_free(f);
+ if (r) {
+ if (errno != ENOENT) {
+ log_warn(LD_FS, "Directory %s cannot be read: %s", dirname,
+ strerror(errno));
+ return -1;
+ }
+ if (check & CPD_CREATE) {
+ log_info(LD_GENERAL, "Creating directory %s", dirname);
+ r = mkdir(dirname);
+ if (r) {
+ log_warn(LD_FS, "Error creating directory %s: %s", dirname,
+ strerror(errno));
+ return -1;
+ }
+ } else if (!(check & CPD_CHECK)) {
+ log_warn(LD_FS, "Directory %s does not exist.", dirname);
+ return -1;
+ }
+ return 0;
+ }
+ if (!(st.st_mode & S_IFDIR)) {
+ log_warn(LD_FS, "%s is not a directory", dirname);
+ return -1;
+ }
+
+#endif /* !defined(_WIN32) */
+ return 0;
+}
+
+/** Return a new list containing the filenames in the directory <b>dirname</b>.
+ * Return NULL on error or if <b>dirname</b> is not a directory.
+ */
+MOCK_IMPL(smartlist_t *,
+tor_listdir, (const char *dirname))
+{
+ smartlist_t *result;
+#ifdef _WIN32
+ char *pattern=NULL;
+ TCHAR tpattern[MAX_PATH] = {0};
+ char name[MAX_PATH*2+1] = {0};
+ HANDLE handle;
+ WIN32_FIND_DATA findData;
+ tor_asprintf(&pattern, "%s\\*", dirname);
+#ifdef UNICODE
+ mbstowcs(tpattern,pattern,MAX_PATH);
+#else
+ strlcpy(tpattern, pattern, MAX_PATH);
+#endif
+ if (INVALID_HANDLE_VALUE == (handle = FindFirstFile(tpattern, &findData))) {
+ tor_free(pattern);
+ return NULL;
+ }
+ result = smartlist_new();
+ while (1) {
+#ifdef UNICODE
+ wcstombs(name,findData.cFileName,MAX_PATH);
+ name[sizeof(name)-1] = '\0';
+#else
+ strlcpy(name,findData.cFileName,sizeof(name));
+#endif /* defined(UNICODE) */
+ if (strcmp(name, ".") &&
+ strcmp(name, "..")) {
+ smartlist_add_strdup(result, name);
+ }
+ if (!FindNextFile(handle, &findData)) {
+ DWORD err;
+ if ((err = GetLastError()) != ERROR_NO_MORE_FILES) {
+ char *errstr = format_win32_error(err);
+ log_warn(LD_FS, "Error reading directory '%s': %s", dirname, errstr);
+ tor_free(errstr);
+ }
+ break;
+ }
+ }
+ FindClose(handle);
+ tor_free(pattern);
+#else /* !(defined(_WIN32)) */
+ const char *prot_dname = sandbox_intern_string(dirname);
+ DIR *d;
+ struct dirent *de;
+ if (!(d = opendir(prot_dname)))
+ return NULL;
+
+ result = smartlist_new();
+ while ((de = readdir(d))) {
+ if (!strcmp(de->d_name, ".") ||
+ !strcmp(de->d_name, ".."))
+ continue;
+ smartlist_add_strdup(result, de->d_name);
+ }
+ closedir(d);
+#endif /* defined(_WIN32) */
+ return result;
+}
diff --git a/src/lib/fs/dir.h b/src/lib/fs/dir.h
new file mode 100644
index 0000000000..61a04e6d58
--- /dev/null
+++ b/src/lib/fs/dir.h
@@ -0,0 +1,33 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_DIR_H
+#define TOR_DIR_H
+
+/**
+ * \file dir.h
+ *
+ * \brief Header for dir.c
+ **/
+
+#include "lib/cc/compat_compiler.h"
+#include "lib/testsupport/testsupport.h"
+
+/** Possible behaviors for check_private_dir() on encountering a nonexistent
+ * directory; see that function's documentation for details. */
+typedef unsigned int cpd_check_t;
+#define CPD_NONE 0
+#define CPD_CREATE (1u << 0)
+#define CPD_CHECK (1u << 1)
+#define CPD_GROUP_OK (1u << 2)
+#define CPD_GROUP_READ (1u << 3)
+#define CPD_CHECK_MODE_ONLY (1u << 4)
+#define CPD_RELAX_DIRMODE_CHECK (1u << 5)
+MOCK_DECL(int, check_private_dir, (const char *dirname, cpd_check_t check,
+ const char *effective_user));
+
+MOCK_DECL(struct smartlist_t *, tor_listdir, (const char *dirname));
+
+#endif
diff --git a/src/lib/fs/files.c b/src/lib/fs/files.c
new file mode 100644
index 0000000000..4e0a398baa
--- /dev/null
+++ b/src/lib/fs/files.c
@@ -0,0 +1,717 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file files.h
+ *
+ * \brief Wrappers for reading and writing data to files on disk.
+ **/
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include "lib/fs/files.h"
+#include "lib/fs/path.h"
+#include "lib/container/smartlist.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/log/escape.h"
+#include "lib/err/torerr.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/sandbox/sandbox.h"
+#include "lib/string/printf.h"
+#include "lib/string/util_string.h"
+#include "lib/fdio/fdio.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+/** As open(path, flags, mode), but return an fd with the close-on-exec mode
+ * set. */
+int
+tor_open_cloexec(const char *path, int flags, unsigned mode)
+{
+ int fd;
+ const char *p = sandbox_intern_string(path);
+#ifdef O_CLOEXEC
+ fd = open(p, flags|O_CLOEXEC, mode);
+ if (fd >= 0)
+ return fd;
+ /* If we got an error, see if it is EINVAL. EINVAL might indicate that,
+ * even though we were built on a system with O_CLOEXEC support, we
+ * are running on one without. */
+ if (errno != EINVAL)
+ return -1;
+#endif /* defined(O_CLOEXEC) */
+
+ log_debug(LD_FS, "Opening %s with flags %x", p, flags);
+ fd = open(p, flags, mode);
+#ifdef FD_CLOEXEC
+ if (fd >= 0) {
+ if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
+ log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
+ close(fd);
+ return -1;
+ }
+ }
+#endif /* defined(FD_CLOEXEC) */
+ return fd;
+}
+
+/** As fopen(path,mode), but ensures that the O_CLOEXEC bit is set on the
+ * underlying file handle. */
+FILE *
+tor_fopen_cloexec(const char *path, const char *mode)
+{
+ FILE *result = fopen(path, mode);
+#ifdef FD_CLOEXEC
+ if (result != NULL) {
+ if (fcntl(fileno(result), F_SETFD, FD_CLOEXEC) == -1) {
+ log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
+ fclose(result);
+ return NULL;
+ }
+ }
+#endif /* defined(FD_CLOEXEC) */
+ return result;
+}
+
+/** As rename(), but work correctly with the sandbox. */
+int
+tor_rename(const char *path_old, const char *path_new)
+{
+ log_debug(LD_FS, "Renaming %s to %s", path_old, path_new);
+ return rename(sandbox_intern_string(path_old),
+ sandbox_intern_string(path_new));
+}
+
+/**
+ * Rename the file <b>from</b> to the file <b>to</b>. On Unix, this is
+ * the same as rename(2). On windows, this removes <b>to</b> first if
+ * it already exists.
+ * Returns 0 on success. Returns -1 and sets errno on failure.
+ */
+int
+replace_file(const char *from, const char *to)
+{
+#ifndef _WIN32
+ return tor_rename(from, to);
+#else
+ switch (file_status(to))
+ {
+ case FN_NOENT:
+ break;
+ case FN_FILE:
+ case FN_EMPTY:
+ if (unlink(to)) return -1;
+ break;
+ case FN_ERROR:
+ return -1;
+ case FN_DIR:
+ errno = EISDIR;
+ return -1;
+ }
+ return tor_rename(from,to);
+#endif /* !defined(_WIN32) */
+}
+
+/** Change <b>fname</b>'s modification time to now. */
+int
+touch_file(const char *fname)
+{
+ if (utime(fname, NULL)!=0)
+ return -1;
+ return 0;
+}
+
+/** Wrapper for unlink() to make it mockable for the test suite; returns 0
+ * if unlinking the file succeeded, -1 and sets errno if unlinking fails.
+ */
+
+MOCK_IMPL(int,
+tor_unlink,(const char *pathname))
+{
+ return unlink(pathname);
+}
+
+/** Write <b>count</b> bytes from <b>buf</b> to <b>fd</b>. Return the number
+ * of bytes written, or -1 on error. Only use if fd is a blocking fd. */
+ssize_t
+write_all_to_fd(int fd, const char *buf, size_t count)
+{
+ size_t written = 0;
+ ssize_t result;
+ raw_assert(count < SSIZE_MAX);
+
+ while (written != count) {
+ result = write(fd, buf+written, count-written);
+ if (result<0)
+ return -1;
+ written += result;
+ }
+ return (ssize_t)count;
+}
+
+/** Read from <b>fd</b> to <b>buf</b>, until we get <b>count</b> bytes or
+ * reach the end of the file. Return the number of bytes read, or -1 on
+ * error. Only use if fd is a blocking fd. */
+ssize_t
+read_all_from_fd(int fd, char *buf, size_t count)
+{
+ size_t numread = 0;
+ ssize_t result;
+
+ if (count > SIZE_T_CEILING || count > SSIZE_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ while (numread < count) {
+ result = read(fd, buf+numread, count-numread);
+ if (result<0)
+ return -1;
+ else if (result == 0)
+ break;
+ numread += result;
+ }
+ return (ssize_t)numread;
+}
+
+/** Return:
+ * FN_ERROR if filename can't be read, is NULL, or is zero-length,
+ * FN_NOENT if it doesn't exist,
+ * FN_FILE if it is a non-empty regular file, or a FIFO on unix-like systems,
+ * FN_EMPTY for zero-byte regular files,
+ * FN_DIR if it's a directory, and
+ * FN_ERROR for any other file type.
+ * On FN_ERROR and FN_NOENT, sets errno. (errno is not set when FN_ERROR
+ * is returned due to an unhandled file type.) */
+file_status_t
+file_status(const char *fname)
+{
+ struct stat st;
+ char *f;
+ int r;
+ if (!fname || strlen(fname) == 0) {
+ return FN_ERROR;
+ }
+ f = tor_strdup(fname);
+ clean_fname_for_stat(f);
+ log_debug(LD_FS, "stat()ing %s", f);
+ r = stat(sandbox_intern_string(f), &st);
+ tor_free(f);
+ if (r) {
+ if (errno == ENOENT) {
+ return FN_NOENT;
+ }
+ return FN_ERROR;
+ }
+ if (st.st_mode & S_IFDIR) {
+ return FN_DIR;
+ } else if (st.st_mode & S_IFREG) {
+ if (st.st_size > 0) {
+ return FN_FILE;
+ } else if (st.st_size == 0) {
+ return FN_EMPTY;
+ } else {
+ return FN_ERROR;
+ }
+#ifndef _WIN32
+ } else if (st.st_mode & S_IFIFO) {
+ return FN_FILE;
+#endif
+ } else {
+ return FN_ERROR;
+ }
+}
+
+/** 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.
+ *
+ * This function replaces the old file atomically, if possible. This
+ * function, and all other functions in util.c that create files, create them
+ * with mode 0600.
+ */
+MOCK_IMPL(int,
+write_str_to_file,(const char *fname, const char *str, int bin))
+{
+#ifdef _WIN32
+ if (!bin && strchr(str, '\r')) {
+ log_warn(LD_BUG,
+ "We're writing a text string that already contains a CR to %s",
+ escaped(fname));
+ }
+#endif /* defined(_WIN32) */
+ return write_bytes_to_file(fname, str, strlen(str), bin);
+}
+
+/** Represents a file that we're writing to, with support for atomic commit:
+ * we can write into a temporary file, and either remove the file on
+ * failure, or replace the original file on success. */
+struct open_file_t {
+ char *tempname; /**< Name of the temporary file. */
+ char *filename; /**< Name of the original file. */
+ unsigned rename_on_close:1; /**< Are we using the temporary file or not? */
+ unsigned binary:1; /**< Did we open in binary mode? */
+ int fd; /**< fd for the open file. */
+ FILE *stdio_file; /**< stdio wrapper for <b>fd</b>. */
+};
+
+/** Try to start writing to the file in <b>fname</b>, passing the flags
+ * <b>open_flags</b> to the open() syscall, creating the file (if needed) with
+ * access value <b>mode</b>. If the O_APPEND flag is set, we append to the
+ * original file. Otherwise, we open a new temporary file in the same
+ * directory, and either replace the original or remove the temporary file
+ * when we're done.
+ *
+ * Return the fd for the newly opened file, and store working data in
+ * *<b>data_out</b>. The caller should not close the fd manually:
+ * instead, call finish_writing_to_file() or abort_writing_to_file().
+ * Returns -1 on failure.
+ *
+ * NOTE: When not appending, the flags O_CREAT and O_TRUNC are treated
+ * as true and the flag O_EXCL is treated as false.
+ *
+ * NOTE: Ordinarily, O_APPEND means "seek to the end of the file before each
+ * write()". We don't do that.
+ */
+int
+start_writing_to_file(const char *fname, int open_flags, int mode,
+ open_file_t **data_out)
+{
+ open_file_t *new_file = tor_malloc_zero(sizeof(open_file_t));
+ const char *open_name;
+ int append = 0;
+
+ tor_assert(fname);
+ tor_assert(data_out);
+#if (O_BINARY != 0 && O_TEXT != 0)
+ tor_assert((open_flags & (O_BINARY|O_TEXT)) != 0);
+#endif
+ new_file->fd = -1;
+ new_file->filename = tor_strdup(fname);
+ if (open_flags & O_APPEND) {
+ open_name = fname;
+ new_file->rename_on_close = 0;
+ append = 1;
+ open_flags &= ~O_APPEND;
+ } else {
+ tor_asprintf(&new_file->tempname, "%s.tmp", fname);
+ open_name = new_file->tempname;
+ /* We always replace an existing temporary file if there is one. */
+ open_flags |= O_CREAT|O_TRUNC;
+ open_flags &= ~O_EXCL;
+ new_file->rename_on_close = 1;
+ }
+#if O_BINARY != 0
+ if (open_flags & O_BINARY)
+ new_file->binary = 1;
+#endif
+
+ new_file->fd = tor_open_cloexec(open_name, open_flags, mode);
+ if (new_file->fd < 0) {
+ log_warn(LD_FS, "Couldn't open \"%s\" (%s) for writing: %s",
+ open_name, fname, strerror(errno));
+ goto err;
+ }
+ if (append) {
+ if (tor_fd_seekend(new_file->fd) < 0) {
+ log_warn(LD_FS, "Couldn't seek to end of file \"%s\": %s", open_name,
+ strerror(errno));
+ goto err;
+ }
+ }
+
+ *data_out = new_file;
+
+ return new_file->fd;
+
+ err:
+ if (new_file->fd >= 0)
+ close(new_file->fd);
+ *data_out = NULL;
+ tor_free(new_file->filename);
+ tor_free(new_file->tempname);
+ tor_free(new_file);
+ return -1;
+}
+
+/** Given <b>file_data</b> from start_writing_to_file(), return a stdio FILE*
+ * that can be used to write to the same file. The caller should not mix
+ * stdio calls with non-stdio calls. */
+FILE *
+fdopen_file(open_file_t *file_data)
+{
+ tor_assert(file_data);
+ if (file_data->stdio_file)
+ return file_data->stdio_file;
+ tor_assert(file_data->fd >= 0);
+ if (!(file_data->stdio_file = fdopen(file_data->fd,
+ file_data->binary?"ab":"a"))) {
+ log_warn(LD_FS, "Couldn't fdopen \"%s\" [%d]: %s", file_data->filename,
+ file_data->fd, strerror(errno));
+ }
+ return file_data->stdio_file;
+}
+
+/** Combines start_writing_to_file with fdopen_file(): arguments are as
+ * for start_writing_to_file, but */
+FILE *
+start_writing_to_stdio_file(const char *fname, int open_flags, int mode,
+ open_file_t **data_out)
+{
+ FILE *res;
+ if (start_writing_to_file(fname, open_flags, mode, data_out)<0)
+ return NULL;
+ if (!(res = fdopen_file(*data_out))) {
+ abort_writing_to_file(*data_out);
+ *data_out = NULL;
+ }
+ return res;
+}
+
+/** Helper function: close and free the underlying file and memory in
+ * <b>file_data</b>. If we were writing into a temporary file, then delete
+ * that file (if abort_write is true) or replaces the target file with
+ * the temporary file (if abort_write is false). */
+static int
+finish_writing_to_file_impl(open_file_t *file_data, int abort_write)
+{
+ int r = 0;
+
+ tor_assert(file_data && file_data->filename);
+ if (file_data->stdio_file) {
+ if (fclose(file_data->stdio_file)) {
+ log_warn(LD_FS, "Error closing \"%s\": %s", file_data->filename,
+ strerror(errno));
+ abort_write = r = -1;
+ }
+ } else if (file_data->fd >= 0 && close(file_data->fd) < 0) {
+ log_warn(LD_FS, "Error flushing \"%s\": %s", file_data->filename,
+ strerror(errno));
+ abort_write = r = -1;
+ }
+
+ if (file_data->rename_on_close) {
+ tor_assert(file_data->tempname && file_data->filename);
+ if (!abort_write) {
+ tor_assert(strcmp(file_data->filename, file_data->tempname));
+ if (replace_file(file_data->tempname, file_data->filename)) {
+ log_warn(LD_FS, "Error replacing \"%s\": %s", file_data->filename,
+ strerror(errno));
+ abort_write = r = -1;
+ }
+ }
+ if (abort_write) {
+ int res = unlink(file_data->tempname);
+ if (res != 0) {
+ /* We couldn't unlink and we'll leave a mess behind */
+ log_warn(LD_FS, "Failed to unlink %s: %s",
+ file_data->tempname, strerror(errno));
+ r = -1;
+ }
+ }
+ }
+
+ tor_free(file_data->filename);
+ tor_free(file_data->tempname);
+ tor_free(file_data);
+
+ return r;
+}
+
+/** Finish writing to <b>file_data</b>: close the file handle, free memory as
+ * needed, and if using a temporary file, replace the original file with
+ * the temporary file. */
+int
+finish_writing_to_file(open_file_t *file_data)
+{
+ return finish_writing_to_file_impl(file_data, 0);
+}
+
+/** Finish writing to <b>file_data</b>: close the file handle, free memory as
+ * needed, and if using a temporary file, delete it. */
+int
+abort_writing_to_file(open_file_t *file_data)
+{
+ return finish_writing_to_file_impl(file_data, 1);
+}
+
+/** Helper: given a set of flags as passed to open(2), open the file
+ * <b>fname</b> and write all the sized_chunk_t structs in <b>chunks</b> to
+ * the file. Do so as atomically as possible e.g. by opening temp files and
+ * renaming. */
+static int
+write_chunks_to_file_impl(const char *fname, const smartlist_t *chunks,
+ int open_flags)
+{
+ open_file_t *file = NULL;
+ int fd;
+ ssize_t result;
+ fd = start_writing_to_file(fname, open_flags, 0600, &file);
+ if (fd<0)
+ return -1;
+ SMARTLIST_FOREACH(chunks, sized_chunk_t *, chunk,
+ {
+ result = write_all_to_fd(fd, chunk->bytes, chunk->len);
+ if (result < 0) {
+ log_warn(LD_FS, "Error writing to \"%s\": %s", fname,
+ strerror(errno));
+ goto err;
+ }
+ tor_assert((size_t)result == chunk->len);
+ });
+
+ return finish_writing_to_file(file);
+ err:
+ abort_writing_to_file(file);
+ return -1;
+}
+
+/** Given a smartlist of sized_chunk_t, write them to a file
+ * <b>fname</b>, overwriting or creating the file as necessary.
+ * If <b>no_tempfile</b> is 0 then the file will be written
+ * atomically. */
+int
+write_chunks_to_file(const char *fname, const smartlist_t *chunks, int bin,
+ int no_tempfile)
+{
+ int flags = OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT);
+
+ if (no_tempfile) {
+ /* O_APPEND stops write_chunks_to_file from using tempfiles */
+ flags |= O_APPEND;
+ }
+ return write_chunks_to_file_impl(fname, chunks, flags);
+}
+
+/** Write <b>len</b> bytes, starting at <b>str</b>, to <b>fname</b>
+ using the open() flags passed in <b>flags</b>. */
+static int
+write_bytes_to_file_impl(const char *fname, const char *str, size_t len,
+ int flags)
+{
+ int r;
+ sized_chunk_t c = { str, len };
+ smartlist_t *chunks = smartlist_new();
+ smartlist_add(chunks, &c);
+ r = write_chunks_to_file_impl(fname, chunks, flags);
+ smartlist_free(chunks);
+ return r;
+}
+
+/** As write_str_to_file, but does not assume a NUL-terminated
+ * string. Instead, we write <b>len</b> bytes, starting at <b>str</b>. */
+MOCK_IMPL(int,
+write_bytes_to_file,(const char *fname, const char *str, size_t len,
+ int bin))
+{
+ return write_bytes_to_file_impl(fname, str, len,
+ OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT));
+}
+
+/** As write_bytes_to_file, but if the file already exists, append the bytes
+ * to the end of the file instead of overwriting it. */
+int
+append_bytes_to_file(const char *fname, const char *str, size_t len,
+ int bin)
+{
+ return write_bytes_to_file_impl(fname, str, len,
+ OPEN_FLAGS_APPEND|(bin?O_BINARY:O_TEXT));
+}
+
+/** Like write_str_to_file(), but also return -1 if there was a file
+ already residing in <b>fname</b>. */
+int
+write_bytes_to_new_file(const char *fname, const char *str, size_t len,
+ int bin)
+{
+ return write_bytes_to_file_impl(fname, str, len,
+ OPEN_FLAGS_DONT_REPLACE|
+ (bin?O_BINARY:O_TEXT));
+}
+
+/**
+ * Read the contents of the open file <b>fd</b> presuming it is a FIFO
+ * (or similar) file descriptor for which the size of the file isn't
+ * known ahead of time. Return NULL on failure, and a NUL-terminated
+ * string on success. On success, set <b>sz_out</b> to the number of
+ * bytes read.
+ */
+char *
+read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out)
+{
+ ssize_t r;
+ size_t pos = 0;
+ char *string = NULL;
+ size_t string_max = 0;
+
+ if (max_bytes_to_read+1 >= SIZE_T_CEILING) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ do {
+ /* XXXX This "add 1K" approach is a little goofy; if we care about
+ * performance here, we should be doubling. But in practice we shouldn't
+ * be using this function on big files anyway. */
+ string_max = pos + 1024;
+ if (string_max > max_bytes_to_read)
+ string_max = max_bytes_to_read + 1;
+ string = tor_realloc(string, string_max);
+ r = read(fd, string + pos, string_max - pos - 1);
+ if (r < 0) {
+ int save_errno = errno;
+ tor_free(string);
+ errno = save_errno;
+ return NULL;
+ }
+
+ pos += r;
+ } while (r > 0 && pos < max_bytes_to_read);
+
+ tor_assert(pos < string_max);
+ *sz_out = pos;
+ string[pos] = '\0';
+ return string;
+}
+
+/** Read the contents of <b>filename</b> into a newly allocated
+ * string; return the string on success or NULL on failure.
+ *
+ * If <b>stat_out</b> is provided, store the result of stat()ing the
+ * file into <b>stat_out</b>.
+ *
+ * If <b>flags</b> &amp; RFTS_BIN, open the file in binary mode.
+ * If <b>flags</b> &amp; RFTS_IGNORE_MISSING, don't warn if the file
+ * doesn't exist.
+ */
+/*
+ * This function <em>may</em> return an erroneous result if the file
+ * is modified while it is running, but must not crash or overflow.
+ * Right now, the error case occurs when the file length grows between
+ * the call to stat and the call to read_all: the resulting string will
+ * be truncated.
+ */
+MOCK_IMPL(char *,
+read_file_to_str, (const char *filename, int flags, struct stat *stat_out))
+{
+ int fd; /* router file */
+ struct stat statbuf;
+ char *string;
+ ssize_t r;
+ int bin = flags & RFTS_BIN;
+
+ tor_assert(filename);
+
+ fd = tor_open_cloexec(filename,O_RDONLY|(bin?O_BINARY:O_TEXT),0);
+ if (fd<0) {
+ int severity = LOG_WARN;
+ int save_errno = errno;
+ if (errno == ENOENT && (flags & RFTS_IGNORE_MISSING))
+ severity = LOG_INFO;
+ log_fn(severity, LD_FS,"Could not open \"%s\": %s",filename,
+ strerror(errno));
+ errno = save_errno;
+ return NULL;
+ }
+
+ if (fstat(fd, &statbuf)<0) {
+ int save_errno = errno;
+ close(fd);
+ log_warn(LD_FS,"Could not fstat \"%s\".",filename);
+ errno = save_errno;
+ return NULL;
+ }
+
+#ifndef _WIN32
+/** When we detect that we're reading from a FIFO, don't read more than
+ * this many bytes. It's insane overkill for most uses. */
+#define FIFO_READ_MAX (1024*1024)
+ if (S_ISFIFO(statbuf.st_mode)) {
+ size_t sz = 0;
+ string = read_file_to_str_until_eof(fd, FIFO_READ_MAX, &sz);
+ int save_errno = errno;
+ if (string && stat_out) {
+ statbuf.st_size = sz;
+ memcpy(stat_out, &statbuf, sizeof(struct stat));
+ }
+ close(fd);
+ if (!string)
+ errno = save_errno;
+ return string;
+ }
+#endif /* !defined(_WIN32) */
+
+ if ((uint64_t)(statbuf.st_size)+1 >= SIZE_T_CEILING) {
+ close(fd);
+ errno = EINVAL;
+ return NULL;
+ }
+
+ string = tor_malloc((size_t)(statbuf.st_size+1));
+
+ r = read_all_from_fd(fd,string,(size_t)statbuf.st_size);
+ if (r<0) {
+ int save_errno = errno;
+ log_warn(LD_FS,"Error reading from file \"%s\": %s", filename,
+ strerror(errno));
+ tor_free(string);
+ close(fd);
+ errno = save_errno;
+ return NULL;
+ }
+ string[r] = '\0'; /* NUL-terminate the result. */
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+ if (!bin && strchr(string, '\r')) {
+ log_debug(LD_FS, "We didn't convert CRLF to LF as well as we hoped "
+ "when reading %s. Coping.",
+ filename);
+ tor_strstrip(string, "\r");
+ r = strlen(string);
+ }
+ if (!bin) {
+ statbuf.st_size = (size_t) r;
+ } else
+#endif /* defined(_WIN32) || defined(__CYGWIN__) */
+ if (r != statbuf.st_size) {
+ /* Unless we're using text mode on win32, we'd better have an exact
+ * match for size. */
+ int save_errno = errno;
+ log_warn(LD_FS,"Could read only %d of %ld bytes of file \"%s\".",
+ (int)r, (long)statbuf.st_size,filename);
+ tor_free(string);
+ close(fd);
+ errno = save_errno;
+ return NULL;
+ }
+ close(fd);
+ if (stat_out) {
+ memcpy(stat_out, &statbuf, sizeof(struct stat));
+ }
+
+ return string;
+}
diff --git a/src/lib/fs/files.h b/src/lib/fs/files.h
new file mode 100644
index 0000000000..5a12eb8215
--- /dev/null
+++ b/src/lib/fs/files.h
@@ -0,0 +1,106 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file files.h
+ *
+ * \brief Header for files.c
+ **/
+
+#ifndef TOR_FS_H
+#define TOR_FS_H
+
+#include "lib/cc/compat_compiler.h"
+#include "lib/cc/torint.h"
+#include "lib/testsupport/testsupport.h"
+
+#include <stddef.h>
+#include <stdio.h>
+
+#ifdef _WIN32
+/* We need these for struct stat to work */
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+#ifndef O_TEXT
+#define O_TEXT 0
+#endif
+#ifndef O_NOFOLLOW
+#define O_NOFOLLOW 0
+#endif
+
+struct stat;
+
+int tor_open_cloexec(const char *path, int flags, unsigned mode);
+FILE *tor_fopen_cloexec(const char *path, const char *mode);
+int tor_rename(const char *path_old, const char *path_new);
+
+int replace_file(const char *from, const char *to);
+int touch_file(const char *fname);
+
+MOCK_DECL(int,tor_unlink,(const char *pathname));
+
+/** Return values from file_status(); see that function's documentation
+ * for details. */
+typedef enum { FN_ERROR, FN_NOENT, FN_FILE, FN_DIR, FN_EMPTY } file_status_t;
+
+file_status_t file_status(const char *filename);
+
+int64_t tor_get_avail_disk_space(const char *path);
+
+ssize_t write_all_to_fd(int fd, const char *buf, size_t count);
+ssize_t read_all_from_fd(int fd, char *buf, size_t count);
+
+#define OPEN_FLAGS_REPLACE (O_WRONLY|O_CREAT|O_TRUNC)
+#define OPEN_FLAGS_APPEND (O_WRONLY|O_CREAT|O_APPEND)
+#define OPEN_FLAGS_DONT_REPLACE (O_CREAT|O_EXCL|O_APPEND|O_WRONLY)
+typedef struct open_file_t open_file_t;
+int start_writing_to_file(const char *fname, int open_flags, int mode,
+ open_file_t **data_out);
+FILE *start_writing_to_stdio_file(const char *fname, int open_flags, int mode,
+ open_file_t **data_out);
+FILE *fdopen_file(open_file_t *file_data);
+int finish_writing_to_file(open_file_t *file_data);
+int abort_writing_to_file(open_file_t *file_data);
+MOCK_DECL(int, write_str_to_file,(const char *fname, const char *str,
+ int bin));
+MOCK_DECL(int, write_bytes_to_file,(const char *fname, const char *str,
+ size_t len,int bin));
+
+/** An ad-hoc type to hold a string of characters and a count; used by
+ * write_chunks_to_file. */
+typedef struct sized_chunk_t {
+ const char *bytes;
+ size_t len;
+} sized_chunk_t;
+struct smartlist_t;
+int write_chunks_to_file(const char *fname, const struct smartlist_t *chunks,
+ int bin, int no_tempfile);
+int append_bytes_to_file(const char *fname, const char *str, size_t len,
+ int bin);
+int write_bytes_to_new_file(const char *fname, const char *str, size_t len,
+ int bin);
+
+/** 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. */
+#define RFTS_IGNORE_MISSING 2
+
+MOCK_DECL_ATTR(char *, read_file_to_str,(const char *filename, int flags,
+ struct stat *stat_out),
+ ATTR_MALLOC);
+char *read_file_to_str_until_eof(int fd, size_t max_bytes_to_read,
+ size_t *sz_out)
+ ATTR_MALLOC;
+
+#endif
diff --git a/src/lib/fs/freespace.c b/src/lib/fs/freespace.c
new file mode 100644
index 0000000000..2dbba3c5f8
--- /dev/null
+++ b/src/lib/fs/freespace.c
@@ -0,0 +1,62 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file freespace.c
+ *
+ * \brief Find the available disk space on the current volume.
+ **/
+
+#include "lib/fs/files.h"
+#include "lib/cc/torint.h"
+
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include <string.h>
+
+/** Return the amount of free disk space we have permission to use, in
+ * bytes. Return -1 if the amount of free space can't be determined. */
+int64_t
+tor_get_avail_disk_space(const char *path)
+{
+#ifdef HAVE_STATVFS
+ struct statvfs st;
+ int r;
+ memset(&st, 0, sizeof(st));
+
+ r = statvfs(path, &st);
+ if (r < 0)
+ return -1;
+
+ int64_t result = st.f_bavail;
+ if (st.f_frsize) {
+ result *= st.f_frsize;
+ } else if (st.f_bsize) {
+ result *= st.f_bsize;
+ } else {
+ return -1;
+ }
+
+ return result;
+#elif defined(_WIN32)
+ ULARGE_INTEGER freeBytesAvail;
+ BOOL ok;
+
+ ok = GetDiskFreeSpaceEx(path, &freeBytesAvail, NULL, NULL);
+ if (!ok) {
+ return -1;
+ }
+ return (int64_t)freeBytesAvail.QuadPart;
+#else
+ (void)path;
+ errno = ENOSYS;
+ return -1;
+#endif /* defined(HAVE_STATVFS) || ... */
+}
diff --git a/src/lib/fs/include.am b/src/lib/fs/include.am
new file mode 100644
index 0000000000..f33e4d6430
--- /dev/null
+++ b/src/lib/fs/include.am
@@ -0,0 +1,37 @@
+
+noinst_LIBRARIES += src/lib/libtor-fs.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-fs-testing.a
+endif
+
+src_lib_libtor_fs_a_SOURCES = \
+ src/lib/fs/conffile.c \
+ src/lib/fs/dir.c \
+ src/lib/fs/files.c \
+ src/lib/fs/freespace.c \
+ src/lib/fs/lockfile.c \
+ src/lib/fs/mmap.c \
+ src/lib/fs/path.c \
+ src/lib/fs/storagedir.c \
+ src/lib/fs/userdb.c
+
+if WIN32
+src_lib_libtor_fs_a_SOURCES += src/lib/fs/winlib.c
+endif
+
+src_lib_libtor_fs_testing_a_SOURCES = \
+ $(src_lib_libtor_fs_a_SOURCES)
+src_lib_libtor_fs_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_fs_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/fs/conffile.h \
+ src/lib/fs/dir.h \
+ src/lib/fs/files.h \
+ src/lib/fs/lockfile.h \
+ src/lib/fs/mmap.h \
+ src/lib/fs/path.h \
+ src/lib/fs/storagedir.h \
+ src/lib/fs/userdb.h \
+ src/lib/fs/winlib.h
diff --git a/src/lib/fs/lockfile.c b/src/lib/fs/lockfile.c
new file mode 100644
index 0000000000..972fd5658d
--- /dev/null
+++ b/src/lib/fs/lockfile.c
@@ -0,0 +1,145 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file lockfile.c
+ *
+ * \brief Implements lock files to prevent two Tor processes from using the
+ * same data directory at the same time.
+ **/
+
+#include "orconfig.h"
+#include "lib/fs/files.h"
+#include "lib/fs/lockfile.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/malloc/util_malloc.h"
+
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef _WIN32
+#include <windows.h>
+#include <sys/locking.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+
+/** Represents a lockfile on which we hold the lock. */
+struct tor_lockfile_t {
+ /** Name of the file */
+ char *filename;
+ /** File descriptor used to hold the file open */
+ int fd;
+};
+
+/** Try to get a lock on the lockfile <b>filename</b>, creating it as
+ * necessary. If someone else has the lock and <b>blocking</b> is true,
+ * wait until the lock is available. Otherwise return immediately whether
+ * we succeeded or not.
+ *
+ * Set *<b>locked_out</b> to true if somebody else had the lock, and to false
+ * otherwise.
+ *
+ * Return a <b>tor_lockfile_t</b> on success, NULL on failure.
+ *
+ * (Implementation note: because we need to fall back to fcntl on some
+ * platforms, these locks are per-process, not per-thread. If you want
+ * to do in-process locking, use tor_mutex_t like a normal person.
+ * On Windows, when <b>blocking</b> is true, the maximum time that
+ * is actually waited is 10 seconds, after which NULL is returned
+ * and <b>locked_out</b> is set to 1.)
+ */
+tor_lockfile_t *
+tor_lockfile_lock(const char *filename, int blocking, int *locked_out)
+{
+ tor_lockfile_t *result;
+ int fd;
+ *locked_out = 0;
+
+ log_info(LD_FS, "Locking \"%s\"", filename);
+ fd = tor_open_cloexec(filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
+ if (fd < 0) {
+ log_warn(LD_FS,"Couldn't open \"%s\" for locking: %s", filename,
+ strerror(errno));
+ return NULL;
+ }
+
+#ifdef _WIN32
+ _lseek(fd, 0, SEEK_SET);
+ if (_locking(fd, blocking ? _LK_LOCK : _LK_NBLCK, 1) < 0) {
+ if (errno != EACCES && errno != EDEADLOCK)
+ log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno));
+ else
+ *locked_out = 1;
+ close(fd);
+ return NULL;
+ }
+#elif defined(HAVE_FLOCK)
+ if (flock(fd, LOCK_EX|(blocking ? 0 : LOCK_NB)) < 0) {
+ if (errno != EWOULDBLOCK)
+ log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno));
+ else
+ *locked_out = 1;
+ close(fd);
+ return NULL;
+ }
+#else
+ {
+ struct flock lock;
+ memset(&lock, 0, sizeof(lock));
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ if (fcntl(fd, blocking ? F_SETLKW : F_SETLK, &lock) < 0) {
+ if (errno != EACCES && errno != EAGAIN)
+ log_warn(LD_FS, "Couldn't lock \"%s\": %s", filename, strerror(errno));
+ else
+ *locked_out = 1;
+ close(fd);
+ return NULL;
+ }
+ }
+#endif /* defined(_WIN32) || ... */
+
+ result = tor_malloc(sizeof(tor_lockfile_t));
+ result->filename = tor_strdup(filename);
+ result->fd = fd;
+ return result;
+}
+
+/** Release the lock held as <b>lockfile</b>. */
+void
+tor_lockfile_unlock(tor_lockfile_t *lockfile)
+{
+ tor_assert(lockfile);
+
+ log_info(LD_FS, "Unlocking \"%s\"", lockfile->filename);
+#ifdef _WIN32
+ _lseek(lockfile->fd, 0, SEEK_SET);
+ if (_locking(lockfile->fd, _LK_UNLCK, 1) < 0) {
+ log_warn(LD_FS,"Error unlocking \"%s\": %s", lockfile->filename,
+ strerror(errno));
+ }
+#elif defined(HAVE_FLOCK)
+ if (flock(lockfile->fd, LOCK_UN) < 0) {
+ log_warn(LD_FS, "Error unlocking \"%s\": %s", lockfile->filename,
+ strerror(errno));
+ }
+#else
+ /* Closing the lockfile is sufficient. */
+#endif /* defined(_WIN32) || ... */
+
+ close(lockfile->fd);
+ lockfile->fd = -1;
+ tor_free(lockfile->filename);
+ tor_free(lockfile);
+}
diff --git a/src/lib/fs/lockfile.h b/src/lib/fs/lockfile.h
new file mode 100644
index 0000000000..e26349811c
--- /dev/null
+++ b/src/lib/fs/lockfile.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file lockfile.h
+ *
+ * \brief Header for lockfile.c
+ **/
+
+#ifndef TOR_LOCKFILE_H
+#define TOR_LOCKFILE_H
+
+typedef struct tor_lockfile_t tor_lockfile_t;
+tor_lockfile_t *tor_lockfile_lock(const char *filename, int blocking,
+ int *locked_out);
+void tor_lockfile_unlock(tor_lockfile_t *lockfile);
+
+#endif
diff --git a/src/lib/fs/mmap.c b/src/lib/fs/mmap.c
new file mode 100644
index 0000000000..2d758c1b5f
--- /dev/null
+++ b/src/lib/fs/mmap.c
@@ -0,0 +1,240 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file mmap.c
+ *
+ * \brief Cross-platform support for mapping files into our address space.
+ **/
+
+#include "lib/fs/mmap.h"
+#include "lib/fs/files.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/log/win32err.h"
+#include "lib/string/compat_string.h"
+#include "lib/malloc/util_malloc.h"
+
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+
+#if defined(HAVE_MMAP) || defined(RUNNING_DOXYGEN)
+/** Try to create a memory mapping for <b>filename</b> and return it. On
+ * failure, return NULL. Sets errno properly, using ERANGE to mean
+ * "empty file". Must only be called on trusted Tor-owned files, as changing
+ * the underlying file's size causes unspecified behavior. */
+tor_mmap_t *
+tor_mmap_file(const char *filename)
+{
+ int fd; /* router file */
+ char *string;
+ int result;
+ tor_mmap_t *res;
+ size_t size, filesize;
+ struct stat st;
+
+ tor_assert(filename);
+
+ fd = tor_open_cloexec(filename, O_RDONLY, 0);
+ if (fd<0) {
+ int save_errno = errno;
+ int severity = (errno == ENOENT) ? LOG_INFO : LOG_WARN;
+ log_fn(severity, LD_FS,"Could not open \"%s\" for mmap(): %s",filename,
+ strerror(errno));
+ errno = save_errno;
+ return NULL;
+ }
+
+ /* Get the size of the file */
+ result = fstat(fd, &st);
+ if (result != 0) {
+ int save_errno = errno;
+ log_warn(LD_FS,
+ "Couldn't fstat opened descriptor for \"%s\" during mmap: %s",
+ filename, strerror(errno));
+ close(fd);
+ errno = save_errno;
+ return NULL;
+ }
+ size = filesize = (size_t)(st.st_size);
+
+ if (st.st_size > SSIZE_T_CEILING || (off_t)size < st.st_size) {
+ log_warn(LD_FS, "File \"%s\" is too large. Ignoring.",filename);
+ errno = EFBIG;
+ close(fd);
+ return NULL;
+ }
+ if (!size) {
+ /* Zero-length file. If we call mmap on it, it will succeed but
+ * return NULL, and bad things will happen. So just fail. */
+ log_info(LD_FS,"File \"%s\" is empty. Ignoring.",filename);
+ errno = ERANGE;
+ close(fd);
+ return NULL;
+ }
+
+ string = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
+ close(fd);
+ if (string == MAP_FAILED) {
+ int save_errno = errno;
+ log_warn(LD_FS,"Could not mmap file \"%s\": %s", filename,
+ strerror(errno));
+ errno = save_errno;
+ return NULL;
+ }
+
+ res = tor_malloc_zero(sizeof(tor_mmap_t));
+ res->data = string;
+ res->size = filesize;
+ res->mapping_size = size;
+
+ return res;
+}
+/** Release storage held for a memory mapping; returns 0 on success,
+ * or -1 on failure (and logs a warning). */
+int
+tor_munmap_file(tor_mmap_t *handle)
+{
+ int res;
+
+ if (handle == NULL)
+ return 0;
+
+ res = munmap((char*)handle->data, handle->mapping_size);
+ if (res == 0) {
+ /* munmap() succeeded */
+ tor_free(handle);
+ } else {
+ log_warn(LD_FS, "Failed to munmap() in tor_munmap_file(): %s",
+ strerror(errno));
+ res = -1;
+ }
+
+ return res;
+}
+#elif defined(_WIN32)
+tor_mmap_t *
+tor_mmap_file(const char *filename)
+{
+ TCHAR tfilename[MAX_PATH]= {0};
+ tor_mmap_t *res = tor_malloc_zero(sizeof(tor_mmap_t));
+ int empty = 0;
+ HANDLE file_handle = INVALID_HANDLE_VALUE;
+ DWORD size_low, size_high;
+ uint64_t real_size;
+ res->mmap_handle = NULL;
+#ifdef UNICODE
+ mbstowcs(tfilename,filename,MAX_PATH);
+#else
+ strlcpy(tfilename,filename,MAX_PATH);
+#endif
+ file_handle = CreateFile(tfilename,
+ GENERIC_READ, FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ 0);
+
+ if (file_handle == INVALID_HANDLE_VALUE)
+ goto win_err;
+
+ size_low = GetFileSize(file_handle, &size_high);
+
+ if (size_low == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) {
+ log_warn(LD_FS,"Error getting size of \"%s\".",filename);
+ goto win_err;
+ }
+ if (size_low == 0 && size_high == 0) {
+ log_info(LD_FS,"File \"%s\" is empty. Ignoring.",filename);
+ empty = 1;
+ goto err;
+ }
+ real_size = (((uint64_t)size_high)<<32) | size_low;
+ if (real_size > SIZE_MAX) {
+ log_warn(LD_FS,"File \"%s\" is too big to map; not trying.",filename);
+ goto err;
+ }
+ res->size = real_size;
+
+ res->mmap_handle = CreateFileMapping(file_handle,
+ NULL,
+ PAGE_READONLY,
+ size_high,
+ size_low,
+ NULL);
+ if (res->mmap_handle == NULL)
+ goto win_err;
+ res->data = (char*) MapViewOfFile(res->mmap_handle,
+ FILE_MAP_READ,
+ 0, 0, 0);
+ if (!res->data)
+ goto win_err;
+
+ CloseHandle(file_handle);
+ return res;
+ win_err: {
+ DWORD e = GetLastError();
+ int severity = (e == ERROR_FILE_NOT_FOUND || e == ERROR_PATH_NOT_FOUND) ?
+ LOG_INFO : LOG_WARN;
+ char *msg = format_win32_error(e);
+ log_fn(severity, LD_FS, "Couldn't mmap file \"%s\": %s", filename, msg);
+ tor_free(msg);
+ if (e == ERROR_FILE_NOT_FOUND || e == ERROR_PATH_NOT_FOUND)
+ errno = ENOENT;
+ else
+ errno = EINVAL;
+ }
+ err:
+ if (empty)
+ errno = ERANGE;
+ if (file_handle != INVALID_HANDLE_VALUE)
+ CloseHandle(file_handle);
+ tor_munmap_file(res);
+ return NULL;
+}
+
+/* Unmap the file, and return 0 for success or -1 for failure */
+int
+tor_munmap_file(tor_mmap_t *handle)
+{
+ if (handle == NULL)
+ return 0;
+
+ if (handle->data) {
+ /* This is an ugly cast, but without it, "data" in struct tor_mmap_t would
+ have to be redefined as non-const. */
+ BOOL ok = UnmapViewOfFile( (LPVOID) handle->data);
+ if (!ok) {
+ log_warn(LD_FS, "Failed to UnmapViewOfFile() in tor_munmap_file(): %d",
+ (int)GetLastError());
+ }
+ }
+
+ if (handle->mmap_handle != NULL)
+ CloseHandle(handle->mmap_handle);
+ tor_free(handle);
+
+ return 0;
+}
+#else
+#error "cannot implement tor_mmap_file"
+#endif /* defined(HAVE_MMAP) || ... || ... */
diff --git a/src/lib/fs/mmap.h b/src/lib/fs/mmap.h
new file mode 100644
index 0000000000..8d6ca9a0e2
--- /dev/null
+++ b/src/lib/fs/mmap.h
@@ -0,0 +1,41 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file mmap.h
+ *
+ * \brief Header for mmap.c
+ **/
+
+#ifndef TOR_MMAP_H
+#define TOR_MMAP_H
+
+#include "lib/cc/compat_compiler.h"
+#include <stddef.h>
+
+#ifdef _WIN32
+#include <windef.h>
+#endif
+
+/** Represents an mmaped file. Allocated via tor_mmap_file; freed with
+ * tor_munmap_file. */
+typedef struct tor_mmap_t {
+ const char *data; /**< Mapping of the file's contents. */
+ size_t size; /**< Size of the file. */
+
+ /* None of the fields below should be accessed from outside compat.c */
+#ifdef HAVE_MMAP
+ size_t mapping_size; /**< Size of the actual mapping. (This is this file
+ * size, rounded up to the nearest page.) */
+#elif defined _WIN32
+ HANDLE mmap_handle;
+#endif /* defined(HAVE_MMAP) || ... */
+
+} tor_mmap_t;
+
+tor_mmap_t *tor_mmap_file(const char *filename);
+int tor_munmap_file(tor_mmap_t *handle);
+
+#endif
diff --git a/src/lib/fs/path.c b/src/lib/fs/path.c
new file mode 100644
index 0000000000..708ff0505a
--- /dev/null
+++ b/src/lib/fs/path.c
@@ -0,0 +1,295 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file path.c
+ *
+ * \brief Manipulate strings that contain filesystem paths.
+ **/
+
+#include "lib/fs/path.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/string/printf.h"
+#include "lib/string/util_string.h"
+#include "lib/string/compat_ctype.h"
+#include "lib/fs/userdb.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+
+/** Removes enclosing quotes from <b>path</b> and unescapes quotes between the
+ * enclosing quotes. Backslashes are not unescaped. Return the unquoted
+ * <b>path</b> on success or 0 if <b>path</b> is not quoted correctly. */
+char *
+get_unquoted_path(const char *path)
+{
+ size_t len = strlen(path);
+
+ if (len == 0) {
+ return tor_strdup("");
+ }
+
+ int has_start_quote = (path[0] == '\"');
+ int has_end_quote = (len > 0 && path[len-1] == '\"');
+ if (has_start_quote != has_end_quote || (len == 1 && has_start_quote)) {
+ return NULL;
+ }
+
+ char *unquoted_path = tor_malloc(len - has_start_quote - has_end_quote + 1);
+ char *s = unquoted_path;
+ size_t i;
+ for (i = has_start_quote; i < len - has_end_quote; i++) {
+ if (path[i] == '\"' && (i > 0 && path[i-1] == '\\')) {
+ *(s-1) = path[i];
+ } else if (path[i] != '\"') {
+ *s++ = path[i];
+ } else { /* unescaped quote */
+ tor_free(unquoted_path);
+ return NULL;
+ }
+ }
+ *s = '\0';
+ return unquoted_path;
+}
+
+/** Expand any homedir prefix on <b>filename</b>; return a newly allocated
+ * string. */
+char *
+expand_filename(const char *filename)
+{
+ tor_assert(filename);
+#ifdef _WIN32
+ /* Might consider using GetFullPathName() as described here:
+ * http://etutorials.org/Programming/secure+programming/
+ * Chapter+3.+Input+Validation/3.7+Validating+Filenames+and+Paths/
+ */
+ return tor_strdup(filename);
+#else /* !(defined(_WIN32)) */
+ if (*filename == '~') {
+ char *home, *result=NULL;
+ const char *rest;
+
+ if (filename[1] == '/' || filename[1] == '\0') {
+ home = getenv("HOME");
+ if (!home) {
+ log_warn(LD_CONFIG, "Couldn't find $HOME environment variable while "
+ "expanding \"%s\"; defaulting to \"\".", filename);
+ home = tor_strdup("");
+ } else {
+ home = tor_strdup(home);
+ }
+ rest = strlen(filename)>=2?(filename+2):"";
+ } else {
+#ifdef HAVE_PWD_H
+ char *username, *slash;
+ slash = strchr(filename, '/');
+ if (slash)
+ username = tor_strndup(filename+1,slash-filename-1);
+ else
+ username = tor_strdup(filename+1);
+ if (!(home = get_user_homedir(username))) {
+ log_warn(LD_CONFIG,"Couldn't get homedir for \"%s\"",username);
+ tor_free(username);
+ return NULL;
+ }
+ tor_free(username);
+ rest = slash ? (slash+1) : "";
+#else /* !(defined(HAVE_PWD_H)) */
+ log_warn(LD_CONFIG, "Couldn't expand homedir on system without pwd.h");
+ return tor_strdup(filename);
+#endif /* defined(HAVE_PWD_H) */
+ }
+ tor_assert(home);
+ /* Remove trailing slash. */
+ if (strlen(home)>1 && !strcmpend(home,PATH_SEPARATOR)) {
+ home[strlen(home)-1] = '\0';
+ }
+ tor_asprintf(&result,"%s"PATH_SEPARATOR"%s",home,rest);
+ tor_free(home);
+ return result;
+ } else {
+ return tor_strdup(filename);
+ }
+#endif /* defined(_WIN32) */
+}
+
+/** Return true iff <b>filename</b> is a relative path. */
+int
+path_is_relative(const char *filename)
+{
+ if (filename && filename[0] == '/')
+ return 0;
+#ifdef _WIN32
+ else if (filename && filename[0] == '\\')
+ return 0;
+ else if (filename && strlen(filename)>3 && TOR_ISALPHA(filename[0]) &&
+ filename[1] == ':' && filename[2] == '\\')
+ return 0;
+#endif /* defined(_WIN32) */
+ else
+ return 1;
+}
+
+/** Clean up <b>name</b> so that we can use it in a call to "stat". On Unix,
+ * we do nothing. On Windows, we remove a trailing slash, unless the path is
+ * the root of a disk. */
+void
+clean_fname_for_stat(char *name)
+{
+#ifdef _WIN32
+ size_t len = strlen(name);
+ if (!len)
+ return;
+ if (name[len-1]=='\\' || name[len-1]=='/') {
+ if (len == 1 || (len==3 && name[1]==':'))
+ return;
+ name[len-1]='\0';
+ }
+#else /* !(defined(_WIN32)) */
+ (void)name;
+#endif /* defined(_WIN32) */
+}
+
+/** 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.
+ *
+ * Path separators are the forward slash (/) everywhere and additionally
+ * the backslash (\) on Win32.
+ *
+ * Cuts off any number of trailing path separators but otherwise ignores
+ * them for purposes of finding the parent directory.
+ *
+ * Returns 0 if a parent directory was successfully found, -1 otherwise (fname
+ * did not have any path separators or only had them at the end).
+ * */
+int
+get_parent_directory(char *fname)
+{
+ char *cp;
+ int at_end = 1;
+ tor_assert(fname);
+#ifdef _WIN32
+ /* If we start with, say, c:, then don't consider that the start of the path
+ */
+ if (fname[0] && fname[1] == ':') {
+ fname += 2;
+ }
+#endif /* defined(_WIN32) */
+ /* Now we want to remove all path-separators at the end of the string,
+ * and to remove the end of the string starting with the path separator
+ * before the last non-path-separator. In perl, this would be
+ * s#[/]*$##; s#/[^/]*$##;
+ * on a unixy platform.
+ */
+ cp = fname + strlen(fname);
+ at_end = 1;
+ while (--cp >= fname) {
+ int is_sep = (*cp == '/'
+#ifdef _WIN32
+ || *cp == '\\'
+#endif
+ );
+ if (is_sep) {
+ if (cp == fname) {
+ /* This is the first separator in the file name; don't remove it! */
+ cp[1] = '\0';
+ return 0;
+ }
+ *cp = '\0';
+ if (! at_end)
+ return 0;
+ } else {
+ at_end = 0;
+ }
+ }
+ return -1;
+}
+
+#ifndef _WIN32
+/** Return a newly allocated string containing the output of getcwd(). Return
+ * NULL on failure. (We can't just use getcwd() into a PATH_MAX buffer, since
+ * Hurd hasn't got a PATH_MAX.)
+ */
+static char *
+alloc_getcwd(void)
+{
+#ifdef HAVE_GET_CURRENT_DIR_NAME
+ /* Glibc makes this nice and simple for us. */
+ char *cwd = get_current_dir_name();
+ char *result = NULL;
+ if (cwd) {
+ /* We make a copy here, in case tor_malloc() is not malloc(). */
+ result = tor_strdup(cwd);
+ raw_free(cwd); // alias for free to avoid tripping check-spaces.
+ }
+ return result;
+#else /* !(defined(HAVE_GET_CURRENT_DIR_NAME)) */
+ size_t size = 1024;
+ char *buf = NULL;
+ char *ptr = NULL;
+
+ while (ptr == NULL) {
+ buf = tor_realloc(buf, size);
+ ptr = getcwd(buf, size);
+
+ if (ptr == NULL && errno != ERANGE) {
+ tor_free(buf);
+ return NULL;
+ }
+
+ size *= 2;
+ }
+ return buf;
+#endif /* defined(HAVE_GET_CURRENT_DIR_NAME) */
+}
+#endif /* !defined(_WIN32) */
+
+/** Expand possibly relative path <b>fname</b> to an absolute path.
+ * Return a newly allocated string, possibly equal to <b>fname</b>. */
+char *
+make_path_absolute(char *fname)
+{
+#ifdef _WIN32
+ char *absfname_malloced = _fullpath(NULL, fname, 1);
+
+ /* We don't want to assume that tor_free can free a string allocated
+ * with malloc. On failure, return fname (it's better than nothing). */
+ char *absfname = tor_strdup(absfname_malloced ? absfname_malloced : fname);
+ if (absfname_malloced) raw_free(absfname_malloced);
+
+ return absfname;
+#else /* !(defined(_WIN32)) */
+ char *absfname = NULL, *path = NULL;
+
+ tor_assert(fname);
+
+ if (fname[0] == '/') {
+ absfname = tor_strdup(fname);
+ } else {
+ path = alloc_getcwd();
+ if (path) {
+ tor_asprintf(&absfname, "%s/%s", path, fname);
+ tor_free(path);
+ } else {
+ /* LCOV_EXCL_START Can't make getcwd fail. */
+ /* If getcwd failed, the best we can do here is keep using the
+ * relative path. (Perhaps / isn't readable by this UID/GID.) */
+ log_warn(LD_GENERAL, "Unable to find current working directory: %s",
+ strerror(errno));
+ absfname = tor_strdup(fname);
+ /* LCOV_EXCL_STOP */
+ }
+ }
+ return absfname;
+#endif /* defined(_WIN32) */
+}
diff --git a/src/lib/fs/path.h b/src/lib/fs/path.h
new file mode 100644
index 0000000000..384d1f514f
--- /dev/null
+++ b/src/lib/fs/path.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file path.h
+ *
+ * \brief Header for path.c
+ **/
+
+#ifndef TOR_PATH_H
+#define TOR_PATH_H
+
+#include "lib/cc/compat_compiler.h"
+
+#ifdef _WIN32
+#define PATH_SEPARATOR "\\"
+#else
+#define PATH_SEPARATOR "/"
+#endif
+
+char *get_unquoted_path(const char *path);
+char *expand_filename(const char *filename);
+int path_is_relative(const char *filename);
+void clean_fname_for_stat(char *name);
+int get_parent_directory(char *fname);
+char *make_path_absolute(char *fname);
+
+#endif
diff --git a/src/common/storagedir.c b/src/lib/fs/storagedir.c
index e2c7b4bb87..1cda2374d8 100644
--- a/src/common/storagedir.c
+++ b/src/lib/fs/storagedir.c
@@ -1,14 +1,32 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "container.h"
-#include "compat.h"
-#include "confline.h"
-#include "memarea.h"
-#include "sandbox.h"
-#include "storagedir.h"
-#include "torlog.h"
-#include "util.h"
+/**
+ * \file storagedir.c
+ *
+ * \brief An abstraction for a directory full of similar files.
+ *
+ * Storagedirs are used by our consensus cache code, and may someday also get
+ * used for unparseable objects. A large part of the need for this type is to
+ * work around the limitations in our sandbox code, where all filenames need
+ * to be registered in advance.
+ **/
+
+#include "lib/fs/storagedir.h"
+
+#include "lib/container/smartlist.h"
+#include "lib/encoding/confline.h"
+#include "lib/fs/dir.h"
+#include "lib/fs/files.h"
+#include "lib/fs/mmap.h"
+#include "lib/log/escape.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/memarea/memarea.h"
+#include "lib/sandbox/sandbox.h"
+#include "lib/string/printf.h"
+#include "lib/string/util_string.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -19,6 +37,9 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
#define FNAME_MIN_NUM 1000
@@ -583,4 +604,3 @@ storage_dir_get_max_files(storage_dir_t *d)
{
return d->max_files;
}
-
diff --git a/src/common/storagedir.h b/src/lib/fs/storagedir.h
index d99bd7ec52..58594b4634 100644
--- a/src/common/storagedir.h
+++ b/src/lib/fs/storagedir.h
@@ -1,12 +1,23 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file storagedir.h
+ *
+ * \brief Header for storagedir.c
+ **/
+
#ifndef TOR_STORAGEDIR_H
#define TOR_STORAGEDIR_H
+#include "lib/cc/torint.h"
+#include <stddef.h>
+
typedef struct storage_dir_t storage_dir_t;
struct config_line_t;
struct sandbox_cfg_elem;
+struct tor_mmap_t;
+struct smartlist_t;
storage_dir_t * storage_dir_new(const char *dirname, int n_files);
void storage_dir_free_(storage_dir_t *d);
@@ -15,9 +26,9 @@ void storage_dir_free_(storage_dir_t *d);
int storage_dir_register_with_sandbox(storage_dir_t *d,
struct sandbox_cfg_elem **cfg);
-const smartlist_t *storage_dir_list(storage_dir_t *d);
+const struct smartlist_t *storage_dir_list(storage_dir_t *d);
uint64_t storage_dir_get_usage(storage_dir_t *d);
-tor_mmap_t *storage_dir_map(storage_dir_t *d, const char *fname);
+struct tor_mmap_t *storage_dir_map(storage_dir_t *d, const char *fname);
uint8_t *storage_dir_read(storage_dir_t *d, const char *fname, int bin,
size_t *sz_out);
int storage_dir_save_bytes_to_file(storage_dir_t *d,
@@ -34,7 +45,7 @@ int storage_dir_save_labeled_to_file(storage_dir_t *d,
const uint8_t *data,
size_t length,
char **fname_out);
-tor_mmap_t *storage_dir_map_labeled(storage_dir_t *dir,
+struct tor_mmap_t *storage_dir_map_labeled(storage_dir_t *dir,
const char *fname,
struct config_line_t **labels_out,
const uint8_t **data_out,
@@ -51,4 +62,3 @@ int storage_dir_remove_all(storage_dir_t *d);
int storage_dir_get_max_files(storage_dir_t *d);
#endif /* !defined(TOR_STORAGEDIR_H) */
-
diff --git a/src/lib/fs/userdb.c b/src/lib/fs/userdb.c
new file mode 100644
index 0000000000..3d7a9da59d
--- /dev/null
+++ b/src/lib/fs/userdb.c
@@ -0,0 +1,138 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file userdb.c
+ *
+ * \brief Access the POSIX user database.
+ **/
+
+#include "lib/fs/userdb.h"
+
+#ifndef _WIN32
+#include "lib/malloc/util_malloc.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+
+#include <pwd.h>
+#include <stddef.h>
+#include <string.h>
+
+/** Cached struct from the last getpwname() call we did successfully. */
+static struct passwd *passwd_cached = NULL;
+
+/** Helper: copy a struct passwd object.
+ *
+ * We only copy the fields pw_uid, pw_gid, pw_name, pw_dir. Tor doesn't use
+ * any others, and I don't want to run into incompatibilities.
+ */
+static struct passwd *
+tor_passwd_dup(const struct passwd *pw)
+{
+ struct passwd *new_pw = tor_malloc_zero(sizeof(struct passwd));
+ if (pw->pw_name)
+ new_pw->pw_name = tor_strdup(pw->pw_name);
+ if (pw->pw_dir)
+ new_pw->pw_dir = tor_strdup(pw->pw_dir);
+ new_pw->pw_uid = pw->pw_uid;
+ new_pw->pw_gid = pw->pw_gid;
+
+ return new_pw;
+}
+
+#define tor_passwd_free(pw) \
+ FREE_AND_NULL(struct passwd, tor_passwd_free_, (pw))
+
+/** Helper: free one of our cached 'struct passwd' values. */
+static void
+tor_passwd_free_(struct passwd *pw)
+{
+ if (!pw)
+ return;
+
+ tor_free(pw->pw_name);
+ tor_free(pw->pw_dir);
+ tor_free(pw);
+}
+
+/** Wrapper around getpwnam() that caches result. Used so that we don't need
+ * to give the sandbox access to /etc/passwd.
+ *
+ * The following fields alone will definitely be copied in the output: pw_uid,
+ * pw_gid, pw_name, pw_dir. Other fields are not present in cached values.
+ *
+ * When called with a NULL argument, this function clears storage associated
+ * with static variables it uses.
+ **/
+const struct passwd *
+tor_getpwnam(const char *username)
+{
+ struct passwd *pw;
+
+ if (username == NULL) {
+ tor_passwd_free(passwd_cached);
+ passwd_cached = NULL;
+ return NULL;
+ }
+
+ if ((pw = getpwnam(username))) {
+ tor_passwd_free(passwd_cached);
+ passwd_cached = tor_passwd_dup(pw);
+ log_info(LD_GENERAL, "Caching new entry %s for %s",
+ passwd_cached->pw_name, username);
+ return pw;
+ }
+
+ /* Lookup failed */
+ if (! passwd_cached || ! passwd_cached->pw_name)
+ return NULL;
+
+ if (! strcmp(username, passwd_cached->pw_name))
+ return passwd_cached; // LCOV_EXCL_LINE - would need to make getpwnam flaky
+
+ return NULL;
+}
+
+/** Wrapper around getpwnam() that can use cached result from
+ * tor_getpwnam(). Used so that we don't need to give the sandbox access to
+ * /etc/passwd.
+ *
+ * The following fields alone will definitely be copied in the output: pw_uid,
+ * pw_gid, pw_name, pw_dir. Other fields are not present in cached values.
+ */
+const struct passwd *
+tor_getpwuid(uid_t uid)
+{
+ struct passwd *pw;
+
+ if ((pw = getpwuid(uid))) {
+ return pw;
+ }
+
+ /* Lookup failed */
+ if (! passwd_cached)
+ return NULL;
+
+ if (uid == passwd_cached->pw_uid)
+ return passwd_cached; // LCOV_EXCL_LINE - would need to make getpwnam flaky
+
+ return NULL;
+}
+
+/** Allocate and return a string containing the home directory for the
+ * user <b>username</b>. Only works on posix-like systems. */
+char *
+get_user_homedir(const char *username)
+{
+ const struct passwd *pw;
+ tor_assert(username);
+
+ if (!(pw = tor_getpwnam(username))) {
+ log_err(LD_CONFIG,"User \"%s\" not found.", username);
+ return NULL;
+ }
+ return tor_strdup(pw->pw_dir);
+}
+#endif /* !defined(_WIN32) */
diff --git a/src/lib/fs/userdb.h b/src/lib/fs/userdb.h
new file mode 100644
index 0000000000..3b3ab6ed2b
--- /dev/null
+++ b/src/lib/fs/userdb.h
@@ -0,0 +1,26 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file userdb.h
+ *
+ * \brief Header for userdb.c
+ **/
+
+#ifndef TOR_USERDB_H
+#define TOR_USERDB_H
+
+#include "orconfig.h"
+
+#ifndef _WIN32
+#include <sys/types.h>
+
+struct passwd;
+const struct passwd *tor_getpwnam(const char *username);
+const struct passwd *tor_getpwuid(uid_t uid);
+char *get_user_homedir(const char *username);
+#endif
+
+#endif
diff --git a/src/lib/fs/winlib.c b/src/lib/fs/winlib.c
new file mode 100644
index 0000000000..532807c03f
--- /dev/null
+++ b/src/lib/fs/winlib.c
@@ -0,0 +1,30 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file winlib.c
+ *
+ * \brief Find and load windows system libraries.
+ *
+ * We use this function to dynamically load code at runtime that might not be
+ * available on all versions of Windows that we support.
+ **/
+
+#ifdef _WIN32
+#include "lib/fs/winlib.h"
+
+HANDLE
+load_windows_system_library(const TCHAR *library_name)
+{
+ TCHAR path[MAX_PATH];
+ unsigned n;
+ n = GetSystemDirectory(path, MAX_PATH);
+ if (n == 0 || n + _tcslen(library_name) + 2 >= MAX_PATH)
+ return 0;
+ _tcscat(path, TEXT("\\"));
+ _tcscat(path, library_name);
+ return LoadLibrary(path);
+}
+#endif /* defined(_WIN32) */
diff --git a/src/lib/fs/winlib.h b/src/lib/fs/winlib.h
new file mode 100644
index 0000000000..5b10b9b78d
--- /dev/null
+++ b/src/lib/fs/winlib.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file winlib.h
+ *
+ * \brief Header for winlib.c
+ **/
+
+#ifndef TOR_WINLIB_H
+#define TOR_WINLIB_H
+
+#ifdef _WIN32
+#include <windows.h>
+#include <tchar.h>
+
+HANDLE load_windows_system_library(const TCHAR *library_name);
+#endif
+
+#endif
diff --git a/src/lib/include.libdonna.am b/src/lib/include.libdonna.am
new file mode 100644
index 0000000000..5b92dc58a0
--- /dev/null
+++ b/src/lib/include.libdonna.am
@@ -0,0 +1,24 @@
+src_lib_libcurve25519_donna_a_CFLAGS=
+
+if BUILD_CURVE25519_DONNA
+src_lib_libcurve25519_donna_a_SOURCES=\
+ src/ext/curve25519_donna/curve25519-donna.c
+# See bug 13538 -- this code is known to have signed overflow issues.
+src_lib_libcurve25519_donna_a_CFLAGS+=\
+ @F_OMIT_FRAME_POINTER@ @CFLAGS_CONSTTIME@
+noinst_LIBRARIES+=src/lib/libcurve25519_donna.a
+LIBDONNA=src/lib/libcurve25519_donna.a
+else
+if BUILD_CURVE25519_DONNA_C64
+src_lib_libcurve25519_donna_a_CFLAGS+=@CFLAGS_CONSTTIME@
+src_lib_libcurve25519_donna_a_SOURCES=\
+ src/ext/curve25519_donna/curve25519-donna-c64.c
+noinst_LIBRARIES+=src/lib/libcurve25519_donna.a
+LIBDONNA=src/lib/libcurve25519_donna.a
+else
+LIBDONNA=
+endif
+endif
+
+LIBDONNA += $(LIBED25519_REF10)
+LIBDONNA += $(LIBED25519_DONNA)
diff --git a/src/lib/intmath/.may_include b/src/lib/intmath/.may_include
new file mode 100644
index 0000000000..d96c112220
--- /dev/null
+++ b/src/lib/intmath/.may_include
@@ -0,0 +1,4 @@
+orconfig.h
+lib/cc/*.h
+lib/err/*.h
+lib/intmath/*.h
diff --git a/src/lib/intmath/addsub.c b/src/lib/intmath/addsub.c
new file mode 100644
index 0000000000..fcfdca6822
--- /dev/null
+++ b/src/lib/intmath/addsub.c
@@ -0,0 +1,28 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file addsub.c
+ *
+ * \brief Helpers for addition and subtraction.
+ *
+ * Currently limited to non-wrapping (saturating) addition.
+ **/
+
+#include "lib/intmath/addsub.h"
+#include "lib/cc/compat_compiler.h"
+
+/* Helper: safely add two uint32_t's, capping at UINT32_MAX rather
+ * than overflow */
+uint32_t
+tor_add_u32_nowrap(uint32_t a, uint32_t b)
+{
+ /* a+b > UINT32_MAX check, without overflow */
+ if (PREDICT_UNLIKELY(a > UINT32_MAX - b)) {
+ return UINT32_MAX;
+ } else {
+ return a+b;
+ }
+}
diff --git a/src/lib/intmath/addsub.h b/src/lib/intmath/addsub.h
new file mode 100644
index 0000000000..5bbc32e4a9
--- /dev/null
+++ b/src/lib/intmath/addsub.h
@@ -0,0 +1,19 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file addsub.h
+ *
+ * \brief Header for addsub.c
+ **/
+
+#ifndef TOR_INTMATH_ADDSUB_H
+#define TOR_INTMATH_ADDSUB_H
+
+#include "lib/cc/torint.h"
+
+uint32_t tor_add_u32_nowrap(uint32_t a, uint32_t b);
+
+#endif /* !defined(TOR_INTMATH_MULDIV_H) */
diff --git a/src/lib/intmath/bits.c b/src/lib/intmath/bits.c
new file mode 100644
index 0000000000..7da524449d
--- /dev/null
+++ b/src/lib/intmath/bits.c
@@ -0,0 +1,94 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file bits.c
+ *
+ * \brief Count the bits in an integer, manipulate powers of 2, etc.
+ **/
+
+#include "lib/intmath/bits.h"
+
+/** Returns floor(log2(u64)). If u64 is 0, (incorrectly) returns 0. */
+int
+tor_log2(uint64_t u64)
+{
+ int r = 0;
+ if (u64 >= (UINT64_C(1)<<32)) {
+ u64 >>= 32;
+ r = 32;
+ }
+ if (u64 >= (UINT64_C(1)<<16)) {
+ u64 >>= 16;
+ r += 16;
+ }
+ if (u64 >= (UINT64_C(1)<<8)) {
+ u64 >>= 8;
+ r += 8;
+ }
+ if (u64 >= (UINT64_C(1)<<4)) {
+ u64 >>= 4;
+ r += 4;
+ }
+ if (u64 >= (UINT64_C(1)<<2)) {
+ u64 >>= 2;
+ r += 2;
+ }
+ if (u64 >= (UINT64_C(1)<<1)) {
+ // u64 >>= 1; // not using this any more.
+ r += 1;
+ }
+ return r;
+}
+
+/** Return the power of 2 in range [1,UINT64_MAX] closest to <b>u64</b>. If
+ * there are two powers of 2 equally close, round down. */
+uint64_t
+round_to_power_of_2(uint64_t u64)
+{
+ int lg2;
+ uint64_t low;
+ uint64_t high;
+ if (u64 == 0)
+ return 1;
+
+ lg2 = tor_log2(u64);
+ low = UINT64_C(1) << lg2;
+
+ if (lg2 == 63)
+ return low;
+
+ high = UINT64_C(1) << (lg2+1);
+ if (high - u64 < u64 - low)
+ return high;
+ else
+ return low;
+}
+
+/** Return the number of bits set in <b>v</b>. */
+int
+n_bits_set_u8(uint8_t v)
+{
+ static const int nybble_table[] = {
+ 0, /* 0000 */
+ 1, /* 0001 */
+ 1, /* 0010 */
+ 2, /* 0011 */
+ 1, /* 0100 */
+ 2, /* 0101 */
+ 2, /* 0110 */
+ 3, /* 0111 */
+ 1, /* 1000 */
+ 2, /* 1001 */
+ 2, /* 1010 */
+ 3, /* 1011 */
+ 2, /* 1100 */
+ 3, /* 1101 */
+ 3, /* 1110 */
+ 4, /* 1111 */
+ };
+
+ return nybble_table[v & 15] + nybble_table[v>>4];
+}
diff --git a/src/lib/intmath/bits.h b/src/lib/intmath/bits.h
new file mode 100644
index 0000000000..80eebe9358
--- /dev/null
+++ b/src/lib/intmath/bits.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file bits.h
+ *
+ * \brief Header for bits.c
+ **/
+
+#ifndef TOR_INTMATH_BITS_H
+#define TOR_INTMATH_BITS_H
+
+#include "lib/cc/torint.h"
+#include "lib/cc/compat_compiler.h"
+
+int tor_log2(uint64_t u64) ATTR_CONST;
+uint64_t round_to_power_of_2(uint64_t u64);
+int n_bits_set_u8(uint8_t v);
+
+#endif /* !defined(TOR_INTMATH_BITS_H) */
diff --git a/src/lib/intmath/cmp.h b/src/lib/intmath/cmp.h
new file mode 100644
index 0000000000..16952bee3e
--- /dev/null
+++ b/src/lib/intmath/cmp.h
@@ -0,0 +1,39 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file cmp.h
+ *
+ * \brief Macro definitions for MIN, MAX, and CLAMP.
+ **/
+
+#ifndef TOR_INTMATH_CMP_H
+#define TOR_INTMATH_CMP_H
+
+/** Macros for MIN/MAX. Never use these when the arguments could have
+ * side-effects.
+ * {With GCC extensions we could probably define a safer MIN/MAX. But
+ * depending on that safety would be dangerous, since not every platform
+ * has it.}
+ **/
+#ifndef MAX
+#define MAX(a,b) ( ((a)<(b)) ? (b) : (a) )
+#endif
+#ifndef MIN
+#define MIN(a,b) ( ((a)>(b)) ? (b) : (a) )
+#endif
+
+/* Return <b>v</b> if it's between <b>min</b> and <b>max</b>. Otherwise
+ * return <b>min</b> if <b>v</b> is smaller than <b>min</b>, or <b>max</b> if
+ * <b>b</b> is larger than <b>max</b>.
+ *
+ * Requires that <b>min</b> is no more than <b>max</b>. May evaluate any of
+ * its arguments more than once! */
+#define CLAMP(min,v,max) \
+ ( ((v) < (min)) ? (min) : \
+ ((v) > (max)) ? (max) : \
+ (v) )
+
+#endif /* !defined(TOR_INTMATH_CMP_H) */
diff --git a/src/lib/intmath/include.am b/src/lib/intmath/include.am
new file mode 100644
index 0000000000..45ee3bd53b
--- /dev/null
+++ b/src/lib/intmath/include.am
@@ -0,0 +1,25 @@
+
+noinst_LIBRARIES += src/lib/libtor-intmath.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-intmath-testing.a
+endif
+
+src_lib_libtor_intmath_a_SOURCES = \
+ src/lib/intmath/addsub.c \
+ src/lib/intmath/bits.c \
+ src/lib/intmath/muldiv.c \
+ src/lib/intmath/weakrng.c
+
+src_lib_libtor_intmath_testing_a_SOURCES = \
+ $(src_lib_libtor_intmath_a_SOURCES)
+src_lib_libtor_intmath_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_intmath_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/intmath/addsub.h \
+ src/lib/intmath/cmp.h \
+ src/lib/intmath/bits.h \
+ src/lib/intmath/logic.h \
+ src/lib/intmath/muldiv.h \
+ src/lib/intmath/weakrng.h
diff --git a/src/lib/intmath/logic.h b/src/lib/intmath/logic.h
new file mode 100644
index 0000000000..b3eabc652e
--- /dev/null
+++ b/src/lib/intmath/logic.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file logic.h
+ *
+ * \brief Macros for comparing the boolean value of integers.
+ **/
+
+#ifndef HAVE_TOR_LOGIC_H
+#define HAVE_TOR_LOGIC_H
+
+/** Macro: true if two values have the same boolean value. */
+#define bool_eq(a,b) (!(a)==!(b))
+/** Macro: true if two values have different boolean values. */
+#define bool_neq(a,b) (!(a)!=!(b))
+
+#endif
diff --git a/src/lib/intmath/muldiv.c b/src/lib/intmath/muldiv.c
new file mode 100644
index 0000000000..c5fc689e2d
--- /dev/null
+++ b/src/lib/intmath/muldiv.c
@@ -0,0 +1,81 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file muldiv.c
+ *
+ * \brief Integer math related to multiplication, division, and rounding.
+ **/
+
+#include "lib/intmath/muldiv.h"
+#include "lib/err/torerr.h"
+
+#include <stdlib.h>
+
+/** Return the lowest x such that x is at least <b>number</b>, and x modulo
+ * <b>divisor</b> == 0. If no such x can be expressed as an unsigned, return
+ * UINT_MAX. Asserts if divisor is zero. */
+unsigned
+round_to_next_multiple_of(unsigned number, unsigned divisor)
+{
+ raw_assert(divisor > 0);
+ if (UINT_MAX - divisor + 1 < number)
+ return UINT_MAX;
+ number += divisor - 1;
+ number -= number % divisor;
+ return number;
+}
+
+/** Return the lowest x such that x is at least <b>number</b>, and x modulo
+ * <b>divisor</b> == 0. If no such x can be expressed as a uint32_t, return
+ * UINT32_MAX. Asserts if divisor is zero. */
+uint32_t
+round_uint32_to_next_multiple_of(uint32_t number, uint32_t divisor)
+{
+ raw_assert(divisor > 0);
+ if (UINT32_MAX - divisor + 1 < number)
+ return UINT32_MAX;
+
+ number += divisor - 1;
+ number -= number % divisor;
+ return number;
+}
+
+/** Return the lowest x such that x is at least <b>number</b>, and x modulo
+ * <b>divisor</b> == 0. If no such x can be expressed as a uint64_t, return
+ * UINT64_MAX. Asserts if divisor is zero. */
+uint64_t
+round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor)
+{
+ raw_assert(divisor > 0);
+ if (UINT64_MAX - divisor + 1 < number)
+ return UINT64_MAX;
+ number += divisor - 1;
+ number -= number % divisor;
+ return number;
+}
+
+/* Helper: return greatest common divisor of a,b */
+static uint64_t
+gcd64(uint64_t a, uint64_t b)
+{
+ while (b) {
+ uint64_t t = b;
+ b = a % b;
+ a = t;
+ }
+ return a;
+}
+
+/* Given a fraction *<b>numer</b> / *<b>denom</b>, simplify it.
+ * Requires that the denominator is greater than 0. */
+void
+simplify_fraction64(uint64_t *numer, uint64_t *denom)
+{
+ raw_assert(denom);
+ uint64_t gcd = gcd64(*numer, *denom);
+ *numer /= gcd;
+ *denom /= gcd;
+}
diff --git a/src/lib/intmath/muldiv.h b/src/lib/intmath/muldiv.h
new file mode 100644
index 0000000000..45b896922f
--- /dev/null
+++ b/src/lib/intmath/muldiv.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file muldiv.h
+ *
+ * \brief Header for muldiv.c
+ **/
+
+#ifndef TOR_INTMATH_MULDIV_H
+#define TOR_INTMATH_MULDIV_H
+
+#include "lib/cc/torint.h"
+
+unsigned round_to_next_multiple_of(unsigned number, unsigned divisor);
+uint32_t round_uint32_to_next_multiple_of(uint32_t number, uint32_t divisor);
+uint64_t round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor);
+
+void simplify_fraction64(uint64_t *numer, uint64_t *denom);
+
+/* Compute the CEIL of <b>a</b> divided by <b>b</b>, for nonnegative <b>a</b>
+ * and positive <b>b</b>. Works on integer types only. Not defined if a+(b-1)
+ * can overflow. */
+#define CEIL_DIV(a,b) (((a)+((b)-1))/(b))
+
+#endif /* !defined(TOR_INTMATH_MULDIV_H) */
diff --git a/src/lib/intmath/weakrng.c b/src/lib/intmath/weakrng.c
new file mode 100644
index 0000000000..36cf5fb0aa
--- /dev/null
+++ b/src/lib/intmath/weakrng.c
@@ -0,0 +1,60 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file weakrng.c
+ *
+ * \brief A weak but fast PRNG based on a linear congruential generator.
+ *
+ * We don't want to use the platform random(), since some of them are even
+ * worse than this.
+ **/
+
+#include "lib/intmath/weakrng.h"
+#include "lib/err/torerr.h"
+
+#include <stdlib.h>
+
+/** Initialize the insecure RNG <b>rng</b> from a seed value <b>seed</b>. */
+void
+tor_init_weak_random(tor_weak_rng_t *rng, unsigned seed)
+{
+ rng->state = (uint32_t)(seed & 0x7fffffff);
+}
+
+/** Return a randomly chosen value in the range 0..TOR_WEAK_RANDOM_MAX based
+ * on the RNG state of <b>rng</b>. This entropy will not be cryptographically
+ * strong; do not rely on it for anything an adversary should not be able to
+ * predict. */
+int32_t
+tor_weak_random(tor_weak_rng_t *rng)
+{
+ /* Here's a linear congruential generator. OpenBSD and glibc use these
+ * parameters; they aren't too bad, and should have maximal period over the
+ * range 0..INT32_MAX. We don't want to use the platform rand() or random(),
+ * since some platforms have bad weak RNGs that only return values in the
+ * range 0..INT16_MAX, which just isn't enough. */
+ rng->state = (rng->state * 1103515245 + 12345) & 0x7fffffff;
+ return (int32_t) rng->state;
+}
+
+/** Return a random number in the range [0 , <b>top</b>). {That is, the range
+ * of integers i such that 0 <= i < top.} Chooses uniformly. Requires that
+ * top is greater than 0. This randomness is not cryptographically strong; do
+ * not rely on it for anything an adversary should not be able to predict. */
+int32_t
+tor_weak_random_range(tor_weak_rng_t *rng, int32_t top)
+{
+ /* We don't want to just do tor_weak_random() % top, since random() is often
+ * implemented with an LCG whose modulus is a power of 2, and those are
+ * cyclic in their low-order bits. */
+ int divisor, result;
+ raw_assert(top > 0);
+ divisor = TOR_WEAK_RANDOM_MAX / top;
+ do {
+ result = (int32_t)(tor_weak_random(rng) / divisor);
+ } while (result >= top);
+ return result;
+}
diff --git a/src/lib/intmath/weakrng.h b/src/lib/intmath/weakrng.h
new file mode 100644
index 0000000000..679bf2449c
--- /dev/null
+++ b/src/lib/intmath/weakrng.h
@@ -0,0 +1,31 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file weakrng.h
+ *
+ * \brief Header for weakrng.c
+ **/
+
+#ifndef TOR_WEAKRNG_H
+#define TOR_WEAKRNG_H
+
+#include "lib/cc/torint.h"
+
+/* ===== Insecure rng */
+typedef struct tor_weak_rng_t {
+ uint32_t state;
+} tor_weak_rng_t;
+
+#define TOR_WEAK_RNG_INIT {383745623}
+#define TOR_WEAK_RANDOM_MAX (INT_MAX)
+void tor_init_weak_random(tor_weak_rng_t *weak_rng, unsigned seed);
+int32_t tor_weak_random(tor_weak_rng_t *weak_rng);
+int32_t tor_weak_random_range(tor_weak_rng_t *rng, int32_t top);
+/** Randomly return true according to <b>rng</b> with probability 1 in
+ * <b>n</b> */
+#define tor_weak_random_one_in_n(rng, n) (0==tor_weak_random_range((rng),(n)))
+
+#endif
diff --git a/src/lib/lock/.may_include b/src/lib/lock/.may_include
new file mode 100644
index 0000000000..9522e3af49
--- /dev/null
+++ b/src/lib/lock/.may_include
@@ -0,0 +1,5 @@
+orconfig.h
+lib/cc/*.h
+lib/err/*.h
+lib/lock/*.h
+lib/malloc/*.h
diff --git a/src/lib/lock/compat_mutex.c b/src/lib/lock/compat_mutex.c
new file mode 100644
index 0000000000..bfab6dd29b
--- /dev/null
+++ b/src/lib/lock/compat_mutex.c
@@ -0,0 +1,40 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file compat_mutex.c
+ *
+ * \brief Portable wrapper for platform mutex implementations.
+ **/
+
+#include "lib/lock/compat_mutex.h"
+#include "lib/malloc/util_malloc.h"
+
+/** Return a newly allocated, ready-for-use mutex. */
+tor_mutex_t *
+tor_mutex_new(void)
+{
+ tor_mutex_t *m = tor_malloc_zero(sizeof(tor_mutex_t));
+ tor_mutex_init(m);
+ return m;
+}
+/** Return a newly allocated, ready-for-use mutex. This one might be
+ * non-recursive, if that's faster. */
+tor_mutex_t *
+tor_mutex_new_nonrecursive(void)
+{
+ tor_mutex_t *m = tor_malloc_zero(sizeof(tor_mutex_t));
+ tor_mutex_init_nonrecursive(m);
+ return m;
+}
+/** Release all storage and system resources held by <b>m</b>. */
+void
+tor_mutex_free_(tor_mutex_t *m)
+{
+ if (!m)
+ return;
+ tor_mutex_uninit(m);
+ tor_free(m);
+}
diff --git a/src/lib/lock/compat_mutex.h b/src/lib/lock/compat_mutex.h
new file mode 100644
index 0000000000..f467aa5dba
--- /dev/null
+++ b/src/lib/lock/compat_mutex.h
@@ -0,0 +1,66 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file compat_mutex.h
+ *
+ * \brief Header for compat_mutex.c
+ **/
+
+#ifndef TOR_COMPAT_MUTEX_H
+#define TOR_COMPAT_MUTEX_H
+
+#include "orconfig.h"
+#include "lib/cc/torint.h"
+#include "lib/malloc/util_malloc.h"
+
+#if defined(HAVE_PTHREAD_H) && !defined(_WIN32)
+#include <pthread.h>
+#endif
+
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
+#if defined(_WIN32)
+#define USE_WIN32_THREADS
+#elif defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_CREATE)
+#define USE_PTHREADS
+#else
+#error "No threading system was found"
+#endif /* defined(_WIN32) || ... */
+
+/* Because we use threads instead of processes on most platforms (Windows,
+ * Linux, etc), we need locking for them. On platforms with poor thread
+ * support or broken gethostbyname_r, these functions are no-ops. */
+
+/** A generic lock structure for multithreaded builds. */
+typedef struct tor_mutex_t {
+#if defined(USE_WIN32_THREADS)
+ /** Windows-only: on windows, we implement locks with CRITICAL_SECTIONS. */
+ CRITICAL_SECTION mutex;
+#elif defined(USE_PTHREADS)
+ /** Pthreads-only: with pthreads, we implement locks with
+ * pthread_mutex_t. */
+ pthread_mutex_t mutex;
+#else
+ /** No-threads only: Dummy variable so that tor_mutex_t takes up space. */
+ int _unused;
+#endif /* defined(USE_WIN32_MUTEX) || ... */
+} tor_mutex_t;
+
+tor_mutex_t *tor_mutex_new(void);
+tor_mutex_t *tor_mutex_new_nonrecursive(void);
+void tor_mutex_init(tor_mutex_t *m);
+void tor_mutex_init_nonrecursive(tor_mutex_t *m);
+void tor_mutex_acquire(tor_mutex_t *m);
+void tor_mutex_release(tor_mutex_t *m);
+void tor_mutex_free_(tor_mutex_t *m);
+#define tor_mutex_free(m) FREE_AND_NULL(tor_mutex_t, tor_mutex_free_, (m))
+void tor_mutex_uninit(tor_mutex_t *m);
+
+void tor_locking_init(void);
+
+#endif /* !defined(TOR_COMPAT_MUTEX_H) */
diff --git a/src/lib/lock/compat_mutex_pthreads.c b/src/lib/lock/compat_mutex_pthreads.c
new file mode 100644
index 0000000000..983abf5ae5
--- /dev/null
+++ b/src/lib/lock/compat_mutex_pthreads.c
@@ -0,0 +1,103 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file compat_mutex_pthreads.c
+ *
+ * \brief Implement the tor_mutex API using pthread_mutex_t.
+ **/
+
+#include "lib/lock/compat_mutex.h"
+#include "lib/cc/compat_compiler.h"
+#include "lib/err/torerr.h"
+
+/** A mutex attribute that we're going to use to tell pthreads that we want
+ * "recursive" mutexes (i.e., once we can re-lock if we're already holding
+ * them.) */
+static pthread_mutexattr_t attr_recursive;
+static int attr_initialized = 0;
+
+void
+tor_locking_init(void)
+{
+ if (!attr_initialized) {
+ pthread_mutexattr_init(&attr_recursive);
+ pthread_mutexattr_settype(&attr_recursive, PTHREAD_MUTEX_RECURSIVE);
+ attr_initialized = 1;
+ }
+}
+
+/** Initialize <b>mutex</b> so it can be locked. Every mutex must be set
+ * up with tor_mutex_init() or tor_mutex_new(); not both. */
+void
+tor_mutex_init(tor_mutex_t *mutex)
+{
+ if (PREDICT_UNLIKELY(!attr_initialized))
+ tor_locking_init(); // LCOV_EXCL_LINE
+ const int err = pthread_mutex_init(&mutex->mutex, &attr_recursive);
+ if (PREDICT_UNLIKELY(err)) {
+ // LCOV_EXCL_START
+ raw_assert_unreached_msg("Error creating a mutex.");
+ // LCOV_EXCL_STOP
+ }
+}
+
+/** As tor_mutex_init, but initialize a mutex suitable that may be
+ * non-recursive, if the OS supports that. */
+void
+tor_mutex_init_nonrecursive(tor_mutex_t *mutex)
+{
+ int err;
+ if (!attr_initialized)
+ tor_locking_init(); // LCOV_EXCL_LINE
+ err = pthread_mutex_init(&mutex->mutex, NULL);
+ if (PREDICT_UNLIKELY(err)) {
+ // LCOV_EXCL_START
+ raw_assert_unreached_msg("Error creating a mutex.");
+ // LCOV_EXCL_STOP
+ }
+}
+
+/** Wait until <b>m</b> is free, then acquire it. */
+void
+tor_mutex_acquire(tor_mutex_t *m)
+{
+ int err;
+ raw_assert(m);
+ err = pthread_mutex_lock(&m->mutex);
+ if (PREDICT_UNLIKELY(err)) {
+ // LCOV_EXCL_START
+ raw_assert_unreached_msg("Error locking a mutex.");
+ // LCOV_EXCL_STOP
+ }
+}
+/** Release the lock <b>m</b> so another thread can have it. */
+void
+tor_mutex_release(tor_mutex_t *m)
+{
+ int err;
+ raw_assert(m);
+ err = pthread_mutex_unlock(&m->mutex);
+ if (PREDICT_UNLIKELY(err)) {
+ // LCOV_EXCL_START
+ raw_assert_unreached_msg("Error unlocking a mutex.");
+ // LCOV_EXCL_STOP
+ }
+}
+/** Clean up the mutex <b>m</b> so that it no longer uses any system
+ * resources. Does not free <b>m</b>. This function must only be called on
+ * mutexes from tor_mutex_init(). */
+void
+tor_mutex_uninit(tor_mutex_t *m)
+{
+ int err;
+ raw_assert(m);
+ err = pthread_mutex_destroy(&m->mutex);
+ if (PREDICT_UNLIKELY(err)) {
+ // LCOV_EXCL_START
+ raw_assert_unreached_msg("Error destroying a mutex.");
+ // LCOV_EXCL_STOP
+ }
+}
diff --git a/src/lib/lock/compat_mutex_winthreads.c b/src/lib/lock/compat_mutex_winthreads.c
new file mode 100644
index 0000000000..22c1edeed4
--- /dev/null
+++ b/src/lib/lock/compat_mutex_winthreads.c
@@ -0,0 +1,46 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file compat_mutex_winthreads.c
+ *
+ * \brief Implement the tor_mutex API using CRITICAL_SECTION.
+ **/
+
+#include "lib/lock/compat_mutex.h"
+#include "lib/err/torerr.h"
+
+void
+tor_locking_init(void)
+{
+}
+
+void
+tor_mutex_init(tor_mutex_t *m)
+{
+ InitializeCriticalSection(&m->mutex);
+}
+void
+tor_mutex_init_nonrecursive(tor_mutex_t *m)
+{
+ InitializeCriticalSection(&m->mutex);
+}
+
+void
+tor_mutex_uninit(tor_mutex_t *m)
+{
+ DeleteCriticalSection(&m->mutex);
+}
+void
+tor_mutex_acquire(tor_mutex_t *m)
+{
+ raw_assert(m);
+ EnterCriticalSection(&m->mutex);
+}
+void
+tor_mutex_release(tor_mutex_t *m)
+{
+ LeaveCriticalSection(&m->mutex);
+}
diff --git a/src/lib/lock/include.am b/src/lib/lock/include.am
new file mode 100644
index 0000000000..4e6f444347
--- /dev/null
+++ b/src/lib/lock/include.am
@@ -0,0 +1,24 @@
+
+noinst_LIBRARIES += src/lib/libtor-lock.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-lock-testing.a
+endif
+
+src_lib_libtor_lock_a_SOURCES = \
+ src/lib/lock/compat_mutex.c
+
+if THREADS_PTHREADS
+src_lib_libtor_lock_a_SOURCES += src/lib/lock/compat_mutex_pthreads.c
+endif
+if THREADS_WIN32
+src_lib_libtor_lock_a_SOURCES += src/lib/lock/compat_mutex_winthreads.c
+endif
+
+src_lib_libtor_lock_testing_a_SOURCES = \
+ $(src_lib_libtor_lock_a_SOURCES)
+src_lib_libtor_lock_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_lock_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/lock/compat_mutex.h
diff --git a/src/lib/log/.may_include b/src/lib/log/.may_include
new file mode 100644
index 0000000000..852173aab3
--- /dev/null
+++ b/src/lib/log/.may_include
@@ -0,0 +1,15 @@
+orconfig.h
+
+lib/cc/*.h
+lib/smartlist_core/*.h
+lib/err/*.h
+lib/fdio/*.h
+lib/intmath/*.h
+lib/lock/*.h
+lib/log/*.h
+lib/malloc/*.h
+lib/string/*.h
+lib/testsupport/*.h
+lib/wallclock/*.h
+
+micro-revision.i \ No newline at end of file
diff --git a/src/lib/log/escape.c b/src/lib/log/escape.c
new file mode 100644
index 0000000000..7561710309
--- /dev/null
+++ b/src/lib/log/escape.c
@@ -0,0 +1,132 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "lib/log/escape.h"
+#include "lib/log/util_bug.h"
+#include "lib/string/compat_ctype.h"
+#include "lib/string/printf.h"
+#include "lib/malloc/util_malloc.h"
+
+/** Allocate and return a new string representing the contents of <b>s</b>,
+ * surrounded by quotes and using standard C escapes.
+ *
+ * Generally, we use this for logging values that come in over the network to
+ * keep them from tricking users, and for sending certain values to the
+ * controller.
+ *
+ * We trust values from the resolver, OS, configuration file, and command line
+ * to not be maliciously ill-formed. We validate incoming routerdescs and
+ * SOCKS requests and addresses from BEGIN cells as they're parsed;
+ * afterwards, we trust them as non-malicious.
+ */
+char *
+esc_for_log(const char *s)
+{
+ const char *cp;
+ char *result, *outp;
+ size_t len = 3;
+ if (!s) {
+ return tor_strdup("(null)");
+ }
+
+ for (cp = s; *cp; ++cp) {
+ switch (*cp) {
+ case '\\':
+ case '\"':
+ case '\'':
+ case '\r':
+ case '\n':
+ case '\t':
+ len += 2;
+ break;
+ default:
+ if (TOR_ISPRINT(*cp) && ((uint8_t)*cp)<127)
+ ++len;
+ else
+ len += 4;
+ break;
+ }
+ }
+
+ tor_assert(len <= SSIZE_MAX);
+
+ result = outp = tor_malloc(len);
+ *outp++ = '\"';
+ for (cp = s; *cp; ++cp) {
+ /* This assertion should always succeed, since we will write at least
+ * one char here, and two chars for closing quote and nul later */
+ tor_assert((outp-result) < (ssize_t)len-2);
+ switch (*cp) {
+ case '\\':
+ case '\"':
+ case '\'':
+ *outp++ = '\\';
+ *outp++ = *cp;
+ break;
+ case '\n':
+ *outp++ = '\\';
+ *outp++ = 'n';
+ break;
+ case '\t':
+ *outp++ = '\\';
+ *outp++ = 't';
+ break;
+ case '\r':
+ *outp++ = '\\';
+ *outp++ = 'r';
+ break;
+ default:
+ if (TOR_ISPRINT(*cp) && ((uint8_t)*cp)<127) {
+ *outp++ = *cp;
+ } else {
+ tor_assert((outp-result) < (ssize_t)len-4);
+ tor_snprintf(outp, 5, "\\%03o", (int)(uint8_t) *cp);
+ outp += 4;
+ }
+ break;
+ }
+ }
+
+ tor_assert((outp-result) <= (ssize_t)len-2);
+ *outp++ = '\"';
+ *outp++ = 0;
+
+ return result;
+}
+
+/** Similar to esc_for_log. Allocate and return a new string representing
+ * the first n characters in <b>chars</b>, surround by quotes and using
+ * standard C escapes. If a NUL character is encountered in <b>chars</b>,
+ * the resulting string will be terminated there.
+ */
+char *
+esc_for_log_len(const char *chars, size_t n)
+{
+ char *string = tor_strndup(chars, n);
+ char *string_escaped = esc_for_log(string);
+ tor_free(string);
+ return string_escaped;
+}
+
+/** Allocate and return a new string representing the contents of <b>s</b>,
+ * surrounded by quotes and using standard C escapes.
+ *
+ * THIS FUNCTION IS NOT REENTRANT. Don't call it from outside the main
+ * thread. Also, each call invalidates the last-returned value, so don't
+ * try log_warn(LD_GENERAL, "%s %s", escaped(a), escaped(b));
+ */
+const char *
+escaped(const char *s)
+{
+ static char *escaped_val_ = NULL;
+ tor_free(escaped_val_);
+
+ if (s)
+ escaped_val_ = esc_for_log(s);
+ else
+ escaped_val_ = NULL;
+
+ return escaped_val_;
+}
diff --git a/src/lib/log/escape.h b/src/lib/log/escape.h
new file mode 100644
index 0000000000..5d2e79d6c2
--- /dev/null
+++ b/src/lib/log/escape.h
@@ -0,0 +1,18 @@
+/* Copyright (c) 2001, Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_ESCAPE_H
+#define TOR_ESCAPE_H
+
+#include "orconfig.h"
+#include "lib/cc/compat_compiler.h"
+#include <stddef.h>
+
+char *esc_for_log(const char *string) ATTR_MALLOC;
+char *esc_for_log_len(const char *chars, size_t n) ATTR_MALLOC;
+const char *escaped(const char *string);
+
+#endif /* !defined(TOR_TORLOG_H) */
diff --git a/src/lib/log/include.am b/src/lib/log/include.am
new file mode 100644
index 0000000000..f0491b3863
--- /dev/null
+++ b/src/lib/log/include.am
@@ -0,0 +1,31 @@
+
+noinst_LIBRARIES += src/lib/libtor-log.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-log-testing.a
+endif
+
+src_lib_libtor_log_a_SOURCES = \
+ src/lib/log/escape.c \
+ src/lib/log/ratelim.c \
+ src/lib/log/torlog.c \
+ src/lib/log/util_bug.c
+
+if WIN32
+src_lib_libtor_log_a_SOURCES += src/lib/log/win32err.c
+endif
+
+src_lib_libtor_log_testing_a_SOURCES = \
+ $(src_lib_libtor_log_a_SOURCES)
+src_lib_libtor_log_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_log_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+src/lib/log/torlog.$(OBJEXT) \
+ src/lib/log/src_lib_libtor_log_testing_a-torlog.$(OBJEXT): micro-revision.i
+
+noinst_HEADERS += \
+ src/lib/log/escape.h \
+ src/lib/log/ratelim.h \
+ src/lib/log/torlog.h \
+ src/lib/log/util_bug.h \
+ src/lib/log/win32err.h
diff --git a/src/lib/log/ratelim.c b/src/lib/log/ratelim.c
new file mode 100644
index 0000000000..677c499110
--- /dev/null
+++ b/src/lib/log/ratelim.c
@@ -0,0 +1,55 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "lib/log/ratelim.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/string/printf.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
+ * rate_limit_is_ready returned nonzero. Otherwise return 0.
+ * If the call number hits <b>RATELIM_TOOMANY</b> limit, drop a warning
+ * about this event and stop counting. */
+static int
+rate_limit_is_ready(ratelim_t *lim, time_t now)
+{
+ if (lim->rate + lim->last_allowed <= now) {
+ int res = lim->n_calls_since_last_time + 1;
+ lim->last_allowed = now;
+ lim->n_calls_since_last_time = 0;
+ return res;
+ } else {
+ if (lim->n_calls_since_last_time <= RATELIM_TOOMANY) {
+ ++lim->n_calls_since_last_time;
+ }
+
+ return 0;
+ }
+}
+
+/** If the rate-limiter <b>lim</b> is ready at <b>now</b>, return a newly
+ * allocated string indicating how many messages were suppressed, suitable to
+ * append to a log message. Otherwise return NULL. */
+char *
+rate_limit_log(ratelim_t *lim, time_t now)
+{
+ int n;
+ if ((n = rate_limit_is_ready(lim, now))) {
+ 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. */
+ tor_asprintf(&cp,
+ " [%s%d similar message(s) suppressed in last %d seconds]",
+ opt_over, n-1, lim->rate);
+ return cp;
+ }
+ } else {
+ return NULL;
+ }
+}
diff --git a/src/lib/log/ratelim.h b/src/lib/log/ratelim.h
new file mode 100644
index 0000000000..4ee6c5fed4
--- /dev/null
+++ b/src/lib/log/ratelim.h
@@ -0,0 +1,48 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_RATELIM_H
+#define TOR_RATELIM_H
+
+#include <time.h>
+
+/* Rate-limiter */
+
+/** A ratelim_t remembers how often an event is occurring, and how often
+ * it's allowed to occur. Typical usage is something like:
+ *
+ <pre>
+ if (possibly_very_frequent_event()) {
+ const int INTERVAL = 300;
+ static ratelim_t warning_limit = RATELIM_INIT(INTERVAL);
+ char *m;
+ if ((m = rate_limit_log(&warning_limit, approx_time()))) {
+ log_warn(LD_GENERAL, "The event occurred!%s", m);
+ tor_free(m);
+ }
+ }
+ </pre>
+
+ As a convenience wrapper for logging, you can replace the above with:
+ <pre>
+ if (possibly_very_frequent_event()) {
+ static ratelim_t warning_limit = RATELIM_INIT(300);
+ log_fn_ratelim(&warning_limit, LOG_WARN, LD_GENERAL,
+ "The event occurred!");
+ }
+ </pre>
+ */
+typedef struct ratelim_t {
+ int rate;
+ time_t last_allowed;
+ int n_calls_since_last_time;
+} ratelim_t;
+
+#define RATELIM_INIT(r) { (r), 0, 0 }
+#define RATELIM_TOOMANY (16*1000*1000)
+
+char *rate_limit_log(ratelim_t *lim, time_t now);
+
+#endif
diff --git a/src/common/log.c b/src/lib/log/torlog.c
index ebd50f62d3..1c9f33790d 100644
--- a/src/common/log.c
+++ b/src/lib/log/torlog.c
@@ -1,18 +1,17 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file log.c
+ * \file torlog.c
* \brief Functions to send messages to log files or the console.
**/
#include "orconfig.h"
#include <stdarg.h>
-#include <assert.h>
-// #include <stdio.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_TIME_H
@@ -30,11 +29,25 @@
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
-#include "compat.h"
-#include "util.h"
+
#define LOG_PRIVATE
-#include "torlog.h"
-#include "container.h"
+#include "lib/log/torlog.h"
+#include "lib/log/ratelim.h"
+#include "lib/lock/compat_mutex.h"
+#include "lib/smartlist_core/smartlist_core.h"
+#include "lib/smartlist_core/smartlist_foreach.h"
+#include "lib/smartlist_core/smartlist_split.h"
+#include "lib/err/torerr.h"
+#include "lib/intmath/bits.h"
+#include "lib/string/compat_string.h"
+#include "lib/string/printf.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/string/util_string.h"
+#include "lib/wallclock/tor_gettimeofday.h"
+#include "lib/wallclock/approx_time.h"
+#include "lib/wallclock/tm_cvt.h"
+#include "lib/fdio/fdio.h"
+
#ifdef HAVE_ANDROID_LOG_H
#include <android/log.h>
#endif // HAVE_ANDROID_LOG_H.
@@ -50,8 +63,6 @@
#define TRUNCATED_STR_LEN 14
/** @} */
-#define raw_assert(x) assert(x) // assert OK
-
/** Defining compile-time constants for Tor log levels (used by the Rust
* log wrapper at src/rust/tor_log) */
const int LOG_WARN_ = LOG_WARN;
@@ -89,9 +100,9 @@ sev_to_string(int severity)
case LOG_NOTICE: return "notice";
case LOG_WARN: return "warn";
case LOG_ERR: return "err";
- default: /* Call assert, not tor_assert, since tor_assert
- * calls log on failure. */
- raw_assert(0); return "UNKNOWN"; // LCOV_EXCL_LINE
+ default: /* Call assert, not tor_assert, since tor_assert
+ * calls log on failure. */
+ raw_assert_unreached(); return "UNKNOWN"; // LCOV_EXCL_LINE
}
}
@@ -195,12 +206,12 @@ static int pretty_fn_has_parens = 0;
/** Lock the log_mutex to prevent others from changing the logfile_t list */
#define LOCK_LOGS() STMT_BEGIN \
- tor_assert(log_mutex_initialized); \
+ raw_assert(log_mutex_initialized); \
tor_mutex_acquire(&log_mutex); \
STMT_END
/** Unlock the log_mutex */
#define UNLOCK_LOGS() STMT_BEGIN \
- tor_assert(log_mutex_initialized); \
+ raw_assert(log_mutex_initialized); \
tor_mutex_release(&log_mutex); \
STMT_END
@@ -268,6 +279,7 @@ void
set_log_time_granularity(int granularity_msec)
{
log_time_granularity = granularity_msec;
+ tor_log_sigsafe_err_set_granularity(granularity_msec);
}
/** Helper: Write the standard prefix for log lines to a
@@ -292,7 +304,8 @@ log_prefix_(char *buf, size_t buf_len, int severity)
ms -= ((int)now.tv_usec / 1000) % log_time_granularity;
}
- n = strftime(buf, buf_len, "%b %d %H:%M:%S", tor_localtime_r(&t, &tm));
+ n = strftime(buf, buf_len, "%b %d %H:%M:%S",
+ tor_localtime_r_msg(&t, &tm, NULL));
r = tor_snprintf(buf+n, buf_len-n, ".%.3i [%s] ", ms,
sev_to_string(severity));
@@ -335,7 +348,7 @@ log_tor_version(logfile_t *lf, int reset)
tor_snprintf(buf+n, sizeof(buf)-n,
"Tor %s opening %slog file.\n", VERSION, is_new?"new ":"");
}
- if (write_all(lf->fd, buf, strlen(buf), 0) < 0) /* error */
+ if (write_all_to_fd_minimal(lf->fd, buf, strlen(buf)) < 0) /* error */
return -1; /* failed */
return 0;
}
@@ -549,7 +562,7 @@ logfile_deliver(logfile_t *lf, const char *buf, size_t msg_len,
lf->callback(severity, domain, msg_after_prefix);
}
} else {
- if (write_all(lf->fd, buf, msg_len, 0) < 0) { /* error */
+ if (write_all_to_fd_minimal(lf->fd, buf, msg_len) < 0) { /* error */
/* don't log the error! mark this log entry to be blown away, and
* continue. */
lf->seems_dead = 1;
@@ -572,7 +585,7 @@ logv,(int severity, log_domain_mask_t domain, const char *funcname,
char *end_of_prefix=NULL;
int callbacks_deferred = 0;
- /* Call assert, not tor_assert, since tor_assert calls log on failure. */
+ /* Call assert, not raw_assert, since raw_assert calls log on failure. */
raw_assert(format);
/* check that severity is sane. Overrunning the masks array leads to
* interesting and hard to diagnose effects */
@@ -634,71 +647,6 @@ tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
va_end(ap);
}
-/** Maximum number of fds that will get notifications if we crash */
-#define MAX_SIGSAFE_FDS 8
-/** Array of fds to log crash-style warnings to. */
-static int sigsafe_log_fds[MAX_SIGSAFE_FDS] = { STDERR_FILENO };
-/** The number of elements used in sigsafe_log_fds */
-static int n_sigsafe_log_fds = 1;
-
-/** Write <b>s</b> to each element of sigsafe_log_fds. Return 0 on success, -1
- * on failure. */
-static int
-tor_log_err_sigsafe_write(const char *s)
-{
- int i;
- ssize_t r;
- size_t len = strlen(s);
- int err = 0;
- for (i=0; i < n_sigsafe_log_fds; ++i) {
- r = write(sigsafe_log_fds[i], s, len);
- err += (r != (ssize_t)len);
- }
- return err ? -1 : 0;
-}
-
-/** Given a list of string arguments ending with a NULL, writes them
- * to our logs and to stderr (if possible). This function is safe to call
- * from within a signal handler. */
-void
-tor_log_err_sigsafe(const char *m, ...)
-{
- va_list ap;
- const char *x;
- char timebuf[33];
- time_t now = time(NULL);
-
- if (!m)
- return;
- if (log_time_granularity >= 2000) {
- int g = log_time_granularity / 1000;
- now -= now % g;
- }
- timebuf[0] = now < 0 ? '-' : ' ';
- if (now < 0) now = -now;
- timebuf[1] = '\0';
- format_dec_number_sigsafe(now, timebuf+1, sizeof(timebuf)-1);
- tor_log_err_sigsafe_write("\n=========================================="
- "================== T=");
- tor_log_err_sigsafe_write(timebuf);
- tor_log_err_sigsafe_write("\n");
- tor_log_err_sigsafe_write(m);
- va_start(ap, m);
- while ((x = va_arg(ap, const char*))) {
- tor_log_err_sigsafe_write(x);
- }
- va_end(ap);
-}
-
-/** Set *<b>out</b> to a pointer to an array of the fds to log errors to from
- * inside a signal handler. Return the number of elements in the array. */
-int
-tor_log_get_sigsafe_err_fds(const int **out)
-{
- *out = sigsafe_log_fds;
- return n_sigsafe_log_fds;
-}
-
/** Helper function; return true iff the <b>n</b>-element array <b>array</b>
* contains <b>item</b>. */
static int
@@ -720,11 +668,14 @@ tor_log_update_sigsafe_err_fds(void)
const logfile_t *lf;
int found_real_stderr = 0;
+ int fds[TOR_SIGSAFE_LOG_MAX_FDS];
+ int n_fds;
+
LOCK_LOGS();
/* Reserve the first one for stderr. This is safe because when we daemonize,
* we dup2 /dev/null to stderr, */
- sigsafe_log_fds[0] = STDERR_FILENO;
- n_sigsafe_log_fds = 1;
+ fds[0] = STDERR_FILENO;
+ n_fds = 1;
for (lf = logfiles; lf; lf = lf->next) {
/* Don't try callback to the control port, or syslogs: We can't
@@ -738,22 +689,24 @@ tor_log_update_sigsafe_err_fds(void)
if (lf->fd == STDERR_FILENO)
found_real_stderr = 1;
/* Avoid duplicates */
- if (int_array_contains(sigsafe_log_fds, n_sigsafe_log_fds, lf->fd))
+ if (int_array_contains(fds, n_fds, lf->fd))
continue;
- sigsafe_log_fds[n_sigsafe_log_fds++] = lf->fd;
- if (n_sigsafe_log_fds == MAX_SIGSAFE_FDS)
+ fds[n_fds++] = lf->fd;
+ if (n_fds == TOR_SIGSAFE_LOG_MAX_FDS)
break;
}
}
if (!found_real_stderr &&
- int_array_contains(sigsafe_log_fds, n_sigsafe_log_fds, STDOUT_FILENO)) {
+ int_array_contains(fds, n_fds, STDOUT_FILENO)) {
/* Don't use a virtual stderr when we're also logging to stdout. */
- raw_assert(n_sigsafe_log_fds >= 2); /* Don't tor_assert inside log fns */
- sigsafe_log_fds[0] = sigsafe_log_fds[--n_sigsafe_log_fds];
+ raw_assert(n_fds >= 2); /* Don't raw_assert inside log fns */
+ fds[0] = fds[--n_fds];
}
UNLOCK_LOGS();
+
+ tor_log_set_sigsafe_err_fds(fds, n_fds);
}
/** Add to <b>out</b> a copy of every currently configured log file name. Used
@@ -762,7 +715,7 @@ void
tor_log_get_logfile_names(smartlist_t *out)
{
logfile_t *lf;
- tor_assert(out);
+ raw_assert(out);
LOCK_LOGS();
@@ -875,8 +828,8 @@ delete_log(logfile_t *victim)
logfiles = victim->next;
else {
for (tmpl = logfiles; tmpl && tmpl->next != victim; tmpl=tmpl->next) ;
-// tor_assert(tmpl);
-// tor_assert(tmpl->next == victim);
+// raw_assert(tmpl);
+// raw_assert(tmpl->next == victim);
if (!tmpl)
return;
tmpl->next = victim->next;
@@ -910,9 +863,9 @@ set_log_severity_config(int loglevelMin, int loglevelMax,
log_severity_list_t *severity_out)
{
int i;
- tor_assert(loglevelMin >= loglevelMax);
- tor_assert(loglevelMin >= LOG_ERR && loglevelMin <= LOG_DEBUG);
- tor_assert(loglevelMax >= LOG_ERR && loglevelMax <= LOG_DEBUG);
+ raw_assert(loglevelMin >= loglevelMax);
+ raw_assert(loglevelMin >= LOG_ERR && loglevelMin <= LOG_DEBUG);
+ raw_assert(loglevelMax >= LOG_ERR && loglevelMax <= LOG_DEBUG);
memset(severity_out, 0, sizeof(log_severity_list_t));
for (i = loglevelMin; i >= loglevelMax; --i) {
severity_out->masks[SEVERITY_MASK_IDX(i)] = ~0u;
@@ -1182,20 +1135,17 @@ mark_logs_temp(void)
}
/**
- * Add a log handler to send messages to <b>filename</b>. If opening the
- * logfile fails, -1 is returned and errno is set appropriately (by open(2)).
+ * Add a log handler to send messages to <b>filename</b> via <b>fd</b>. If
+ * opening the logfile failed, -1 is returned and errno is set appropriately
+ * (by open(2)). Takes ownership of fd.
*/
int
-add_file_log(const log_severity_list_t *severity, const char *filename,
- const int truncate_log)
+add_file_log(const log_severity_list_t *severity,
+ const char *filename,
+ int fd)
{
- int fd;
logfile_t *lf;
- int open_flags = O_WRONLY|O_CREAT;
- open_flags |= truncate_log ? O_TRUNC : O_APPEND;
-
- fd = tor_open_cloexec(filename, open_flags, 0640);
if (fd<0)
return -1;
if (tor_fd_seekend(fd)<0) {
@@ -1536,4 +1486,3 @@ truncate_logs(void)
}
}
}
-
diff --git a/src/common/torlog.h b/src/lib/log/torlog.h
index de389883c0..c24b638191 100644
--- a/src/common/torlog.h
+++ b/src/lib/log/torlog.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,8 +12,10 @@
#ifndef TOR_TORLOG_H
-#include "compat.h"
-#include "testsupport.h"
+#include <stdarg.h>
+#include "lib/cc/torint.h"
+#include "lib/cc/compat_compiler.h"
+#include "lib/testsupport/testsupport.h"
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
@@ -143,8 +145,10 @@ void set_log_severity_config(int minSeverity, int maxSeverity,
log_severity_list_t *severity_out);
void add_stream_log(const log_severity_list_t *severity, const char *name,
int fd);
-int add_file_log(const log_severity_list_t *severity, const char *filename,
- const int truncate);
+int add_file_log(const log_severity_list_t *severity,
+ const char *filename,
+ int fd);
+
#ifdef HAVE_SYSLOG_H
int add_syslog_log(const log_severity_list_t *severity,
const char* syslog_identity_tag);
@@ -175,8 +179,6 @@ void truncate_logs(void);
void tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
CHECK_PRINTF(3,4);
-void tor_log_err_sigsafe(const char *m, ...);
-int tor_log_get_sigsafe_err_fds(const int **out);
void tor_log_update_sigsafe_err_fds(void);
struct smartlist_t;
@@ -272,4 +274,3 @@ MOCK_DECL(STATIC void, logv, (int severity, log_domain_mask_t domain,
# define TOR_TORLOG_H
#endif /* !defined(TOR_TORLOG_H) */
-
diff --git a/src/common/util_bug.c b/src/lib/log/util_bug.c
index 126e843866..78af08f022 100644
--- a/src/common/util_bug.c
+++ b/src/lib/log/util_bug.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -8,10 +8,17 @@
**/
#include "orconfig.h"
-#include "util_bug.h"
-#include "torlog.h"
-#include "backtrace.h"
-#include "container.h"
+#include "lib/log/util_bug.h"
+#include "lib/log/torlog.h"
+#include "lib/err/backtrace.h"
+#ifdef TOR_UNIT_TESTS
+#include "lib/smartlist_core/smartlist_core.h"
+#include "lib/smartlist_core/smartlist_foreach.h"
+#endif
+#include "lib/malloc/util_malloc.h"
+#include "lib/string/printf.h"
+
+#include <string.h>
#ifdef __COVERITY__
int bug_macro_deadcode_dummy__ = 0;
@@ -117,3 +124,28 @@ tor_bug_occurred_(const char *fname, unsigned int line,
#endif
}
+#ifdef _WIN32
+/** Take a filename and return a pointer to its final element. This
+ * function is called on __FILE__ to fix a MSVC nit where __FILE__
+ * contains the full path to the file. This is bad, because it
+ * confuses users to find the home directory of the person who
+ * compiled the binary in their warning messages.
+ */
+const char *
+tor_fix_source_file(const char *fname)
+{
+ const char *cp1, *cp2, *r;
+ cp1 = strrchr(fname, '/');
+ cp2 = strrchr(fname, '\\');
+ if (cp1 && cp2) {
+ r = (cp1<cp2)?(cp2+1):(cp1+1);
+ } else if (cp1) {
+ r = cp1+1;
+ } else if (cp2) {
+ r = cp2+1;
+ } else {
+ r = fname;
+ }
+ return r;
+}
+#endif /* defined(_WIN32) */
diff --git a/src/common/util_bug.h b/src/lib/log/util_bug.h
index be549fde07..a0753c807b 100644
--- a/src/common/util_bug.h
+++ b/src/lib/log/util_bug.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -37,8 +37,9 @@
#define TOR_UTIL_BUG_H
#include "orconfig.h"
-#include "compat.h"
-#include "testsupport.h"
+#include "lib/cc/compat_compiler.h"
+#include "lib/log/torlog.h"
+#include "lib/testsupport/testsupport.h"
/* Replace assert() with a variant that sends failures to the log before
* calling assert() normally.
@@ -191,6 +192,14 @@ void tor_bug_occurred_(const char *fname, unsigned int line,
const char *func, const char *expr,
int once);
+#ifdef _WIN32
+#define SHORT_FILE__ (tor_fix_source_file(__FILE__))
+const char *tor_fix_source_file(const char *fname);
+#else
+#define SHORT_FILE__ (__FILE__)
+#define tor_fix_source_file(s) (s)
+#endif /* defined(_WIN32) */
+
#ifdef TOR_UNIT_TESTS
void tor_capture_bugs_(int n);
void tor_end_capture_bugs_(void);
@@ -199,4 +208,3 @@ void tor_set_failed_assertion_callback(void (*fn)(void));
#endif /* defined(TOR_UNIT_TESTS) */
#endif /* !defined(TOR_UTIL_BUG_H) */
-
diff --git a/src/lib/log/win32err.c b/src/lib/log/win32err.c
new file mode 100644
index 0000000000..4586c23c84
--- /dev/null
+++ b/src/lib/log/win32err.c
@@ -0,0 +1,56 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifdef _WIN32
+#include "orconfig.h"
+#include "lib/log/win32err.h"
+#include "lib/malloc/util_malloc.h"
+
+#include <tchar.h>
+#include <windows.h>
+
+/** Return a newly allocated string describing the windows system error code
+ * <b>err</b>. Note that error codes are different from errno. Error codes
+ * come from GetLastError() when a winapi call fails. errno is set only when
+ * ANSI functions fail. Whee. */
+char *
+format_win32_error(DWORD err)
+{
+ TCHAR *str = NULL;
+ char *result;
+ DWORD n;
+
+ /* Somebody once decided that this interface was better than strerror(). */
+ n = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err,
+ MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
+ (LPVOID)&str,
+ 0, NULL);
+
+ if (str && n) {
+#ifdef UNICODE
+ size_t len;
+ if (n > 128*1024)
+ len = (128 * 1024) * 2 + 1; /* This shouldn't be possible, but let's
+ * make sure. */
+ else
+ len = n * 2 + 1;
+ result = tor_malloc(len);
+ wcstombs(result,str,len);
+ result[len-1] = '\0';
+#else /* !(defined(UNICODE)) */
+ result = tor_strdup(str);
+#endif /* defined(UNICODE) */
+ } else {
+ result = tor_strdup("<unformattable error>");
+ }
+ if (str) {
+ LocalFree(str); /* LocalFree != free() */
+ }
+ return result;
+}
+#endif /* defined(_WIN32) */
diff --git a/src/lib/log/win32err.h b/src/lib/log/win32err.h
new file mode 100644
index 0000000000..61d3af57dd
--- /dev/null
+++ b/src/lib/log/win32err.h
@@ -0,0 +1,17 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_WIN32ERR_H
+#define TOR_WIN32ERR_H
+
+#include "orconfig.h"
+
+/* Platform-specific helpers. */
+#ifdef _WIN32
+#include <windef.h>
+char *format_win32_error(DWORD err);
+#endif
+
+#endif
diff --git a/src/lib/malloc/.may_include b/src/lib/malloc/.may_include
new file mode 100644
index 0000000000..cc62bb1013
--- /dev/null
+++ b/src/lib/malloc/.may_include
@@ -0,0 +1,6 @@
+orconfig.h
+
+lib/cc/*.h
+lib/err/*.h
+lib/malloc/*.h
+lib/testsupport/testsupport.h
diff --git a/src/lib/malloc/include.am b/src/lib/malloc/include.am
new file mode 100644
index 0000000000..50de9cb736
--- /dev/null
+++ b/src/lib/malloc/include.am
@@ -0,0 +1,21 @@
+
+noinst_LIBRARIES += src/lib/libtor-malloc.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-malloc-testing.a
+endif
+
+src_lib_libtor_malloc_a_SOURCES = \
+ src/lib/malloc/util_malloc.c
+
+if USE_OPENBSD_MALLOC
+src_lib_libtor_malloc_a_SOURCES += src/ext/OpenBSD_malloc_Linux.c
+endif
+
+src_lib_libtor_malloc_testing_a_SOURCES = \
+ $(src_lib_libtor_malloc_a_SOURCES)
+src_lib_libtor_malloc_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_malloc_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/malloc/util_malloc.h
diff --git a/src/lib/malloc/util_malloc.c b/src/lib/malloc/util_malloc.c
new file mode 100644
index 0000000000..f3b0e50c70
--- /dev/null
+++ b/src/lib/malloc/util_malloc.c
@@ -0,0 +1,230 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file util_malloc.c
+ * \brief Wrappers for C malloc code, and replacements for items that
+ * may be missing.
+ **/
+
+#include "orconfig.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "lib/testsupport/testsupport.h"
+#define UTIL_MALLOC_PRIVATE
+#include "lib/malloc/util_malloc.h"
+#include "lib/cc/torint.h"
+#include "lib/err/torerr.h"
+
+#ifdef __clang_analyzer__
+#undef MALLOC_ZERO_WORKS
+#endif
+
+/** Allocate a chunk of <b>size</b> bytes of memory, and return a pointer to
+ * result. On error, log and terminate the process. (Same as malloc(size),
+ * but never returns NULL.)
+ */
+void *
+tor_malloc_(size_t size)
+{
+ void *result;
+
+ raw_assert(size < SIZE_T_CEILING);
+
+#ifndef MALLOC_ZERO_WORKS
+ /* Some libc mallocs don't work when size==0. Override them. */
+ if (size==0) {
+ size=1;
+ }
+#endif /* !defined(MALLOC_ZERO_WORKS) */
+
+ result = raw_malloc(size);
+
+ if (PREDICT_UNLIKELY(result == NULL)) {
+ /* LCOV_EXCL_START */
+ /* If these functions die within a worker process, they won't call
+ * spawn_exit, but that's ok, since the parent will run out of memory soon
+ * anyway. */
+ raw_assert_unreached_msg("Out of memory on malloc(). Dying.");
+ /* LCOV_EXCL_STOP */
+ }
+ return result;
+}
+
+/** Allocate a chunk of <b>size</b> bytes of memory, fill the memory with
+ * zero bytes, and return a pointer to the result. Log and terminate
+ * the process on error. (Same as calloc(size,1), but never returns NULL.)
+ */
+void *
+tor_malloc_zero_(size_t size)
+{
+ /* You may ask yourself, "wouldn't it be smart to use calloc instead of
+ * malloc+memset? Perhaps libc's calloc knows some nifty optimization trick
+ * we don't!" Indeed it does, but its optimizations are only a big win when
+ * we're allocating something very big (it knows if it just got the memory
+ * from the OS in a pre-zeroed state). We don't want to use tor_malloc_zero
+ * for big stuff, so we don't bother with calloc. */
+ void *result = tor_malloc_(size);
+ memset(result, 0, size);
+ return result;
+}
+
+/* The square root of SIZE_MAX + 1. If a is less than this, and b is less
+ * than this, then a*b is less than SIZE_MAX. (For example, if size_t is
+ * 32 bits, then SIZE_MAX is 0xffffffff and this value is 0x10000. If a and
+ * b are less than this, then their product is at most (65535*65535) ==
+ * 0xfffe0001. */
+#define SQRT_SIZE_MAX_P1 (((size_t)1) << (sizeof(size_t)*4))
+
+/** Return non-zero if and only if the product of the arguments is exact,
+ * and cannot overflow. */
+STATIC int
+size_mul_check(const size_t x, const size_t y)
+{
+ /* This first check is equivalent to
+ (x < SQRT_SIZE_MAX_P1 && y < SQRT_SIZE_MAX_P1)
+
+ Rationale: if either one of x or y is >= SQRT_SIZE_MAX_P1, then it
+ will have some bit set in its most significant half.
+ */
+ return ((x|y) < SQRT_SIZE_MAX_P1 ||
+ y == 0 ||
+ x <= SIZE_MAX / y);
+}
+
+/** Allocate a chunk of <b>nmemb</b>*<b>size</b> bytes of memory, fill
+ * the memory with zero bytes, and return a pointer to the result.
+ * Log and terminate the process on error. (Same as
+ * calloc(<b>nmemb</b>,<b>size</b>), but never returns NULL.)
+ * The second argument (<b>size</b>) should preferably be non-zero
+ * and a compile-time constant.
+ */
+void *
+tor_calloc_(size_t nmemb, size_t size)
+{
+ raw_assert(size_mul_check(nmemb, size));
+ return tor_malloc_zero_((nmemb * size));
+}
+
+/** Change the size of the memory block pointed to by <b>ptr</b> to <b>size</b>
+ * bytes long; return the new memory block. On error, log and
+ * terminate. (Like realloc(ptr,size), but never returns NULL.)
+ */
+void *
+tor_realloc_(void *ptr, size_t size)
+{
+ void *result;
+
+ raw_assert(size < SIZE_T_CEILING);
+
+#ifndef MALLOC_ZERO_WORKS
+ /* Some libc mallocs don't work when size==0. Override them. */
+ if (size==0) {
+ size=1;
+ }
+#endif /* !defined(MALLOC_ZERO_WORKS) */
+
+ result = raw_realloc(ptr, size);
+
+ if (PREDICT_UNLIKELY(result == NULL)) {
+ /* LCOV_EXCL_START */
+ raw_assert_unreached_msg("Out of memory on realloc(). Dying.");
+ /* LCOV_EXCL_STOP */
+ }
+ return result;
+}
+
+/**
+ * Try to realloc <b>ptr</b> so that it takes up sz1 * sz2 bytes. Check for
+ * overflow. Unlike other allocation functions, return NULL on overflow.
+ */
+void *
+tor_reallocarray_(void *ptr, size_t sz1, size_t sz2)
+{
+ /* XXXX we can make this return 0, but we would need to check all the
+ * reallocarray users. */
+ raw_assert(size_mul_check(sz1, sz2));
+
+ return tor_realloc(ptr, (sz1 * sz2));
+}
+
+/** Return a newly allocated copy of the NUL-terminated string s. On
+ * error, log and terminate. (Like strdup(s), but never returns
+ * NULL.)
+ */
+char *
+tor_strdup_(const char *s)
+{
+ char *duplicate;
+ raw_assert(s);
+
+ duplicate = raw_strdup(s);
+
+ if (PREDICT_UNLIKELY(duplicate == NULL)) {
+ /* LCOV_EXCL_START */
+ raw_assert_unreached_msg("Out of memory on strdup(). Dying.");
+ /* LCOV_EXCL_STOP */
+ }
+ return duplicate;
+}
+
+/** Allocate and return a new string containing the first <b>n</b>
+ * characters of <b>s</b>. If <b>s</b> is longer than <b>n</b>
+ * characters, only the first <b>n</b> are copied. The result is
+ * always NUL-terminated. (Like strndup(s,n), but never returns
+ * NULL.)
+ */
+char *
+tor_strndup_(const char *s, size_t n)
+{
+ char *duplicate;
+ raw_assert(s);
+ raw_assert(n < SIZE_T_CEILING);
+ duplicate = tor_malloc_((n+1));
+ /* Performance note: Ordinarily we prefer strlcpy to strncpy. But
+ * this function gets called a whole lot, and platform strncpy is
+ * much faster than strlcpy when strlen(s) is much longer than n.
+ */
+ strncpy(duplicate, s, n);
+ duplicate[n]='\0';
+ return duplicate;
+}
+
+/** Allocate a chunk of <b>len</b> bytes, with the same contents as the
+ * <b>len</b> bytes starting at <b>mem</b>. */
+void *
+tor_memdup_(const void *mem, size_t len)
+{
+ char *duplicate;
+ raw_assert(len < SIZE_T_CEILING);
+ raw_assert(mem);
+ duplicate = tor_malloc_(len);
+ memcpy(duplicate, mem, len);
+ return duplicate;
+}
+
+/** As tor_memdup(), but add an extra 0 byte at the end of the resulting
+ * memory. */
+void *
+tor_memdup_nulterm_(const void *mem, size_t len)
+{
+ char *duplicate;
+ raw_assert(len < SIZE_T_CEILING+1);
+ raw_assert(mem);
+ duplicate = tor_malloc_(len+1);
+ memcpy(duplicate, mem, len);
+ duplicate[len] = '\0';
+ return duplicate;
+}
+
+/** Helper for places that need to take a function pointer to the right
+ * spelling of "free()". */
+void
+tor_free_(void *mem)
+{
+ tor_free(mem);
+}
diff --git a/src/lib/malloc/util_malloc.h b/src/lib/malloc/util_malloc.h
new file mode 100644
index 0000000000..a1e9531176
--- /dev/null
+++ b/src/lib/malloc/util_malloc.h
@@ -0,0 +1,92 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file util_malloc.h
+ * \brief Headers for util_malloc.c
+ **/
+
+#ifndef TOR_UTIL_MALLOC_H
+#define TOR_UTIL_MALLOC_H
+
+#include <stddef.h>
+#include <stdlib.h>
+#include "lib/cc/compat_compiler.h"
+
+/* Memory management */
+void *tor_malloc_(size_t size) ATTR_MALLOC;
+void *tor_malloc_zero_(size_t size) ATTR_MALLOC;
+void *tor_calloc_(size_t nmemb, size_t size) ATTR_MALLOC;
+void *tor_realloc_(void *ptr, size_t size);
+void *tor_reallocarray_(void *ptr, size_t size1, size_t size2);
+char *tor_strdup_(const char *s) ATTR_MALLOC;
+char *tor_strndup_(const char *s, size_t n)
+ ATTR_MALLOC;
+void *tor_memdup_(const void *mem, size_t len)
+ ATTR_MALLOC;
+void *tor_memdup_nulterm_(const void *mem, size_t len)
+ ATTR_MALLOC;
+void tor_free_(void *mem);
+
+/** Release memory allocated by tor_malloc, tor_realloc, tor_strdup,
+ * etc. Unlike the free() function, the tor_free() macro sets the
+ * pointer value to NULL after freeing it.
+ *
+ * This is a macro. If you need a function pointer to release memory from
+ * tor_malloc(), use tor_free_().
+ *
+ * Note that this macro takes the address of the pointer it is going to
+ * free and clear. If that pointer is stored with a nonstandard
+ * alignment (eg because of a "packed" pragma) it is not correct to use
+ * tor_free().
+ */
+#ifdef __GNUC__
+#define tor_free(p) STMT_BEGIN \
+ typeof(&(p)) tor_free__tmpvar = &(p); \
+ raw_free(*tor_free__tmpvar); \
+ *tor_free__tmpvar=NULL; \
+ STMT_END
+#else
+#define tor_free(p) STMT_BEGIN \
+ raw_free(p); \
+ (p)=NULL; \
+ STMT_END
+#endif
+
+#define tor_malloc(size) tor_malloc_(size)
+#define tor_malloc_zero(size) tor_malloc_zero_(size)
+#define tor_calloc(nmemb,size) tor_calloc_(nmemb, size)
+#define tor_realloc(ptr, size) tor_realloc_(ptr, size)
+#define tor_reallocarray(ptr, sz1, sz2) \
+ tor_reallocarray_((ptr), (sz1), (sz2))
+#define tor_strdup(s) tor_strdup_(s)
+#define tor_strndup(s, n) tor_strndup_(s, n)
+#define tor_memdup(s, n) tor_memdup_(s, n)
+#define tor_memdup_nulterm(s, n) tor_memdup_nulterm_(s, n)
+
+/* Aliases for the underlying system malloc/realloc/free. Only use
+ * them to indicate "I really want the underlying system function, I know
+ * what I'm doing." */
+#define raw_malloc malloc
+#define raw_realloc realloc
+#define raw_free free
+#define raw_strdup strdup
+
+/* Helper macro: free a variable of type 'typename' using freefn, and
+ * set the variable to NULL.
+ */
+#define FREE_AND_NULL(typename, freefn, var) \
+ do { \
+ /* only evaluate (var) once. */ \
+ typename **tmp__free__ptr ## freefn = &(var); \
+ freefn(*tmp__free__ptr ## freefn); \
+ (*tmp__free__ptr ## freefn) = NULL; \
+ } while (0)
+
+#ifdef UTIL_MALLOC_PRIVATE
+STATIC int size_mul_check(const size_t x, const size_t y);
+#endif
+
+#endif /* !defined(TOR_UTIL_MALLOC_H) */
diff --git a/src/lib/math/.may_include b/src/lib/math/.may_include
new file mode 100644
index 0000000000..1fd26864dc
--- /dev/null
+++ b/src/lib/math/.may_include
@@ -0,0 +1,5 @@
+orconfig.h
+
+lib/cc/*.h
+lib/log/*.h
+lib/math/*.h
diff --git a/src/lib/math/fp.c b/src/lib/math/fp.c
new file mode 100644
index 0000000000..d5989db637
--- /dev/null
+++ b/src/lib/math/fp.c
@@ -0,0 +1,119 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file fp.c
+ *
+ * \brief Basic floating-point compatibility and convenience code.
+ **/
+
+#include "orconfig.h"
+#include "lib/math/fp.h"
+
+#include <math.h>
+
+/**
+ * Returns the natural logarithm of d base e. We defined this wrapper here so
+ * to avoid conflicts with old versions of tor_log(), which were named log().
+ */
+double
+tor_mathlog(double d)
+{
+ return log(d);
+}
+
+/** Return the long integer closest to <b>d</b>. We define this wrapper
+ * here so that not all users of math.h need to use the right incantations
+ * to get the c99 functions. */
+long
+tor_lround(double d)
+{
+#if defined(HAVE_LROUND)
+ return lround(d);
+#elif defined(HAVE_RINT)
+ return (long)rint(d);
+#else
+ return (long)(d > 0 ? d + 0.5 : ceil(d - 0.5));
+#endif /* defined(HAVE_LROUND) || ... */
+}
+
+/** Return the 64-bit integer closest to d. We define this wrapper here so
+ * that not all users of math.h need to use the right incantations to get the
+ * c99 functions. */
+int64_t
+tor_llround(double d)
+{
+#if defined(HAVE_LLROUND)
+ return (int64_t)llround(d);
+#elif defined(HAVE_RINT)
+ return (int64_t)rint(d);
+#else
+ return (int64_t)(d > 0 ? d + 0.5 : ceil(d - 0.5));
+#endif /* defined(HAVE_LLROUND) || ... */
+}
+
+/** Cast a given double value to a int64_t. Return 0 if number is NaN.
+ * Returns either INT64_MIN or INT64_MAX if number is outside of the int64_t
+ * range. */
+int64_t
+clamp_double_to_int64(double number)
+{
+ int exponent;
+
+#if defined(MINGW_ANY) && GCC_VERSION >= 409
+/*
+ Mingw's math.h uses gcc's __builtin_choose_expr() facility to declare
+ isnan, isfinite, and signbit. But as implemented in at least some
+ versions of gcc, __builtin_choose_expr() can generate type warnings
+ even from branches that are not taken. So, suppress those warnings.
+*/
+#define PROBLEMATIC_FLOAT_CONVERSION_WARNING
+DISABLE_GCC_WARNING(float-conversion)
+#endif /* defined(MINGW_ANY) && GCC_VERSION >= 409 */
+
+/*
+ With clang 4.0 we apparently run into "double promotion" warnings here,
+ since clang thinks we're promoting a double to a long double.
+ */
+#if defined(__clang__)
+#if __has_warning("-Wdouble-promotion")
+#define PROBLEMATIC_DOUBLE_PROMOTION_WARNING
+DISABLE_GCC_WARNING(double-promotion)
+#endif
+#endif /* defined(__clang__) */
+
+ /* NaN is a special case that can't be used with the logic below. */
+ if (isnan(number)) {
+ return 0;
+ }
+
+ /* Time to validate if result can overflows a int64_t value. Fun with
+ * float! Find that exponent exp such that
+ * number == x * 2^exp
+ * for some x with abs(x) in [0.5, 1.0). Note that this implies that the
+ * magnitude of number is strictly less than 2^exp.
+ *
+ * If number is infinite, the call to frexp is legal but the contents of
+ * are exponent unspecified. */
+ frexp(number, &exponent);
+
+ /* If the magnitude of number is strictly less than 2^63, the truncated
+ * version of number is guaranteed to be representable. The only
+ * representable integer for which this is not the case is INT64_MIN, but
+ * it is covered by the logic below. */
+ if (isfinite(number) && exponent <= 63) {
+ return (int64_t)number;
+ }
+
+ /* Handle infinities and finite numbers with magnitude >= 2^63. */
+ return signbit(number) ? INT64_MIN : INT64_MAX;
+
+#ifdef PROBLEMATIC_DOUBLE_PROMOTION_WARNING
+ENABLE_GCC_WARNING(double-promotion)
+#endif
+#ifdef PROBLEMATIC_FLOAT_CONVERSION_WARNING
+ENABLE_GCC_WARNING(float-conversion)
+#endif
+}
diff --git a/src/lib/math/fp.h b/src/lib/math/fp.h
new file mode 100644
index 0000000000..e27b8f8d80
--- /dev/null
+++ b/src/lib/math/fp.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file fp.h
+ *
+ * \brief Header for fp.c
+ **/
+
+#ifndef TOR_FP_H
+#define TOR_FP_H
+
+#include "lib/cc/compat_compiler.h"
+#include "lib/cc/torint.h"
+
+double tor_mathlog(double d) ATTR_CONST;
+long tor_lround(double d) ATTR_CONST;
+int64_t tor_llround(double d) ATTR_CONST;
+int64_t clamp_double_to_int64(double number);
+
+#endif
diff --git a/src/lib/math/include.am b/src/lib/math/include.am
new file mode 100644
index 0000000000..b088b3f3cc
--- /dev/null
+++ b/src/lib/math/include.am
@@ -0,0 +1,20 @@
+
+noinst_LIBRARIES += src/lib/libtor-math.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-math-testing.a
+endif
+
+src_lib_libtor_math_a_SOURCES = \
+ src/lib/math/fp.c \
+ src/lib/math/laplace.c
+
+
+src_lib_libtor_math_testing_a_SOURCES = \
+ $(src_lib_libtor_math_a_SOURCES)
+src_lib_libtor_math_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_math_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/math/fp.h \
+ src/lib/math/laplace.h
diff --git a/src/lib/math/laplace.c b/src/lib/math/laplace.c
new file mode 100644
index 0000000000..6b33b46902
--- /dev/null
+++ b/src/lib/math/laplace.c
@@ -0,0 +1,73 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file laplace.c
+ *
+ * \brief Implements a Laplace distribution, used for adding noise to things.
+ **/
+
+#include "orconfig.h"
+#include "lib/math/laplace.h"
+#include "lib/math/fp.h"
+
+#include "lib/log/util_bug.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+/** Transform a random value <b>p</b> from the uniform distribution in
+ * [0.0, 1.0[ into a Laplace distributed value with location parameter
+ * <b>mu</b> and scale parameter <b>b</b>. Truncate the final result
+ * to be an integer in [INT64_MIN, INT64_MAX]. */
+int64_t
+sample_laplace_distribution(double mu, double b, double p)
+{
+ double result;
+ tor_assert(p >= 0.0 && p < 1.0);
+
+ /* This is the "inverse cumulative distribution function" from:
+ * http://en.wikipedia.org/wiki/Laplace_distribution */
+ if (p <= 0.0) {
+ /* Avoid taking log(0.0) == -INFINITY, as some processors or compiler
+ * options can cause the program to trap. */
+ return INT64_MIN;
+ }
+
+ result = mu - b * (p > 0.5 ? 1.0 : -1.0)
+ * tor_mathlog(1.0 - 2.0 * fabs(p - 0.5));
+
+ return clamp_double_to_int64(result);
+}
+
+/** Add random noise between INT64_MIN and INT64_MAX coming from a Laplace
+ * distribution with mu = 0 and b = <b>delta_f</b>/<b>epsilon</b> to
+ * <b>signal</b> based on the provided <b>random</b> value in [0.0, 1.0[.
+ * The epsilon value must be between ]0.0, 1.0]. delta_f must be greater
+ * than 0. */
+int64_t
+add_laplace_noise(int64_t signal_, double random_, double delta_f,
+ double epsilon)
+{
+ int64_t noise;
+
+ /* epsilon MUST be between ]0.0, 1.0] */
+ tor_assert(epsilon > 0.0 && epsilon <= 1.0);
+ /* delta_f MUST be greater than 0. */
+ tor_assert(delta_f > 0.0);
+
+ /* Just add noise, no further signal */
+ noise = sample_laplace_distribution(0.0,
+ delta_f / epsilon,
+ random_);
+
+ /* Clip (signal + noise) to [INT64_MIN, INT64_MAX] */
+ if (noise > 0 && INT64_MAX - noise < signal_)
+ return INT64_MAX;
+ else if (noise < 0 && INT64_MIN - noise > signal_)
+ return INT64_MIN;
+ else
+ return signal_ + noise;
+}
diff --git a/src/lib/math/laplace.h b/src/lib/math/laplace.h
new file mode 100644
index 0000000000..62d698e369
--- /dev/null
+++ b/src/lib/math/laplace.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file laplace.h
+ *
+ * \brief Header for laplace.c
+ **/
+
+#ifndef TOR_LAPLACE_H
+#define TOR_LAPLACE_H
+
+#include "lib/cc/compat_compiler.h"
+#include "lib/cc/torint.h"
+
+int64_t sample_laplace_distribution(double mu, double b, double p);
+int64_t add_laplace_noise(int64_t signal, double random, double delta_f,
+ double epsilon);
+
+#endif
diff --git a/src/lib/memarea/.may_include b/src/lib/memarea/.may_include
new file mode 100644
index 0000000000..814652a93c
--- /dev/null
+++ b/src/lib/memarea/.may_include
@@ -0,0 +1,7 @@
+orconfig.h
+lib/arch/*.h
+lib/cc/*.h
+lib/container/*.h
+lib/log/*.h
+lib/malloc/*.h
+lib/memarea/*.h
diff --git a/src/lib/memarea/include.am b/src/lib/memarea/include.am
new file mode 100644
index 0000000000..94343dcead
--- /dev/null
+++ b/src/lib/memarea/include.am
@@ -0,0 +1,17 @@
+
+noinst_LIBRARIES += src/lib/libtor-memarea.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-memarea-testing.a
+endif
+
+src_lib_libtor_memarea_a_SOURCES = \
+ src/lib/memarea/memarea.c
+
+src_lib_libtor_memarea_testing_a_SOURCES = \
+ $(src_lib_libtor_memarea_a_SOURCES)
+src_lib_libtor_memarea_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_memarea_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/memarea/memarea.h
diff --git a/src/common/memarea.c b/src/lib/memarea/memarea.c
index 68c1625fe4..9d494ab2d4 100644
--- a/src/common/memarea.c
+++ b/src/lib/memarea/memarea.c
@@ -1,19 +1,25 @@
-/* Copyright (c) 2008-2017, The Tor Project, Inc. */
+/* Copyright (c) 2008-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-/** \file memarea.c
+/**
+ * \file memarea.c
+ *
* \brief Implementation for memarea_t, an allocator for allocating lots of
* small objects that will be freed all at once.
*/
#include "orconfig.h"
-#include <stddef.h>
+#include "lib/memarea/memarea.h"
+
#include <stdlib.h>
-#include "memarea.h"
-#include "util.h"
-#include "compat.h"
-#include "torlog.h"
-#include "container.h"
+#include <string.h>
+
+#include "lib/arch/bytes.h"
+#include "lib/cc/torint.h"
+#include "lib/container/smartlist.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/malloc/util_malloc.h"
#ifndef DISABLE_MEMORY_SENTINELS
@@ -395,4 +401,3 @@ memarea_assert_ok(memarea_t *area)
}
#endif /* !defined(DISABLE_MEMORY_SENTINELS) */
-
diff --git a/src/common/memarea.h b/src/lib/memarea/memarea.h
index 5207e8a5bd..4978b54162 100644
--- a/src/common/memarea.h
+++ b/src/lib/memarea/memarea.h
@@ -1,10 +1,17 @@
-/* Copyright (c) 2008-2017, The Tor Project, Inc. */
+/* Copyright (c) 2008-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-/* Tor dependencies */
+
+/**
+ * \file memarea.h
+ *
+ * \brief Header for memarea.c
+ **/
#ifndef TOR_MEMAREA_H
#define TOR_MEMAREA_H
+#include <stddef.h>
+
typedef struct memarea_t memarea_t;
memarea_t *memarea_new(void);
@@ -26,4 +33,3 @@ void memarea_get_stats(memarea_t *area,
void memarea_assert_ok(memarea_t *area);
#endif /* !defined(TOR_MEMAREA_H) */
-
diff --git a/src/lib/meminfo/.may_include b/src/lib/meminfo/.may_include
new file mode 100644
index 0000000000..9e4d25fd6a
--- /dev/null
+++ b/src/lib/meminfo/.may_include
@@ -0,0 +1,8 @@
+orconfig.h
+
+lib/cc/*.h
+lib/fs/*.h
+lib/log/*.h
+lib/malloc/*.h
+lib/meminfo/*.h
+lib/testsupport/*.h
diff --git a/src/lib/meminfo/include.am b/src/lib/meminfo/include.am
new file mode 100644
index 0000000000..d1fdde6313
--- /dev/null
+++ b/src/lib/meminfo/include.am
@@ -0,0 +1,17 @@
+
+noinst_LIBRARIES += src/lib/libtor-meminfo.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-meminfo-testing.a
+endif
+
+src_lib_libtor_meminfo_a_SOURCES = \
+ src/lib/meminfo/meminfo.c
+
+src_lib_libtor_meminfo_testing_a_SOURCES = \
+ $(src_lib_libtor_meminfo_a_SOURCES)
+src_lib_libtor_meminfo_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_meminfo_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/meminfo/meminfo.h
diff --git a/src/lib/meminfo/meminfo.c b/src/lib/meminfo/meminfo.c
new file mode 100644
index 0000000000..b5a74ce624
--- /dev/null
+++ b/src/lib/meminfo/meminfo.c
@@ -0,0 +1,180 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file meminfo.c
+ *
+ * \brief Functions to query total memory, and access meta-information about
+ * the allocator.
+ **/
+
+#include "lib/meminfo/meminfo.h"
+
+#include "lib/cc/compat_compiler.h"
+#include "lib/cc/torint.h"
+#include "lib/fs/files.h"
+#include "lib/log/torlog.h"
+#include "lib/malloc/util_malloc.h"
+
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+#include <string.h>
+
+DISABLE_GCC_WARNING(aggregate-return)
+/** Call the platform malloc info function, and dump the results to the log at
+ * level <b>severity</b>. If no such function exists, do nothing. */
+void
+tor_log_mallinfo(int severity)
+{
+#ifdef HAVE_MALLINFO
+ struct mallinfo mi;
+ memset(&mi, 0, sizeof(mi));
+ mi = mallinfo();
+ tor_log(severity, LD_MM,
+ "mallinfo() said: arena=%d, ordblks=%d, smblks=%d, hblks=%d, "
+ "hblkhd=%d, usmblks=%d, fsmblks=%d, uordblks=%d, fordblks=%d, "
+ "keepcost=%d",
+ mi.arena, mi.ordblks, mi.smblks, mi.hblks,
+ mi.hblkhd, mi.usmblks, mi.fsmblks, mi.uordblks, mi.fordblks,
+ mi.keepcost);
+#else /* !(defined(HAVE_MALLINFO)) */
+ (void)severity;
+#endif /* defined(HAVE_MALLINFO) */
+}
+ENABLE_GCC_WARNING(aggregate-return)
+
+#if defined(HW_PHYSMEM64)
+/* This appears to be an OpenBSD thing */
+#define INT64_HW_MEM HW_PHYSMEM64
+#elif defined(HW_MEMSIZE)
+/* OSX defines this one */
+#define INT64_HW_MEM HW_MEMSIZE
+#endif /* defined(HW_PHYSMEM64) || ... */
+
+/**
+ * Helper: try to detect the total system memory, and return it. On failure,
+ * return 0.
+ */
+static uint64_t
+get_total_system_memory_impl(void)
+{
+#if defined(__linux__)
+ /* On linux, sysctl is deprecated. Because proc is so awesome that you
+ * shouldn't _want_ to write portable code, I guess? */
+ unsigned long long result=0;
+ int fd = -1;
+ char *s = NULL;
+ const char *cp;
+ size_t file_size=0;
+ if (-1 == (fd = tor_open_cloexec("/proc/meminfo",O_RDONLY,0)))
+ return 0;
+ s = read_file_to_str_until_eof(fd, 65536, &file_size);
+ if (!s)
+ goto err;
+ cp = strstr(s, "MemTotal:");
+ if (!cp)
+ goto err;
+ /* Use the system sscanf so that space will match a wider number of space */
+ if (sscanf(cp, "MemTotal: %llu kB\n", &result) != 1)
+ goto err;
+
+ close(fd);
+ tor_free(s);
+ return result * 1024;
+
+ /* LCOV_EXCL_START Can't reach this unless proc is broken. */
+ err:
+ tor_free(s);
+ close(fd);
+ return 0;
+ /* LCOV_EXCL_STOP */
+#elif defined (_WIN32)
+ /* Windows has MEMORYSTATUSEX; pretty straightforward. */
+ MEMORYSTATUSEX ms;
+ memset(&ms, 0, sizeof(ms));
+ ms.dwLength = sizeof(ms);
+ if (! GlobalMemoryStatusEx(&ms))
+ return 0;
+
+ return ms.ullTotalPhys;
+
+#elif defined(HAVE_SYSCTL) && defined(INT64_HW_MEM)
+ /* On many systems, HW_PYHSMEM is clipped to 32 bits; let's use a better
+ * variant if we know about it. */
+ uint64_t memsize = 0;
+ size_t len = sizeof(memsize);
+ int mib[2] = {CTL_HW, INT64_HW_MEM};
+ if (sysctl(mib,2,&memsize,&len,NULL,0))
+ return 0;
+
+ return memsize;
+
+#elif defined(HAVE_SYSCTL) && defined(HW_PHYSMEM)
+ /* On some systems (like FreeBSD I hope) you can use a size_t with
+ * HW_PHYSMEM. */
+ size_t memsize=0;
+ size_t len = sizeof(memsize);
+ int mib[2] = {CTL_HW, HW_USERMEM};
+ if (sysctl(mib,2,&memsize,&len,NULL,0))
+ return 0;
+
+ return memsize;
+
+#else
+ /* I have no clue. */
+ return 0;
+#endif /* defined(__linux__) || ... */
+}
+
+/**
+ * Try to find out how much physical memory the system has. On success,
+ * return 0 and set *<b>mem_out</b> to that value. On failure, return -1.
+ */
+MOCK_IMPL(int,
+get_total_system_memory, (size_t *mem_out))
+{
+ static size_t mem_cached=0;
+ uint64_t m = get_total_system_memory_impl();
+ if (0 == m) {
+ /* LCOV_EXCL_START -- can't make this happen without mocking. */
+ /* We couldn't find our memory total */
+ if (0 == mem_cached) {
+ /* We have no cached value either */
+ *mem_out = 0;
+ return -1;
+ }
+
+ *mem_out = mem_cached;
+ return 0;
+ /* LCOV_EXCL_STOP */
+ }
+
+#if SIZE_MAX != UINT64_MAX
+ if (m > SIZE_MAX) {
+ /* I think this could happen if we're a 32-bit Tor running on a 64-bit
+ * system: we could have more system memory than would fit in a
+ * size_t. */
+ m = SIZE_MAX;
+ }
+#endif /* SIZE_MAX != UINT64_MAX */
+
+ *mem_out = mem_cached = (size_t) m;
+
+ return 0;
+}
diff --git a/src/lib/meminfo/meminfo.h b/src/lib/meminfo/meminfo.h
new file mode 100644
index 0000000000..b67d235559
--- /dev/null
+++ b/src/lib/meminfo/meminfo.h
@@ -0,0 +1,21 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file meminfo.h
+ *
+ * \brief Header for meminfo.c
+ **/
+
+#ifndef TOR_MEMINFO_H
+#define TOR_MEMINFO_H
+
+#include "lib/testsupport/testsupport.h"
+#include <stddef.h>
+
+void tor_log_mallinfo(int severity);
+MOCK_DECL(int, get_total_system_memory, (size_t *mem_out));
+
+#endif
diff --git a/src/lib/net/.may_include b/src/lib/net/.may_include
new file mode 100644
index 0000000000..1458dad990
--- /dev/null
+++ b/src/lib/net/.may_include
@@ -0,0 +1,14 @@
+orconfig.h
+siphash.h
+ht.h
+
+lib/cc/*.h
+lib/container/*.h
+lib/ctime/*.h
+lib/err/*.h
+lib/lock/*.h
+lib/log/*.h
+lib/net/*.h
+lib/string/*.h
+lib/testsupport/*.h
+lib/malloc/*.h \ No newline at end of file
diff --git a/src/common/address.c b/src/lib/net/address.c
index a32df99107..f3eddca7bb 100644
--- a/src/common/address.c
+++ b/src/lib/net/address.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -35,13 +35,22 @@
#include <iphlpapi.h>
#endif /* defined(_WIN32) */
-#include "compat.h"
-#include "util.h"
-#include "util_format.h"
-#include "address.h"
-#include "torlog.h"
-#include "container.h"
-#include "sandbox.h"
+#include "lib/net/address.h"
+#include "lib/net/socket.h"
+#include "lib/net/resolve.h"
+#include "lib/container/smartlist.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/log/torlog.h"
+#include "lib/log/escape.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/net/ipv4.h"
+#include "lib/string/compat_ctype.h"
+#include "lib/string/compat_string.h"
+#include "lib/string/parse_int.h"
+#include "lib/string/printf.h"
+#include "lib/string/util_string.h"
+
+#include "siphash.h"
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
@@ -52,9 +61,6 @@
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
@@ -83,7 +89,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
/* tor_addr_is_null() and maybe other functions rely on AF_UNSPEC being 0 to
* work correctly. Bail out here if we've found a platform where AF_UNSPEC
@@ -272,7 +277,7 @@ tor_addr_lookup,(const char *name, uint16_t family, tor_addr_t *addr))
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
- err = sandbox_getaddrinfo(name, NULL, &hints, &res);
+ err = tor_getaddrinfo(name, NULL, &hints, &res);
/* The check for 'res' here shouldn't be necessary, but it makes static
* analysis tools happy. */
if (!err && res) {
@@ -301,7 +306,7 @@ tor_addr_lookup,(const char *name, uint16_t family, tor_addr_t *addr))
&((struct sockaddr_in6*)best->ai_addr)->sin6_addr);
result = 0;
}
- sandbox_freeaddrinfo(res);
+ tor_freeaddrinfo(res);
return result;
}
return (err == EAI_AGAIN) ? 1 : -1;
@@ -1474,14 +1479,7 @@ ip_adapter_addresses_to_smartlist(const IP_ADAPTER_ADDRESSES *addresses)
STATIC smartlist_t *
get_interface_addresses_win32(int severity, sa_family_t family)
{
-
- /* Windows XP began to provide GetAdaptersAddresses. Windows 2000 had a
- "GetAdaptersInfo", but that's deprecated; let's just try
- GetAdaptersAddresses and fall back to connect+getsockname.
- */
- HANDLE lib = load_windows_system_library(TEXT("iphlpapi.dll"));
smartlist_t *result = NULL;
- GetAdaptersAddresses_fn_t fn;
ULONG size, res;
IP_ADAPTER_ADDRESSES *addresses = NULL;
@@ -1491,27 +1489,16 @@ get_interface_addresses_win32(int severity, sa_family_t family)
GAA_FLAG_SKIP_MULTICAST | \
GAA_FLAG_SKIP_DNS_SERVER)
- if (!lib) {
- log_fn(severity, LD_NET, "Unable to load iphlpapi.dll");
- goto done;
- }
-
- if (!(fn = (GetAdaptersAddresses_fn_t)
- GetProcAddress(lib, "GetAdaptersAddresses"))) {
- log_fn(severity, LD_NET, "Unable to obtain pointer to "
- "GetAdaptersAddresses");
- goto done;
- }
-
/* Guess how much space we need. */
size = 15*1024;
addresses = tor_malloc(size);
- res = fn(family, FLAGS, NULL, addresses, &size);
+ /* Exists in windows XP and later. */
+ res = GetAdaptersAddresses(family, FLAGS, NULL, addresses, &size);
if (res == ERROR_BUFFER_OVERFLOW) {
/* we didn't guess that we needed enough space; try again */
tor_free(addresses);
addresses = tor_malloc(size);
- res = fn(AF_UNSPEC, FLAGS, NULL, addresses, &size);
+ res = GetAdaptersAddresses(AF_UNSPEC, FLAGS, NULL, addresses, &size);
}
if (res != NO_ERROR) {
log_fn(severity, LD_NET, "GetAdaptersAddresses failed (result: %lu)", res);
@@ -1521,8 +1508,6 @@ get_interface_addresses_win32(int severity, sa_family_t family)
result = ip_adapter_addresses_to_smartlist(addresses);
done:
- if (lib)
- FreeLibrary(lib);
tor_free(addresses);
return result;
}
@@ -2087,22 +2072,6 @@ parse_port_range(const char *port, uint16_t *port_min_out,
return 0;
}
-/** Given an IPv4 in_addr struct *<b>in</b> (in network order, as usual),
- * write it as a string into the <b>buf_len</b>-byte buffer in
- * <b>buf</b>. Returns a non-negative integer on success.
- * Returns -1 on failure.
- */
-int
-tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len)
-{
- uint32_t a = ntohl(in->s_addr);
- return tor_snprintf(buf, buf_len, "%d.%d.%d.%d",
- (int)(uint8_t)((a>>24)&0xff),
- (int)(uint8_t)((a>>16)&0xff),
- (int)(uint8_t)((a>>8 )&0xff),
- (int)(uint8_t)((a )&0xff));
-}
-
/** Given a host-order <b>addr</b>, call tor_inet_ntop() on it
* and return a strdup of the resulting address.
*/
@@ -2171,3 +2140,117 @@ 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
+ * 'a.b.c.d' form.
+ */
+int
+string_is_valid_ipv4_address(const char *string)
+{
+ struct in_addr addr;
+
+ return (tor_inet_pton(AF_INET,string,&addr) == 1);
+}
+
+/** Return true if <b>string</b> represents a valid IPv6 address in
+ * a form that inet_pton() can parse.
+ */
+int
+string_is_valid_ipv6_address(const char *string)
+{
+ struct in6_addr addr;
+
+ return (tor_inet_pton(AF_INET6,string,&addr) == 1);
+}
+
+/** Return true iff <b>string</b> is a valid destination address,
+ * i.e. either a DNS hostname or IPv4/IPv6 address string.
+ */
+int
+string_is_valid_dest(const char *string)
+{
+ char *tmp = NULL;
+ int retval;
+ size_t len;
+
+ if (string == NULL)
+ return 0;
+
+ len = strlen(string);
+
+ if (len == 0)
+ return 0;
+
+ if (string[0] == '[' && string[len - 1] == ']')
+ string = tmp = tor_strndup(string + 1, len - 2);
+
+ retval = string_is_valid_ipv4_address(string) ||
+ string_is_valid_ipv6_address(string) ||
+ string_is_valid_nonrfc_hostname(string);
+
+ tor_free(tmp);
+
+ return retval;
+}
+
+/** Return true iff <b>string</b> matches a pattern of DNS names
+ * that we allow Tor clients to connect to.
+ *
+ * Note: This allows certain technically invalid characters ('_') to cope
+ * with misconfigured zones that have been encountered in the wild.
+ */
+int
+string_is_valid_nonrfc_hostname(const char *string)
+{
+ int result = 1;
+ int has_trailing_dot;
+ char *last_label;
+ smartlist_t *components;
+
+ if (!string || strlen(string) == 0)
+ return 0;
+
+ if (string_is_valid_ipv4_address(string))
+ return 0;
+
+ components = smartlist_new();
+
+ smartlist_split_string(components,string,".",0,0);
+
+ if (BUG(smartlist_len(components) == 0))
+ return 0; // LCOV_EXCL_LINE should be impossible given the earlier checks.
+
+ /* Allow a single terminating '.' used rarely to indicate domains
+ * are FQDNs rather than relative. */
+ last_label = (char *)smartlist_get(components,
+ smartlist_len(components) - 1);
+ has_trailing_dot = (last_label[0] == '\0');
+ if (has_trailing_dot) {
+ smartlist_pop_last(components);
+ tor_free(last_label);
+ last_label = NULL;
+ }
+
+ SMARTLIST_FOREACH_BEGIN(components, char *, c) {
+ if ((c[0] == '-') || (*c == '_')) {
+ result = 0;
+ break;
+ }
+
+ do {
+ result = (TOR_ISALNUM(*c) || (*c == '-') || (*c == '_'));
+ c++;
+ } while (result && *c);
+
+ if (result == 0) {
+ break;
+ }
+ } SMARTLIST_FOREACH_END(c);
+
+ SMARTLIST_FOREACH_BEGIN(components, char *, c) {
+ tor_free(c);
+ } SMARTLIST_FOREACH_END(c);
+
+ smartlist_free(components);
+
+ return result;
+}
diff --git a/src/common/address.h b/src/lib/net/address.h
index c9d9543dee..f8ea573c30 100644
--- a/src/common/address.h
+++ b/src/lib/net/address.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -11,11 +11,22 @@
#ifndef TOR_ADDRESS_H
#define TOR_ADDRESS_H
-//#include <sys/sockio.h>
#include "orconfig.h"
-#include "torint.h"
-#include "compat.h"
-#include "container.h"
+#include "lib/cc/torint.h"
+#include "lib/log/util_bug.h"
+#include "lib/net/ipv6.h"
+#include "lib/net/nettypes.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef _WIN32
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
#ifdef ADDRESS_PRIVATE
@@ -73,6 +84,9 @@ typedef struct tor_addr_port_t
#define TOR_ADDR_NULL {AF_UNSPEC, {0}}
+/* XXXX To do: extract all of the functions here that can possibly invoke
+ * XXXX resolver, and make sure they have distinctive names. */
+
static inline const struct in6_addr *tor_addr_to_in6(const tor_addr_t *a);
static inline const struct in6_addr *tor_addr_to_in6_assert(
const tor_addr_t *a);
@@ -206,10 +220,11 @@ const char * fmt_addr32(uint32_t addr);
MOCK_DECL(int,get_interface_address6,(int severity, sa_family_t family,
tor_addr_t *addr));
-void interface_address6_list_free_(smartlist_t * addrs);// XXXX
+struct smartlist_t;
+void interface_address6_list_free_(struct smartlist_t * addrs);// XXXX
#define interface_address6_list_free(addrs) \
- FREE_AND_NULL(smartlist_t, interface_address6_list_free_, (addrs))
-MOCK_DECL(smartlist_t *,get_interface_address6_list,(int severity,
+ FREE_AND_NULL(struct smartlist_t, interface_address6_list_free_, (addrs))
+MOCK_DECL(struct smartlist_t *,get_interface_address6_list,(int severity,
sa_family_t family,
int include_internal));
@@ -320,9 +335,6 @@ int addr_port_lookup(int severity, const char *addrport, char **address,
int parse_port_range(const char *port, uint16_t *port_min_out,
uint16_t *port_max_out);
int addr_mask_get_bits(uint32_t mask);
-/** Length of a buffer to allocate to hold the results of tor_inet_ntoa.*/
-#define INET_NTOA_BUF_LEN 16
-int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len);
char *tor_dup_ip(uint32_t addr) ATTR_MALLOC;
MOCK_DECL(int,get_interface_address,(int severity, uint32_t *addr));
#define interface_address_list_free(lst)\
@@ -335,7 +347,7 @@ MOCK_DECL(int,get_interface_address,(int severity, uint32_t *addr));
* Returns NULL on failure.
* Use free_interface_address_list to free the returned list.
*/
-static inline smartlist_t *
+static inline struct smartlist_t *
get_interface_address_list(int severity, int include_internal)
{
return get_interface_address6_list(severity, AF_INET, include_internal);
@@ -345,35 +357,39 @@ 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);
+int string_is_valid_dest(const char *string);
+int string_is_valid_nonrfc_hostname(const char *string);
+int string_is_valid_ipv4_address(const char *string);
+int string_is_valid_ipv6_address(const char *string);
+
#ifdef ADDRESS_PRIVATE
-MOCK_DECL(smartlist_t *,get_interface_addresses_raw,(int severity,
+MOCK_DECL(struct smartlist_t *,get_interface_addresses_raw,(int severity,
sa_family_t family));
MOCK_DECL(int,get_interface_address6_via_udp_socket_hack,(int severity,
sa_family_t family,
tor_addr_t *addr));
#ifdef HAVE_IFADDRS_TO_SMARTLIST
-STATIC smartlist_t *ifaddrs_to_smartlist(const struct ifaddrs *ifa,
+STATIC struct smartlist_t *ifaddrs_to_smartlist(const struct ifaddrs *ifa,
sa_family_t family);
-STATIC smartlist_t *get_interface_addresses_ifaddrs(int severity,
+STATIC struct smartlist_t *get_interface_addresses_ifaddrs(int severity,
sa_family_t family);
#endif /* defined(HAVE_IFADDRS_TO_SMARTLIST) */
#ifdef HAVE_IP_ADAPTER_TO_SMARTLIST
-STATIC smartlist_t *ip_adapter_addresses_to_smartlist(
+STATIC struct smartlist_t *ip_adapter_addresses_to_smartlist(
const IP_ADAPTER_ADDRESSES *addresses);
-STATIC smartlist_t *get_interface_addresses_win32(int severity,
+STATIC struct smartlist_t *get_interface_addresses_win32(int severity,
sa_family_t family);
#endif /* defined(HAVE_IP_ADAPTER_TO_SMARTLIST) */
#ifdef HAVE_IFCONF_TO_SMARTLIST
-STATIC smartlist_t *ifreq_to_smartlist(char *ifr,
+STATIC struct smartlist_t *ifreq_to_smartlist(char *ifr,
size_t buflen);
-STATIC smartlist_t *get_interface_addresses_ioctl(int severity,
+STATIC struct smartlist_t *get_interface_addresses_ioctl(int severity,
sa_family_t family);
#endif /* defined(HAVE_IFCONF_TO_SMARTLIST) */
#endif /* defined(ADDRESS_PRIVATE) */
#endif /* !defined(TOR_ADDRESS_H) */
-
diff --git a/src/common/compat_threads.c b/src/lib/net/alertsock.c
index 3171c4b2f2..340f9513fb 100644
--- a/src/common/compat_threads.c
+++ b/src/lib/net/alertsock.c
@@ -1,23 +1,23 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file compat_threads.c
+ * \file alertsock.c
*
- * \brief Cross-platform threading and inter-thread communication logic.
- * (Platform-specific parts are written in the other compat_*threads
- * modules.)
- */
+ * \brief Use a socket to alert the main thread from a worker thread.
+ *
+ * Because our main loop spends all of its time in select, epoll, kqueue, or
+ * etc, we need a way to wake up the main loop from another thread. This code
+ * tries to provide the fastest reasonable way to do that, depending on our
+ * platform.
+ **/
#include "orconfig.h"
-#include <stdlib.h>
-#include "compat.h"
-#include "compat_threads.h"
-
-#include "util.h"
-#include "torlog.h"
+#include "lib/net/alertsock.h"
+#include "lib/net/socket.h"
+#include "lib/log/util_bug.h"
#ifdef HAVE_SYS_EVENTFD_H
#include <sys/eventfd.h>
@@ -28,70 +28,12 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-
-/** Return a newly allocated, ready-for-use mutex. */
-tor_mutex_t *
-tor_mutex_new(void)
-{
- tor_mutex_t *m = tor_malloc_zero(sizeof(tor_mutex_t));
- tor_mutex_init(m);
- return m;
-}
-/** Return a newly allocated, ready-for-use mutex. This one might be
- * non-recursive, if that's faster. */
-tor_mutex_t *
-tor_mutex_new_nonrecursive(void)
-{
- tor_mutex_t *m = tor_malloc_zero(sizeof(tor_mutex_t));
- tor_mutex_init_nonrecursive(m);
- return m;
-}
-/** Release all storage and system resources held by <b>m</b>. */
-void
-tor_mutex_free_(tor_mutex_t *m)
-{
- if (!m)
- return;
- tor_mutex_uninit(m);
- tor_free(m);
-}
-
-/** Allocate and return a new condition variable. */
-tor_cond_t *
-tor_cond_new(void)
-{
- tor_cond_t *cond = tor_malloc(sizeof(tor_cond_t));
- if (BUG(tor_cond_init(cond)<0))
- tor_free(cond); // LCOV_EXCL_LINE
- return cond;
-}
-
-/** Free all storage held in <b>c</b>. */
-void
-tor_cond_free_(tor_cond_t *c)
-{
- if (!c)
- return;
- tor_cond_uninit(c);
- tor_free(c);
-}
-
-/** Identity of the "main" thread */
-static unsigned long main_thread_id = -1;
-
-/** Start considering the current thread to be the 'main thread'. This has
- * no effect on anything besides in_main_thread(). */
-void
-set_main_thread(void)
-{
- main_thread_id = tor_get_thread_id();
-}
-/** Return true iff called from the main thread. */
-int
-in_main_thread(void)
-{
- return main_thread_id == tor_get_thread_id();
-}
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef _WIN32
+#include <winsock2.h>
+#endif
#if defined(HAVE_EVENTFD) || defined(HAVE_PIPE)
/* As write(), but retry on EINTR, and return the negative error code on
@@ -351,57 +293,3 @@ alert_sockets_close(alert_sockets_t *socks)
}
socks->read_fd = socks->write_fd = -1;
}
-
-#ifndef HAVE_STDATOMIC_H
-/** Initialize a new atomic counter with the value 0 */
-void
-atomic_counter_init(atomic_counter_t *counter)
-{
- memset(counter, 0, sizeof(*counter));
- tor_mutex_init_nonrecursive(&counter->mutex);
-}
-/** Clean up all resources held by an atomic counter. */
-void
-atomic_counter_destroy(atomic_counter_t *counter)
-{
- tor_mutex_uninit(&counter->mutex);
- memset(counter, 0, sizeof(*counter));
-}
-/** Add a value to an atomic counter. */
-void
-atomic_counter_add(atomic_counter_t *counter, size_t add)
-{
- tor_mutex_acquire(&counter->mutex);
- counter->val += add;
- tor_mutex_release(&counter->mutex);
-}
-/** Subtract a value from an atomic counter. */
-void
-atomic_counter_sub(atomic_counter_t *counter, size_t sub)
-{
- // this relies on unsigned overflow, but that's fine.
- atomic_counter_add(counter, -sub);
-}
-/** Return the current value of an atomic counter */
-size_t
-atomic_counter_get(atomic_counter_t *counter)
-{
- size_t val;
- tor_mutex_acquire(&counter->mutex);
- val = counter->val;
- tor_mutex_release(&counter->mutex);
- return val;
-}
-/** Replace the value of an atomic counter; return the old one. */
-size_t
-atomic_counter_exchange(atomic_counter_t *counter, size_t newval)
-{
- size_t oldval;
- tor_mutex_acquire(&counter->mutex);
- oldval = counter->val;
- counter->val = newval;
- tor_mutex_release(&counter->mutex);
- return oldval;
-}
-#endif /* !defined(HAVE_STDATOMIC_H) */
-
diff --git a/src/lib/net/alertsock.h b/src/lib/net/alertsock.h
new file mode 100644
index 0000000000..5dfe53a2a0
--- /dev/null
+++ b/src/lib/net/alertsock.h
@@ -0,0 +1,45 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file alertsock.h
+ *
+ * \brief Header for alertsock.c
+ **/
+
+#ifndef TOR_ALERTSOCK_H
+#define TOR_ALERTSOCK_H
+
+#include "orconfig.h"
+#include "lib/net/nettypes.h"
+#include "lib/cc/torint.h"
+
+/** Helper type used to manage waking up the main thread while it's in
+ * the libevent main loop. Used by the work queue code. */
+typedef struct alert_sockets_t {
+ /* XXXX This structure needs a better name. */
+ /** Socket that the main thread should listen for EV_READ events on.
+ * Note that this socket may be a regular fd on a non-Windows platform.
+ */
+ tor_socket_t read_fd;
+ /** Socket to use when alerting the main thread. */
+ tor_socket_t write_fd;
+ /** Function to alert the main thread */
+ int (*alert_fn)(tor_socket_t write_fd);
+ /** Function to make the main thread no longer alerted. */
+ int (*drain_fn)(tor_socket_t read_fd);
+} alert_sockets_t;
+
+/* Flags to disable one or more alert_sockets backends. */
+#define ASOCKS_NOEVENTFD2 (1u<<0)
+#define ASOCKS_NOEVENTFD (1u<<1)
+#define ASOCKS_NOPIPE2 (1u<<2)
+#define ASOCKS_NOPIPE (1u<<3)
+#define ASOCKS_NOSOCKETPAIR (1u<<4)
+
+int alert_sockets_create(alert_sockets_t *socks_out, uint32_t flags);
+void alert_sockets_close(alert_sockets_t *socks);
+
+#endif
diff --git a/src/lib/net/buffers_net.c b/src/lib/net/buffers_net.c
new file mode 100644
index 0000000000..edc9954f22
--- /dev/null
+++ b/src/lib/net/buffers_net.c
@@ -0,0 +1,197 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define BUFFERS_PRIVATE
+#include "lib/net/buffers_net.h"
+#include "lib/container/buffers.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/net/nettypes.h"
+
+#ifdef _WIN32
+#include <winsock2.h>
+#endif
+
+#include <stdlib.h>
+
+#ifdef PARANOIA
+/** Helper: If PARANOIA is defined, assert that the buffer in local variable
+ * <b>buf</b> is well-formed. */
+#define check() STMT_BEGIN buf_assert_ok(buf); STMT_END
+#else
+#define check() STMT_NIL
+#endif /* defined(PARANOIA) */
+
+/** Read up to <b>at_most</b> bytes from the socket <b>fd</b> into
+ * <b>chunk</b> (which must be on <b>buf</b>). If we get an EOF, set
+ * *<b>reached_eof</b> to 1. Return -1 on error, 0 on eof or blocking,
+ * and the number of bytes read otherwise. */
+static inline int
+read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most,
+ int *reached_eof, int *socket_error)
+{
+ ssize_t read_result;
+ if (at_most > CHUNK_REMAINING_CAPACITY(chunk))
+ at_most = CHUNK_REMAINING_CAPACITY(chunk);
+ read_result = tor_socket_recv(fd, CHUNK_WRITE_PTR(chunk), at_most, 0);
+
+ if (read_result < 0) {
+ int e = tor_socket_errno(fd);
+ if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */
+#ifdef _WIN32
+ if (e == WSAENOBUFS)
+ log_warn(LD_NET,"recv() failed: WSAENOBUFS. Not enough ram?");
+#endif
+ *socket_error = e;
+ return -1;
+ }
+ return 0; /* would block. */
+ } else if (read_result == 0) {
+ log_debug(LD_NET,"Encountered eof on fd %d", (int)fd);
+ *reached_eof = 1;
+ return 0;
+ } else { /* actually got bytes. */
+ buf->datalen += read_result;
+ chunk->datalen += read_result;
+ log_debug(LD_NET,"Read %ld bytes. %d on inbuf.", (long)read_result,
+ (int)buf->datalen);
+ tor_assert(read_result < INT_MAX);
+ return (int)read_result;
+ }
+}
+
+/** Read from socket <b>s</b>, writing onto end of <b>buf</b>. Read at most
+ * <b>at_most</b> bytes, growing the buffer as necessary. If recv() returns 0
+ * (because of EOF), set *<b>reached_eof</b> to 1 and return 0. Return -1 on
+ * error; else return the number of bytes read.
+ */
+/* XXXX indicate "read blocked" somehow? */
+int
+buf_read_from_socket(buf_t *buf, tor_socket_t s, size_t at_most,
+ int *reached_eof,
+ int *socket_error)
+{
+ /* XXXX It's stupid to overload the return values for these functions:
+ * "error status" and "number of bytes read" are not mutually exclusive.
+ */
+ int r = 0;
+ size_t total_read = 0;
+
+ check();
+ tor_assert(reached_eof);
+ tor_assert(SOCKET_OK(s));
+
+ if (BUG(buf->datalen >= INT_MAX))
+ return -1;
+ if (BUG(buf->datalen >= INT_MAX - at_most))
+ return -1;
+
+ while (at_most > total_read) {
+ size_t readlen = at_most - total_read;
+ chunk_t *chunk;
+ if (!buf->tail || CHUNK_REMAINING_CAPACITY(buf->tail) < MIN_READ_LEN) {
+ chunk = buf_add_chunk_with_capacity(buf, at_most, 1);
+ if (readlen > chunk->memlen)
+ readlen = chunk->memlen;
+ } else {
+ size_t cap = CHUNK_REMAINING_CAPACITY(buf->tail);
+ chunk = buf->tail;
+ if (cap < readlen)
+ readlen = cap;
+ }
+
+ r = read_to_chunk(buf, chunk, s, readlen, reached_eof, socket_error);
+ check();
+ if (r < 0)
+ return r; /* Error */
+ tor_assert(total_read+r < INT_MAX);
+ total_read += r;
+ if ((size_t)r < readlen) { /* eof, block, or no more to read. */
+ break;
+ }
+ }
+ return (int)total_read;
+}
+
+/** Helper for buf_flush_to_socket(): try to write <b>sz</b> bytes from chunk
+ * <b>chunk</b> of buffer <b>buf</b> onto socket <b>s</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.
+ */
+static inline int
+flush_chunk(tor_socket_t s, buf_t *buf, chunk_t *chunk, size_t sz,
+ size_t *buf_flushlen)
+{
+ ssize_t write_result;
+
+ if (sz > chunk->datalen)
+ sz = chunk->datalen;
+ write_result = tor_socket_send(s, chunk->data, sz, 0);
+
+ if (write_result < 0) {
+ int e = tor_socket_errno(s);
+ if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */
+#ifdef _WIN32
+ if (e == WSAENOBUFS)
+ log_warn(LD_NET,"write() failed: WSAENOBUFS. Not enough ram?");
+#endif
+ return -1;
+ }
+ log_debug(LD_NET,"write() would block, returning.");
+ return 0;
+ } else {
+ *buf_flushlen -= write_result;
+ buf_drain(buf, write_result);
+ tor_assert(write_result < INT_MAX);
+ return (int)write_result;
+ }
+}
+
+/** Write data from <b>buf</b> to the socket <b>s</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
+ * from the buffer. Return the number of bytes written on success,
+ * -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)
+{
+ /* 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(s));
+ if (BUG(*buf_flushlen > buf->datalen)) {
+ *buf_flushlen = buf->datalen;
+ }
+ if (BUG(sz > *buf_flushlen)) {
+ sz = *buf_flushlen;
+ }
+
+ check();
+ while (sz) {
+ size_t flushlen0;
+ tor_assert(buf->head);
+ if (buf->head->datalen >= sz)
+ flushlen0 = sz;
+ else
+ flushlen0 = buf->head->datalen;
+
+ r = flush_chunk(s, buf, buf->head, flushlen0, buf_flushlen);
+ check();
+ if (r < 0)
+ return r;
+ flushed += r;
+ sz -= r;
+ if (r == 0 || (size_t)r < flushlen0) /* can't flush any more now. */
+ break;
+ }
+ tor_assert(flushed < INT_MAX);
+ return (int)flushed;
+}
diff --git a/src/lib/net/buffers_net.h b/src/lib/net/buffers_net.h
new file mode 100644
index 0000000000..417f6f9413
--- /dev/null
+++ b/src/lib/net/buffers_net.h
@@ -0,0 +1,27 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file buffers_net.h
+ *
+ * \brief Header file for buffers_net.c.
+ **/
+
+#ifndef TOR_BUFFERS_NET_H
+#define TOR_BUFFERS_NET_H
+
+#include <stddef.h>
+#include "lib/net/socket.h"
+
+struct buf_t;
+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);
+
+#endif /* !defined(TOR_BUFFERS_H) */
diff --git a/src/lib/net/gethostname.c b/src/lib/net/gethostname.c
new file mode 100644
index 0000000000..b6cc9b8e5f
--- /dev/null
+++ b/src/lib/net/gethostname.c
@@ -0,0 +1,25 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "lib/net/gethostname.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef _WIN32
+#include <winsock2.h>
+#endif
+
+/** Get name of current host and write it to <b>name</b> array, whose
+ * length is specified by <b>namelen</b> argument. Return 0 upon
+ * successful completion; otherwise return return -1. (Currently,
+ * this function is merely a mockable wrapper for POSIX gethostname().)
+ */
+MOCK_IMPL(int,
+tor_gethostname,(char *name, size_t namelen))
+{
+ return gethostname(name,namelen);
+}
diff --git a/src/lib/net/gethostname.h b/src/lib/net/gethostname.h
new file mode 100644
index 0000000000..d83c5fe096
--- /dev/null
+++ b/src/lib/net/gethostname.h
@@ -0,0 +1,14 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_GETHOSTNAME_H
+#define TOR_GETHOSTNAME_H
+
+#include "lib/testsupport/testsupport.h"
+#include <stddef.h>
+
+MOCK_DECL(int,tor_gethostname,(char *name, size_t namelen));
+
+#endif
diff --git a/src/lib/net/include.am b/src/lib/net/include.am
new file mode 100644
index 0000000000..6fda173614
--- /dev/null
+++ b/src/lib/net/include.am
@@ -0,0 +1,33 @@
+
+noinst_LIBRARIES += src/lib/libtor-net.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-net-testing.a
+endif
+
+src_lib_libtor_net_a_SOURCES = \
+ src/lib/net/address.c \
+ src/lib/net/alertsock.c \
+ src/lib/net/buffers_net.c \
+ src/lib/net/gethostname.c \
+ src/lib/net/ipv4.c \
+ src/lib/net/ipv6.c \
+ src/lib/net/resolve.c \
+ src/lib/net/socket.c
+
+src_lib_libtor_net_testing_a_SOURCES = \
+ $(src_lib_libtor_net_a_SOURCES)
+src_lib_libtor_net_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_net_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/net/address.h \
+ src/lib/net/alertsock.h \
+ src/lib/net/buffers_net.h \
+ src/lib/net/gethostname.h \
+ src/lib/net/ipv4.h \
+ src/lib/net/ipv6.h \
+ src/lib/net/nettypes.h \
+ src/lib/net/resolve.h \
+ src/lib/net/socket.h \
+ src/lib/net/socks5_status.h
diff --git a/src/lib/net/ipv4.c b/src/lib/net/ipv4.c
new file mode 100644
index 0000000000..18e69761e2
--- /dev/null
+++ b/src/lib/net/ipv4.c
@@ -0,0 +1,52 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "lib/cc/torint.h"
+#include "lib/net/ipv4.h"
+#include "lib/string/printf.h"
+#include "lib/string/scanf.h"
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef _WIN32
+#include <winsock2.h>
+#endif
+
+/** Set *addr to the IP address (in dotted-quad notation) stored in *str.
+ * Return 1 on success, 0 if *str is badly formatted.
+ * (Like inet_aton(str,addr), but works on Windows and Solaris.)
+ */
+int
+tor_inet_aton(const char *str, struct in_addr* addr)
+{
+ unsigned a,b,c,d;
+ char more;
+ if (tor_sscanf(str, "%3u.%3u.%3u.%3u%c", &a,&b,&c,&d,&more) != 4)
+ return 0;
+ if (a > 255) return 0;
+ if (b > 255) return 0;
+ if (c > 255) return 0;
+ if (d > 255) return 0;
+ addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d);
+ return 1;
+}
+
+/** Given an IPv4 in_addr struct *<b>in</b> (in network order, as usual),
+ * write it as a string into the <b>buf_len</b>-byte buffer in
+ * <b>buf</b>. Returns a non-negative integer on success.
+ * Returns -1 on failure.
+ */
+int
+tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len)
+{
+ uint32_t a = ntohl(in->s_addr);
+ return tor_snprintf(buf, buf_len, "%d.%d.%d.%d",
+ (int)(uint8_t)((a>>24)&0xff),
+ (int)(uint8_t)((a>>16)&0xff),
+ (int)(uint8_t)((a>>8 )&0xff),
+ (int)(uint8_t)((a )&0xff));
+}
diff --git a/src/lib/net/ipv4.h b/src/lib/net/ipv4.h
new file mode 100644
index 0000000000..1ccc729970
--- /dev/null
+++ b/src/lib/net/ipv4.h
@@ -0,0 +1,17 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_IPV4_H
+#define TOR_IPV4_H
+
+#include <stddef.h>
+
+struct in_addr;
+int tor_inet_aton(const char *str, struct in_addr *addr);
+/** Length of a buffer to allocate to hold the results of tor_inet_ntoa.*/
+#define INET_NTOA_BUF_LEN 16
+int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len);
+
+#endif
diff --git a/src/lib/net/ipv6.c b/src/lib/net/ipv6.c
new file mode 100644
index 0000000000..35d7ddb901
--- /dev/null
+++ b/src/lib/net/ipv6.c
@@ -0,0 +1,221 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "lib/net/ipv6.h"
+#include "lib/net/ipv4.h"
+#include "lib/string/util_string.h"
+#include "lib/string/compat_string.h"
+#include "lib/string/compat_ctype.h"
+#include "lib/string/printf.h"
+#include "lib/string/scanf.h"
+#include "lib/log/util_bug.h"
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+/** Given <b>af</b>==AF_INET and <b>src</b> a struct in_addr, or
+ * <b>af</b>==AF_INET6 and <b>src</b> a struct in6_addr, try to format the
+ * address and store it in the <b>len</b>-byte buffer <b>dst</b>. Returns
+ * <b>dst</b> on success, NULL on failure.
+ *
+ * (Like inet_ntop(af,src,dst,len), but works on platforms that don't have it:
+ * Tor sometimes needs to format ipv6 addresses even on platforms without ipv6
+ * support.) */
+const char *
+tor_inet_ntop(int af, const void *src, char *dst, size_t len)
+{
+ if (af == AF_INET) {
+ if (tor_inet_ntoa(src, dst, len) < 0)
+ return NULL;
+ else
+ return dst;
+ } else if (af == AF_INET6) {
+ const struct in6_addr *addr = src;
+ char buf[64], *cp;
+ int longestGapLen = 0, longestGapPos = -1, i,
+ curGapPos = -1, curGapLen = 0;
+ uint16_t words[8];
+ for (i = 0; i < 8; ++i) {
+ words[i] = (((uint16_t)addr->s6_addr[2*i])<<8) + addr->s6_addr[2*i+1];
+ }
+ if (words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
+ words[4] == 0 && ((words[5] == 0 && words[6] && words[7]) ||
+ (words[5] == 0xffff))) {
+ /* This is an IPv4 address. */
+ if (words[5] == 0) {
+ tor_snprintf(buf, sizeof(buf), "::%d.%d.%d.%d",
+ addr->s6_addr[12], addr->s6_addr[13],
+ addr->s6_addr[14], addr->s6_addr[15]);
+ } else {
+ tor_snprintf(buf, sizeof(buf), "::%x:%d.%d.%d.%d", words[5],
+ addr->s6_addr[12], addr->s6_addr[13],
+ addr->s6_addr[14], addr->s6_addr[15]);
+ }
+ if ((strlen(buf) + 1) > len) /* +1 for \0 */
+ return NULL;
+ strlcpy(dst, buf, len);
+ return dst;
+ }
+ i = 0;
+ while (i < 8) {
+ if (words[i] == 0) {
+ curGapPos = i++;
+ curGapLen = 1;
+ while (i<8 && words[i] == 0) {
+ ++i; ++curGapLen;
+ }
+ if (curGapLen > longestGapLen) {
+ longestGapPos = curGapPos;
+ longestGapLen = curGapLen;
+ }
+ } else {
+ ++i;
+ }
+ }
+ if (longestGapLen<=1)
+ longestGapPos = -1;
+
+ cp = buf;
+ for (i = 0; i < 8; ++i) {
+ if (words[i] == 0 && longestGapPos == i) {
+ if (i == 0)
+ *cp++ = ':';
+ *cp++ = ':';
+ while (i < 8 && words[i] == 0)
+ ++i;
+ --i; /* to compensate for loop increment. */
+ } else {
+ tor_snprintf(cp, sizeof(buf)-(cp-buf), "%x", (unsigned)words[i]);
+ cp += strlen(cp);
+ if (i != 7)
+ *cp++ = ':';
+ }
+ }
+ *cp = '\0';
+ if ((strlen(buf) + 1) > len) /* +1 for \0 */
+ return NULL;
+ strlcpy(dst, buf, len);
+ return dst;
+ } else {
+ return NULL;
+ }
+}
+
+/** Given <b>af</b>==AF_INET or <b>af</b>==AF_INET6, and a string <b>src</b>
+ * encoding an IPv4 address or IPv6 address correspondingly, try to parse the
+ * address and store the result in <b>dst</b> (which must have space for a
+ * struct in_addr or a struct in6_addr, as appropriate). Return 1 on success,
+ * 0 on a bad parse, and -1 on a bad <b>af</b>.
+ *
+ * (Like inet_pton(af,src,dst) but works on platforms that don't have it: Tor
+ * sometimes needs to format ipv6 addresses even on platforms without ipv6
+ * support.) */
+int
+tor_inet_pton(int af, const char *src, void *dst)
+{
+ if (af == AF_INET) {
+ return tor_inet_aton(src, dst);
+ } else if (af == AF_INET6) {
+ struct in6_addr *out = dst;
+ uint16_t words[8];
+ int gapPos = -1, i, setWords=0;
+ const char *dot = strchr(src, '.');
+ const char *eow; /* end of words. */
+ memset(words, 0xf8, sizeof(words));
+ if (dot == src)
+ return 0;
+ else if (!dot)
+ eow = src+strlen(src);
+ else {
+ unsigned byte1,byte2,byte3,byte4;
+ char more;
+ for (eow = dot-1; eow > src && TOR_ISDIGIT(*eow); --eow)
+ ;
+ if (*eow != ':')
+ return 0;
+ ++eow;
+
+ /* We use "scanf" because some platform inet_aton()s are too lax
+ * about IPv4 addresses of the form "1.2.3" */
+ if (tor_sscanf(eow, "%3u.%3u.%3u.%3u%c",
+ &byte1,&byte2,&byte3,&byte4,&more) != 4)
+ return 0;
+
+ if (byte1 > 255 || byte2 > 255 || byte3 > 255 || byte4 > 255)
+ return 0;
+
+ words[6] = (byte1<<8) | byte2;
+ words[7] = (byte3<<8) | byte4;
+ setWords += 2;
+ }
+
+ i = 0;
+ while (src < eow) {
+ if (i > 7)
+ return 0;
+ if (TOR_ISXDIGIT(*src)) {
+ char *next;
+ ssize_t len;
+ long r = strtol(src, &next, 16);
+ if (next == NULL || next == src) {
+ /* The 'next == src' error case can happen on versions of openbsd
+ * which treat "0xfoo" as an error, rather than as "0" followed by
+ * "xfoo". */
+ return 0;
+ }
+
+ len = *next == '\0' ? eow - src : next - src;
+ if (len > 4)
+ return 0;
+ if (len > 1 && !TOR_ISXDIGIT(src[1]))
+ return 0; /* 0x is not valid */
+
+ tor_assert(r >= 0);
+ tor_assert(r < 65536);
+ words[i++] = (uint16_t)r;
+ setWords++;
+ src = next;
+ if (*src != ':' && src != eow)
+ return 0;
+ ++src;
+ } else if (*src == ':' && i > 0 && gapPos == -1) {
+ gapPos = i;
+ ++src;
+ } else if (*src == ':' && i == 0 && src+1 < eow && src[1] == ':' &&
+ gapPos == -1) {
+ gapPos = i;
+ src += 2;
+ } else {
+ return 0;
+ }
+ }
+
+ if (setWords > 8 ||
+ (setWords == 8 && gapPos != -1) ||
+ (setWords < 8 && gapPos == -1))
+ return 0;
+
+ if (gapPos >= 0) {
+ int nToMove = setWords - (dot ? 2 : 0) - gapPos;
+ int gapLen = 8 - setWords;
+ tor_assert(nToMove >= 0);
+ memmove(&words[gapPos+gapLen], &words[gapPos],
+ sizeof(uint16_t)*nToMove);
+ memset(&words[gapPos], 0, sizeof(uint16_t)*gapLen);
+ }
+ for (i = 0; i < 8; ++i) {
+ out->s6_addr[2*i ] = words[i] >> 8;
+ out->s6_addr[2*i+1] = words[i] & 0xff;
+ }
+
+ return 1;
+ } else {
+ return -1;
+ }
+}
diff --git a/src/lib/net/ipv6.h b/src/lib/net/ipv6.h
new file mode 100644
index 0000000000..0a12e046ac
--- /dev/null
+++ b/src/lib/net/ipv6.h
@@ -0,0 +1,86 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_IPV6_H
+#define TOR_IPV6_H
+
+#include "orconfig.h"
+#include <stddef.h>
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+#endif
+#include "lib/cc/torint.h"
+
+/** Implementation of struct in6_addr for platforms that do not have it.
+ * Generally, these platforms are ones without IPv6 support, but we want to
+ * have a working in6_addr there anyway, so we can use it to parse IPv6
+ * addresses. */
+#if !defined(HAVE_STRUCT_IN6_ADDR)
+struct in6_addr
+{
+ union {
+ uint8_t u6_addr8[16];
+ uint16_t u6_addr16[8];
+ uint32_t u6_addr32[4];
+ } in6_u;
+#define s6_addr in6_u.u6_addr8
+#define s6_addr16 in6_u.u6_addr16
+#define s6_addr32 in6_u.u6_addr32
+};
+#endif /* !defined(HAVE_STRUCT_IN6_ADDR) */
+
+/** @{ */
+/** Many BSD variants seem not to define these. */
+#if defined(__APPLE__) || defined(__darwin__) || \
+ defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#ifndef s6_addr16
+#define s6_addr16 __u6_addr.__u6_addr16
+#endif
+#ifndef s6_addr32
+#define s6_addr32 __u6_addr.__u6_addr32
+#endif
+#endif /* defined(__APPLE__) || defined(__darwin__) || ... */
+/** @} */
+
+#ifndef HAVE_SA_FAMILY_T
+typedef uint16_t sa_family_t;
+#endif
+
+/** @{ */
+/** Apparently, MS and Solaris don't define s6_addr16 or s6_addr32; these
+ * macros get you a pointer to s6_addr32 or local equivalent. */
+#ifdef HAVE_STRUCT_IN6_ADDR_S6_ADDR32
+#define S6_ADDR32(x) ((uint32_t*)(x).s6_addr32)
+#else
+#define S6_ADDR32(x) ((uint32_t*)((char*)&(x).s6_addr))
+#endif
+#ifdef HAVE_STRUCT_IN6_ADDR_S6_ADDR16
+#define S6_ADDR16(x) ((uint16_t*)(x).s6_addr16)
+#else
+#define S6_ADDR16(x) ((uint16_t*)((char*)&(x).s6_addr))
+#endif
+/** @} */
+
+/** Implementation of struct sockaddr_in6 on platforms that do not have
+ * it. See notes on struct in6_addr. */
+#if !defined(HAVE_STRUCT_SOCKADDR_IN6)
+struct sockaddr_in6 {
+ sa_family_t sin6_family;
+ uint16_t sin6_port;
+ // uint32_t sin6_flowinfo;
+ struct in6_addr sin6_addr;
+ // uint32_t sin6_scope_id;
+};
+#endif /* !defined(HAVE_STRUCT_SOCKADDR_IN6) */
+
+const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len);
+int tor_inet_pton(int af, const char *src, void *dst);
+
+#endif
diff --git a/src/lib/net/nettypes.h b/src/lib/net/nettypes.h
new file mode 100644
index 0000000000..f212374368
--- /dev/null
+++ b/src/lib/net/nettypes.h
@@ -0,0 +1,39 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_NET_TYPES_H
+#define TOR_NET_TYPES_H
+
+#include "orconfig.h"
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#if (SIZEOF_SOCKLEN_T == 0)
+typedef int socklen_t;
+#endif
+
+#ifdef _WIN32
+/* XXX Actually, this should arguably be SOCKET; we use intptr_t here so that
+ * any inadvertent checks for the socket being <= 0 or > 0 will probably
+ * still work. */
+#define tor_socket_t intptr_t
+#define TOR_SOCKET_T_FORMAT "%"PRIuPTR
+#define SOCKET_OK(s) ((SOCKET)(s) != INVALID_SOCKET)
+#define TOR_INVALID_SOCKET INVALID_SOCKET
+#else /* !(defined(_WIN32)) */
+/** Type used for a network socket. */
+#define tor_socket_t int
+#define TOR_SOCKET_T_FORMAT "%d"
+/** Macro: true iff 's' is a possible value for a valid initialized socket. */
+#define SOCKET_OK(s) ((s) >= 0)
+/** Error/uninitialized value for a tor_socket_t. */
+#define TOR_INVALID_SOCKET (-1)
+#endif /* defined(_WIN32) */
+
+#endif
diff --git a/src/lib/net/resolve.c b/src/lib/net/resolve.c
new file mode 100644
index 0000000000..cbe368ccfb
--- /dev/null
+++ b/src/lib/net/resolve.c
@@ -0,0 +1,236 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "lib/net/resolve.h"
+#include "lib/net/address.h"
+#include "lib/malloc/util_malloc.h"
+
+#include "siphash.h"
+#include "ht.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#include <string.h>
+
+/** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
+ * *<b>addr</b> to the proper IP address, in host byte order. Returns 0
+ * on success, -1 on failure; 1 on transient failure.
+ *
+ * (This function exists because standard windows gethostbyname
+ * doesn't treat raw IP addresses properly.)
+ */
+
+MOCK_IMPL(int,
+tor_lookup_hostname,(const char *name, uint32_t *addr))
+{
+ tor_addr_t myaddr;
+ int ret;
+
+ if ((ret = tor_addr_lookup(name, AF_INET, &myaddr)))
+ return ret;
+
+ if (tor_addr_family(&myaddr) == AF_INET) {
+ *addr = tor_addr_to_ipv4h(&myaddr);
+ return ret;
+ }
+
+ return -1;
+}
+
+#ifdef USE_SANDBOX_GETADDRINFO
+/** True if we should only return cached values */
+static int sandbox_getaddrinfo_is_active = 0;
+
+/** Cache entry for getaddrinfo results; used when sandboxing is implemented
+ * so that we can consult the cache when the sandbox prevents us from doing
+ * getaddrinfo.
+ *
+ * We support only a limited range of getaddrinfo calls, where servname is null
+ * and hints contains only socktype=SOCK_STREAM, family in INET,INET6,UNSPEC.
+ */
+typedef struct cached_getaddrinfo_item_t {
+ HT_ENTRY(cached_getaddrinfo_item_t) node;
+ char *name;
+ int family;
+ /** set if no error; otherwise NULL */
+ struct addrinfo *res;
+ /** 0 for no error; otherwise an EAI_* value */
+ int err;
+} cached_getaddrinfo_item_t;
+
+static unsigned
+cached_getaddrinfo_item_hash(const cached_getaddrinfo_item_t *item)
+{
+ return (unsigned)siphash24g(item->name, strlen(item->name)) + item->family;
+}
+
+static unsigned
+cached_getaddrinfo_items_eq(const cached_getaddrinfo_item_t *a,
+ const cached_getaddrinfo_item_t *b)
+{
+ return (a->family == b->family) && 0 == strcmp(a->name, b->name);
+}
+
+#define cached_getaddrinfo_item_free(item) \
+ FREE_AND_NULL(cached_getaddrinfo_item_t, \
+ cached_getaddrinfo_item_free_, (item))
+
+static void
+cached_getaddrinfo_item_free_(cached_getaddrinfo_item_t *item)
+{
+ if (item == NULL)
+ return;
+
+ tor_free(item->name);
+ if (item->res)
+ freeaddrinfo(item->res);
+ tor_free(item);
+}
+
+static HT_HEAD(getaddrinfo_cache, cached_getaddrinfo_item_t)
+ getaddrinfo_cache = HT_INITIALIZER();
+
+HT_PROTOTYPE(getaddrinfo_cache, cached_getaddrinfo_item_t, node,
+ cached_getaddrinfo_item_hash,
+ cached_getaddrinfo_items_eq)
+HT_GENERATE2(getaddrinfo_cache, cached_getaddrinfo_item_t, node,
+ cached_getaddrinfo_item_hash,
+ cached_getaddrinfo_items_eq,
+ 0.6, tor_reallocarray_, tor_free_)
+
+/** If true, don't try to cache getaddrinfo results. */
+static int sandbox_getaddrinfo_cache_disabled = 0;
+
+/** Tell the sandbox layer not to try to cache getaddrinfo results. Used as in
+ * tor-resolve, when we have no intention of initializing crypto or of
+ * installing the sandbox.*/
+void
+sandbox_disable_getaddrinfo_cache(void)
+{
+ sandbox_getaddrinfo_cache_disabled = 1;
+}
+
+void
+tor_freeaddrinfo(struct addrinfo *ai)
+{
+ if (sandbox_getaddrinfo_cache_disabled)
+ freeaddrinfo(ai);
+}
+
+int
+tor_getaddrinfo(const char *name, const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **res)
+{
+ int err;
+ struct cached_getaddrinfo_item_t search, *item;
+
+ if (sandbox_getaddrinfo_cache_disabled) {
+ return getaddrinfo(name, NULL, hints, res);
+ }
+
+ if (servname != NULL) {
+ log_warn(LD_BUG, "called with non-NULL servname");
+ return EAI_NONAME;
+ }
+ if (name == NULL) {
+ log_warn(LD_BUG, "called with NULL name");
+ return EAI_NONAME;
+ }
+
+ *res = NULL;
+
+ memset(&search, 0, sizeof(search));
+ search.name = (char *) name;
+ search.family = hints ? hints->ai_family : AF_UNSPEC;
+ item = HT_FIND(getaddrinfo_cache, &getaddrinfo_cache, &search);
+
+ if (! sandbox_getaddrinfo_is_active) {
+ /* If the sandbox is not turned on yet, then getaddrinfo and store the
+ result. */
+
+ err = getaddrinfo(name, NULL, hints, res);
+ log_info(LD_NET,"(Sandbox) getaddrinfo %s.", err ? "failed" : "succeeded");
+
+ if (! item) {
+ item = tor_malloc_zero(sizeof(*item));
+ item->name = tor_strdup(name);
+ item->family = hints ? hints->ai_family : AF_UNSPEC;
+ HT_INSERT(getaddrinfo_cache, &getaddrinfo_cache, item);
+ }
+
+ if (item->res) {
+ freeaddrinfo(item->res);
+ item->res = NULL;
+ }
+ item->res = *res;
+ item->err = err;
+ return err;
+ }
+
+ /* Otherwise, the sandbox is on. If we have an item, yield its cached
+ result. */
+ if (item) {
+ *res = item->res;
+ return item->err;
+ }
+
+ /* getting here means something went wrong */
+ log_err(LD_BUG,"(Sandbox) failed to get address %s!", name);
+ return EAI_NONAME;
+}
+
+int
+tor_add_addrinfo(const char *name)
+{
+ struct addrinfo *res;
+ struct addrinfo hints;
+ int i;
+ static const int families[] = { AF_INET, AF_INET6, AF_UNSPEC };
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_STREAM;
+ for (i = 0; i < 3; ++i) {
+ hints.ai_family = families[i];
+
+ res = NULL;
+ (void) tor_getaddrinfo(name, NULL, &hints, &res);
+ if (res)
+ tor_freeaddrinfo(res);
+ }
+
+ return 0;
+}
+
+void
+tor_free_getaddrinfo_cache(void)
+{
+ cached_getaddrinfo_item_t **next, **item, *this;
+
+ for (item = HT_START(getaddrinfo_cache, &getaddrinfo_cache);
+ item;
+ item = next) {
+ this = *item;
+ next = HT_NEXT_RMV(getaddrinfo_cache, &getaddrinfo_cache, item);
+ cached_getaddrinfo_item_free(this);
+ }
+
+ HT_CLEAR(getaddrinfo_cache, &getaddrinfo_cache);
+}
+
+void
+tor_make_getaddrinfo_cache_active(void)
+{
+ sandbox_getaddrinfo_is_active = 1;
+}
+#endif
diff --git a/src/lib/net/resolve.h b/src/lib/net/resolve.h
new file mode 100644
index 0000000000..f2280ae7e8
--- /dev/null
+++ b/src/lib/net/resolve.h
@@ -0,0 +1,47 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_RESOLVE_H
+#define TOR_RESOLVE_H
+
+#include "orconfig.h"
+#include "lib/cc/torint.h"
+#include "lib/testsupport/testsupport.h"
+#ifdef _WIN32
+#include <winsock2.h>
+#endif
+
+#if defined(HAVE_SECCOMP_H) && defined(__linux__)
+#define USE_SANDBOX_GETADDRINFO
+#endif
+
+MOCK_DECL(int,tor_lookup_hostname,(const char *name, uint32_t *addr));
+
+struct addrinfo;
+#ifdef USE_SANDBOX_GETADDRINFO
+/** Pre-calls getaddrinfo in order to pre-record result. */
+int tor_add_addrinfo(const char *addr);
+
+struct addrinfo;
+/** Replacement for getaddrinfo(), using pre-recorded results. */
+int tor_getaddrinfo(const char *name, const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **res);
+void tor_freeaddrinfo(struct addrinfo *addrinfo);
+void tor_free_getaddrinfo_cache(void);
+void tor_make_getaddrinfo_cache_active(void);
+#else /* !(defined(USE_SANDBOX_GETADDRINFO)) */
+#define tor_getaddrinfo(name, servname, hints, res) \
+ getaddrinfo((name),(servname), (hints),(res))
+#define tor_add_addrinfo(name) \
+ ((void)(name))
+#define tor_freeaddrinfo(addrinfo) \
+ freeaddrinfo((addrinfo))
+#define tor_free_getaddrinfo_cache()
+#endif /* defined(USE_SANDBOX_GETADDRINFO) */
+
+void sandbox_disable_getaddrinfo_cache(void);
+
+#endif
diff --git a/src/lib/net/socket.c b/src/lib/net/socket.c
new file mode 100644
index 0000000000..dc3d1531ff
--- /dev/null
+++ b/src/lib/net/socket.c
@@ -0,0 +1,824 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define SOCKET_PRIVATE
+#include "lib/net/socket.h"
+#include "lib/net/address.h"
+#include "lib/cc/compat_compiler.h"
+#include "lib/err/torerr.h"
+#include "lib/lock/compat_mutex.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <windows.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include <stddef.h>
+#include <string.h>
+
+/** Called before we make any calls to network-related functions.
+ * (Some operating systems require their network libraries to be
+ * initialized.) */
+int
+network_init(void)
+{
+#ifdef _WIN32
+ /* This silly exercise is necessary before windows will allow
+ * gethostbyname to work. */
+ WSADATA WSAData;
+ int r;
+ r = WSAStartup(0x101,&WSAData);
+ if (r) {
+ log_warn(LD_NET,"Error initializing windows network layer: code was %d",r);
+ return -1;
+ }
+ if (sizeof(SOCKET) != sizeof(tor_socket_t)) {
+ log_warn(LD_BUG,"The tor_socket_t type does not match SOCKET in size; Tor "
+ "might not work. (Sizes are %d and %d respectively.)",
+ (int)sizeof(tor_socket_t), (int)sizeof(SOCKET));
+ }
+ /* WSAData.iMaxSockets might show the max sockets we're allowed to use.
+ * We might use it to complain if we're trying to be a server but have
+ * too few sockets available. */
+#endif /* defined(_WIN32) */
+ return 0;
+}
+
+/* When set_max_file_sockets() is called, update this with the max file
+ * descriptor value so we can use it to check the limit when opening a new
+ * socket. Default value is what Debian sets as the default hard limit. */
+static int max_sockets = 1024;
+
+/** Return the maximum number of allowed sockets. */
+int
+get_max_sockets(void)
+{
+ return max_sockets;
+}
+
+/** Set the maximum number of allowed sockets to <b>n</b> */
+void
+set_max_sockets(int n)
+{
+ max_sockets = n;
+}
+
+#undef DEBUG_SOCKET_COUNTING
+#ifdef DEBUG_SOCKET_COUNTING
+#include "lib/container/bitarray.h"
+
+/** A bitarray of all fds that should be passed to tor_socket_close(). Only
+ * used if DEBUG_SOCKET_COUNTING is defined. */
+static bitarray_t *open_sockets = NULL;
+/** The size of <b>open_sockets</b>, in bits. */
+static int max_socket = -1;
+#endif /* defined(DEBUG_SOCKET_COUNTING) */
+
+/** Count of number of sockets currently open. (Undercounts sockets opened by
+ * eventdns and libevent.) */
+static int n_sockets_open = 0;
+
+/** Mutex to protect open_sockets, max_socket, and n_sockets_open. */
+static tor_mutex_t *socket_accounting_mutex = NULL;
+
+/** Helper: acquire the socket accounting lock. */
+static inline void
+socket_accounting_lock(void)
+{
+ if (PREDICT_UNLIKELY(!socket_accounting_mutex))
+ socket_accounting_mutex = tor_mutex_new();
+ tor_mutex_acquire(socket_accounting_mutex);
+}
+
+/** Helper: release the socket accounting lock. */
+static inline void
+socket_accounting_unlock(void)
+{
+ tor_mutex_release(socket_accounting_mutex);
+}
+
+/** As close(), but guaranteed to work for sockets across platforms (including
+ * Windows, where close()ing a socket doesn't work. Returns 0 on success and
+ * the socket error code on failure. */
+int
+tor_close_socket_simple(tor_socket_t s)
+{
+ int r = 0;
+
+ /* On Windows, you have to call close() on fds returned by open(),
+ * and closesocket() on fds returned by socket(). On Unix, everything
+ * gets close()'d. We abstract this difference by always using
+ * tor_close_socket to close sockets, and always using close() on
+ * files.
+ */
+ #if defined(_WIN32)
+ r = closesocket(s);
+ #else
+ r = close(s);
+ #endif
+
+ if (r != 0) {
+ int err = tor_socket_errno(-1);
+ log_info(LD_NET, "Close returned an error: %s", tor_socket_strerror(err));
+ return err;
+ }
+
+ return r;
+}
+
+/** As tor_close_socket_simple(), but keeps track of the number
+ * of open sockets. Returns 0 on success, -1 on failure. */
+MOCK_IMPL(int,
+tor_close_socket,(tor_socket_t s))
+{
+ int r = tor_close_socket_simple(s);
+
+ socket_accounting_lock();
+#ifdef DEBUG_SOCKET_COUNTING
+ if (s > max_socket || ! bitarray_is_set(open_sockets, s)) {
+ log_warn(LD_BUG, "Closing a socket (%d) that wasn't returned by tor_open_"
+ "socket(), or that was already closed or something.", s);
+ } else {
+ tor_assert(open_sockets && s <= max_socket);
+ bitarray_clear(open_sockets, s);
+ }
+#endif /* defined(DEBUG_SOCKET_COUNTING) */
+ if (r == 0) {
+ --n_sockets_open;
+ } else {
+#ifdef _WIN32
+ if (r != WSAENOTSOCK)
+ --n_sockets_open;
+#else
+ if (r != EBADF)
+ --n_sockets_open; // LCOV_EXCL_LINE -- EIO and EINTR too hard to force.
+#endif /* defined(_WIN32) */
+ r = -1;
+ }
+
+ tor_assert_nonfatal(n_sockets_open >= 0);
+ socket_accounting_unlock();
+ return r;
+}
+
+/** @{ */
+#ifdef DEBUG_SOCKET_COUNTING
+/** Helper: if DEBUG_SOCKET_COUNTING is enabled, remember that <b>s</b> is
+ * now an open socket. */
+static inline void
+mark_socket_open(tor_socket_t s)
+{
+ /* XXXX This bitarray business will NOT work on windows: sockets aren't
+ small ints there. */
+ if (s > max_socket) {
+ if (max_socket == -1) {
+ open_sockets = bitarray_init_zero(s+128);
+ max_socket = s+128;
+ } else {
+ open_sockets = bitarray_expand(open_sockets, max_socket, s+128);
+ max_socket = s+128;
+ }
+ }
+ if (bitarray_is_set(open_sockets, s)) {
+ log_warn(LD_BUG, "I thought that %d was already open, but socket() just "
+ "gave it to me!", s);
+ }
+ bitarray_set(open_sockets, s);
+}
+#else /* !(defined(DEBUG_SOCKET_COUNTING)) */
+#define mark_socket_open(s) ((void) (s))
+#endif /* defined(DEBUG_SOCKET_COUNTING) */
+/** @} */
+
+/** As socket(), but counts the number of open sockets. */
+MOCK_IMPL(tor_socket_t,
+tor_open_socket,(int domain, int type, int protocol))
+{
+ return tor_open_socket_with_extensions(domain, type, protocol, 1, 0);
+}
+
+/** Mockable wrapper for connect(). */
+MOCK_IMPL(tor_socket_t,
+tor_connect_socket,(tor_socket_t sock, const struct sockaddr *address,
+ socklen_t address_len))
+{
+ return connect(sock,address,address_len);
+}
+
+/** As socket(), but creates a nonblocking socket and
+ * counts the number of open sockets. */
+tor_socket_t
+tor_open_socket_nonblocking(int domain, int type, int protocol)
+{
+ return tor_open_socket_with_extensions(domain, type, protocol, 1, 1);
+}
+
+/** As socket(), but counts the number of open sockets and handles
+ * socket creation with either of SOCK_CLOEXEC and SOCK_NONBLOCK specified.
+ * <b>cloexec</b> and <b>nonblock</b> should be either 0 or 1 to indicate
+ * if the corresponding extension should be used.*/
+tor_socket_t
+tor_open_socket_with_extensions(int domain, int type, int protocol,
+ int cloexec, int nonblock)
+{
+ tor_socket_t s;
+
+ /* We are about to create a new file descriptor so make sure we have
+ * enough of them. */
+ if (get_n_open_sockets() >= max_sockets - 1) {
+#ifdef _WIN32
+ WSASetLastError(WSAEMFILE);
+#else
+ errno = EMFILE;
+#endif
+ return TOR_INVALID_SOCKET;
+ }
+
+#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
+ int ext_flags = (cloexec ? SOCK_CLOEXEC : 0) |
+ (nonblock ? SOCK_NONBLOCK : 0);
+ s = socket(domain, type|ext_flags, protocol);
+ if (SOCKET_OK(s))
+ goto socket_ok;
+ /* If we got an error, see if it is EINVAL. EINVAL might indicate that,
+ * even though we were built on a system with SOCK_CLOEXEC and SOCK_NONBLOCK
+ * support, we are running on one without. */
+ if (errno != EINVAL)
+ return s;
+#endif /* defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK) */
+
+ s = socket(domain, type, protocol);
+ if (! SOCKET_OK(s))
+ return s;
+
+#if defined(FD_CLOEXEC)
+ if (cloexec) {
+ if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) {
+ log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
+ tor_close_socket_simple(s);
+ return TOR_INVALID_SOCKET;
+ }
+ }
+#else /* !(defined(FD_CLOEXEC)) */
+ (void)cloexec;
+#endif /* defined(FD_CLOEXEC) */
+
+ if (nonblock) {
+ if (set_socket_nonblocking(s) == -1) {
+ tor_close_socket_simple(s);
+ return TOR_INVALID_SOCKET;
+ }
+ }
+
+ goto socket_ok; /* So that socket_ok will not be unused. */
+
+ socket_ok:
+ tor_take_socket_ownership(s);
+ return s;
+}
+
+/**
+ * For socket accounting: remember that we are the owner of the socket
+ * <b>s</b>. This will prevent us from overallocating sockets, and prevent us
+ * from asserting later when we close the socket <b>s</b>.
+ */
+void
+tor_take_socket_ownership(tor_socket_t s)
+{
+ socket_accounting_lock();
+ ++n_sockets_open;
+ mark_socket_open(s);
+ socket_accounting_unlock();
+}
+
+/** As accept(), but counts the number of open sockets. */
+tor_socket_t
+tor_accept_socket(tor_socket_t sockfd, struct sockaddr *addr, socklen_t *len)
+{
+ return tor_accept_socket_with_extensions(sockfd, addr, len, 1, 0);
+}
+
+/** As accept(), but returns a nonblocking socket and
+ * counts the number of open sockets. */
+tor_socket_t
+tor_accept_socket_nonblocking(tor_socket_t sockfd, struct sockaddr *addr,
+ socklen_t *len)
+{
+ return tor_accept_socket_with_extensions(sockfd, addr, len, 1, 1);
+}
+
+/** As accept(), but counts the number of open sockets and handles
+ * socket creation with either of SOCK_CLOEXEC and SOCK_NONBLOCK specified.
+ * <b>cloexec</b> and <b>nonblock</b> should be either 0 or 1 to indicate
+ * if the corresponding extension should be used.*/
+tor_socket_t
+tor_accept_socket_with_extensions(tor_socket_t sockfd, struct sockaddr *addr,
+ socklen_t *len, int cloexec, int nonblock)
+{
+ tor_socket_t s;
+
+ /* We are about to create a new file descriptor so make sure we have
+ * enough of them. */
+ if (get_n_open_sockets() >= max_sockets - 1) {
+#ifdef _WIN32
+ WSASetLastError(WSAEMFILE);
+#else
+ errno = EMFILE;
+#endif
+ return TOR_INVALID_SOCKET;
+ }
+
+#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) \
+ && defined(SOCK_NONBLOCK)
+ int ext_flags = (cloexec ? SOCK_CLOEXEC : 0) |
+ (nonblock ? SOCK_NONBLOCK : 0);
+ s = accept4(sockfd, addr, len, ext_flags);
+ if (SOCKET_OK(s))
+ goto socket_ok;
+ /* If we got an error, see if it is ENOSYS. ENOSYS indicates that,
+ * even though we were built on a system with accept4 support, we
+ * are running on one without. Also, check for EINVAL, which indicates that
+ * we are missing SOCK_CLOEXEC/SOCK_NONBLOCK support. */
+ if (errno != EINVAL && errno != ENOSYS)
+ return s;
+#endif /* defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) ... */
+
+ s = accept(sockfd, addr, len);
+ if (!SOCKET_OK(s))
+ return s;
+
+#if defined(FD_CLOEXEC)
+ if (cloexec) {
+ if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) {
+ log_warn(LD_NET, "Couldn't set FD_CLOEXEC: %s", strerror(errno));
+ tor_close_socket_simple(s);
+ return TOR_INVALID_SOCKET;
+ }
+ }
+#else /* !(defined(FD_CLOEXEC)) */
+ (void)cloexec;
+#endif /* defined(FD_CLOEXEC) */
+
+ if (nonblock) {
+ if (set_socket_nonblocking(s) == -1) {
+ tor_close_socket_simple(s);
+ return TOR_INVALID_SOCKET;
+ }
+ }
+
+ goto socket_ok; /* So that socket_ok will not be unused. */
+
+ socket_ok:
+ tor_take_socket_ownership(s);
+ return s;
+}
+
+/** Return the number of sockets we currently have opened. */
+int
+get_n_open_sockets(void)
+{
+ int n;
+ socket_accounting_lock();
+ n = n_sockets_open;
+ socket_accounting_unlock();
+ return n;
+}
+
+/**
+ * Allocate a pair of connected sockets. (Like socketpair(family,
+ * type,protocol,fd), but works on systems that don't have
+ * socketpair.)
+ *
+ * Currently, only (AF_UNIX, SOCK_STREAM, 0) sockets are supported.
+ *
+ * Note that on systems without socketpair, this call will fail if
+ * localhost is inaccessible (for example, if the networking
+ * stack is down). And even if it succeeds, the socket pair will not
+ * be able to read while localhost is down later (the socket pair may
+ * even close, depending on OS-specific timeouts).
+ *
+ * Returns 0 on success and -errno on failure; do not rely on the value
+ * of errno or WSAGetLastError().
+ **/
+/* It would be nicer just to set errno, but that won't work for windows. */
+int
+tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
+{
+//don't use win32 socketpairs (they are always bad)
+#if defined(HAVE_SOCKETPAIR) && !defined(_WIN32)
+ int r;
+
+#ifdef SOCK_CLOEXEC
+ r = socketpair(family, type|SOCK_CLOEXEC, protocol, fd);
+ if (r == 0)
+ goto sockets_ok;
+ /* If we got an error, see if it is EINVAL. EINVAL might indicate that,
+ * even though we were built on a system with SOCK_CLOEXEC support, we
+ * are running on one without. */
+ if (errno != EINVAL)
+ return -errno;
+#endif /* defined(SOCK_CLOEXEC) */
+
+ r = socketpair(family, type, protocol, fd);
+ if (r < 0)
+ return -errno;
+
+#if defined(FD_CLOEXEC)
+ if (SOCKET_OK(fd[0])) {
+ r = fcntl(fd[0], F_SETFD, FD_CLOEXEC);
+ if (r == -1) {
+ close(fd[0]);
+ close(fd[1]);
+ return -errno;
+ }
+ }
+ if (SOCKET_OK(fd[1])) {
+ r = fcntl(fd[1], F_SETFD, FD_CLOEXEC);
+ if (r == -1) {
+ close(fd[0]);
+ close(fd[1]);
+ return -errno;
+ }
+ }
+#endif /* defined(FD_CLOEXEC) */
+ goto sockets_ok; /* So that sockets_ok will not be unused. */
+
+ sockets_ok:
+ socket_accounting_lock();
+ if (SOCKET_OK(fd[0])) {
+ ++n_sockets_open;
+ mark_socket_open(fd[0]);
+ }
+ if (SOCKET_OK(fd[1])) {
+ ++n_sockets_open;
+ mark_socket_open(fd[1]);
+ }
+ socket_accounting_unlock();
+
+ return 0;
+#else /* !(defined(HAVE_SOCKETPAIR) && !defined(_WIN32)) */
+ return tor_ersatz_socketpair(family, type, protocol, fd);
+#endif /* defined(HAVE_SOCKETPAIR) && !defined(_WIN32) */
+}
+
+#ifdef NEED_ERSATZ_SOCKETPAIR
+
+static inline socklen_t
+SIZEOF_SOCKADDR(int domain)
+{
+ switch (domain) {
+ case AF_INET:
+ return sizeof(struct sockaddr_in);
+ case AF_INET6:
+ return sizeof(struct sockaddr_in6);
+ default:
+ return 0;
+ }
+}
+
+/**
+ * Helper used to implement socketpair on systems that lack it, by
+ * making a direct connection to localhost.
+ */
+STATIC int
+tor_ersatz_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
+{
+ /* This socketpair does not work when localhost is down. So
+ * it's really not the same thing at all. But it's close enough
+ * for now, and really, when localhost is down sometimes, we
+ * have other problems too.
+ */
+ tor_socket_t listener = TOR_INVALID_SOCKET;
+ tor_socket_t connector = TOR_INVALID_SOCKET;
+ tor_socket_t acceptor = TOR_INVALID_SOCKET;
+ tor_addr_t listen_tor_addr;
+ struct sockaddr_storage connect_addr_ss, listen_addr_ss;
+ struct sockaddr *listen_addr = (struct sockaddr *) &listen_addr_ss;
+ uint16_t listen_port = 0;
+ tor_addr_t connect_tor_addr;
+ uint16_t connect_port = 0;
+ struct sockaddr *connect_addr = (struct sockaddr *) &connect_addr_ss;
+ socklen_t size;
+ int saved_errno = -1;
+ int ersatz_domain = AF_INET;
+
+ memset(&connect_tor_addr, 0, sizeof(connect_tor_addr));
+ memset(&connect_addr_ss, 0, sizeof(connect_addr_ss));
+ memset(&listen_tor_addr, 0, sizeof(listen_tor_addr));
+ memset(&listen_addr_ss, 0, sizeof(listen_addr_ss));
+
+ if (protocol
+#ifdef AF_UNIX
+ || family != AF_UNIX
+#endif
+ ) {
+#ifdef _WIN32
+ return -WSAEAFNOSUPPORT;
+#else
+ return -EAFNOSUPPORT;
+#endif
+ }
+ if (!fd) {
+ return -EINVAL;
+ }
+
+ listener = tor_open_socket(ersatz_domain, type, 0);
+ if (!SOCKET_OK(listener)) {
+ int first_errno = tor_socket_errno(-1);
+ if (first_errno == SOCK_ERRNO(EPROTONOSUPPORT)
+ && ersatz_domain == AF_INET) {
+ /* Assume we're on an IPv6-only system */
+ ersatz_domain = AF_INET6;
+ listener = tor_open_socket(ersatz_domain, type, 0);
+ if (!SOCKET_OK(listener)) {
+ /* Keep the previous behaviour, which was to return the IPv4 error.
+ * (This may be less informative on IPv6-only systems.)
+ * XX/teor - is there a better way to decide which errno to return?
+ * (I doubt we care much either way, once there is an error.)
+ */
+ return -first_errno;
+ }
+ }
+ }
+ /* If there is no 127.0.0.1 or ::1, this will and must fail. Otherwise, we
+ * risk exposing a socketpair on a routable IP address. (Some BSD jails
+ * use a routable address for localhost. Fortunately, they have the real
+ * AF_UNIX socketpair.) */
+ if (ersatz_domain == AF_INET) {
+ tor_addr_from_ipv4h(&listen_tor_addr, INADDR_LOOPBACK);
+ } else {
+ tor_addr_parse(&listen_tor_addr, "[::1]");
+ }
+ tor_assert(tor_addr_is_loopback(&listen_tor_addr));
+ size = tor_addr_to_sockaddr(&listen_tor_addr,
+ 0 /* kernel chooses port. */,
+ listen_addr,
+ sizeof(listen_addr_ss));
+ if (bind(listener, listen_addr, size) == -1)
+ goto tidy_up_and_fail;
+ if (listen(listener, 1) == -1)
+ goto tidy_up_and_fail;
+
+ connector = tor_open_socket(ersatz_domain, type, 0);
+ if (!SOCKET_OK(connector))
+ goto tidy_up_and_fail;
+ /* We want to find out the port number to connect to. */
+ size = sizeof(connect_addr_ss);
+ if (getsockname(listener, connect_addr, &size) == -1)
+ goto tidy_up_and_fail;
+ if (size != SIZEOF_SOCKADDR (connect_addr->sa_family))
+ goto abort_tidy_up_and_fail;
+ if (connect(connector, connect_addr, size) == -1)
+ goto tidy_up_and_fail;
+
+ size = sizeof(listen_addr_ss);
+ acceptor = tor_accept_socket(listener, listen_addr, &size);
+ if (!SOCKET_OK(acceptor))
+ goto tidy_up_and_fail;
+ if (size != SIZEOF_SOCKADDR(listen_addr->sa_family))
+ goto abort_tidy_up_and_fail;
+ /* Now check we are talking to ourself by matching port and host on the
+ two sockets. */
+ if (getsockname(connector, connect_addr, &size) == -1)
+ goto tidy_up_and_fail;
+ /* Set *_tor_addr and *_port to the address and port that was used */
+ tor_addr_from_sockaddr(&listen_tor_addr, listen_addr, &listen_port);
+ tor_addr_from_sockaddr(&connect_tor_addr, connect_addr, &connect_port);
+ if (size != SIZEOF_SOCKADDR (connect_addr->sa_family)
+ || tor_addr_compare(&listen_tor_addr, &connect_tor_addr, CMP_SEMANTIC)
+ || listen_port != connect_port) {
+ goto abort_tidy_up_and_fail;
+ }
+ tor_close_socket(listener);
+ fd[0] = connector;
+ fd[1] = acceptor;
+
+ return 0;
+
+ abort_tidy_up_and_fail:
+#ifdef _WIN32
+ saved_errno = WSAECONNABORTED;
+#else
+ saved_errno = ECONNABORTED; /* I hope this is portable and appropriate. */
+#endif
+ tidy_up_and_fail:
+ if (saved_errno < 0)
+ saved_errno = errno;
+ if (SOCKET_OK(listener))
+ tor_close_socket(listener);
+ if (SOCKET_OK(connector))
+ tor_close_socket(connector);
+ if (SOCKET_OK(acceptor))
+ tor_close_socket(acceptor);
+ return -saved_errno;
+}
+
+#endif /* defined(NEED_ERSATZ_SOCKETPAIR) */
+
+/** Mockable wrapper for getsockname(). */
+MOCK_IMPL(int,
+tor_getsockname,(tor_socket_t sock, struct sockaddr *address,
+ socklen_t *address_len))
+{
+ return getsockname(sock, address, address_len);
+}
+
+/**
+ * Find the local address associated with the socket <b>sock</b>, and
+ * place it in *<b>addr_out</b>. Return 0 on success, -1 on failure.
+ *
+ * (As tor_getsockname, but instead places the result in a tor_addr_t.) */
+int
+tor_addr_from_getsockname(struct tor_addr_t *addr_out, tor_socket_t sock)
+{
+ struct sockaddr_storage ss;
+ socklen_t ss_len = sizeof(ss);
+ memset(&ss, 0, sizeof(ss));
+
+ if (tor_getsockname(sock, (struct sockaddr *) &ss, &ss_len) < 0)
+ return -1;
+
+ return tor_addr_from_sockaddr(addr_out, (struct sockaddr *)&ss, NULL);
+}
+
+/** Turn <b>socket</b> into a nonblocking socket. Return 0 on success, -1
+ * on failure.
+ */
+int
+set_socket_nonblocking(tor_socket_t sock)
+{
+#if defined(_WIN32)
+ unsigned long nonblocking = 1;
+ ioctlsocket(sock, FIONBIO, (unsigned long*) &nonblocking);
+#else
+ int flags;
+
+ flags = fcntl(sock, F_GETFL, 0);
+ if (flags == -1) {
+ log_warn(LD_NET, "Couldn't get file status flags: %s", strerror(errno));
+ return -1;
+ }
+ flags |= O_NONBLOCK;
+ if (fcntl(sock, F_SETFL, flags) == -1) {
+ log_warn(LD_NET, "Couldn't set file status flags: %s", strerror(errno));
+ return -1;
+ }
+#endif /* defined(_WIN32) */
+
+ return 0;
+}
+
+/** Read from <b>sock</b> to <b>buf</b>, until we get <b>count</b> bytes or
+ * reach the end of the file. Return the number of bytes read, or -1 on
+ * error. Only use if fd is a blocking fd. */
+ssize_t
+read_all_from_socket(tor_socket_t sock, char *buf, size_t count)
+{
+ size_t numread = 0;
+ ssize_t result;
+
+ if (count > SIZE_T_CEILING || count > SSIZE_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ while (numread < count) {
+ result = tor_socket_recv(sock, buf+numread, count-numread, 0);
+ if (result<0)
+ return -1;
+ else if (result == 0)
+ break;
+ numread += result;
+ }
+ return (ssize_t)numread;
+}
+
+/** Write <b>count</b> bytes from <b>buf</b> to <b>sock</b>. Return the number
+ * of bytes written, or -1 on error. Only use if fd is a blocking fd. */
+ssize_t
+write_all_to_socket(tor_socket_t fd, const char *buf, size_t count)
+{
+ size_t written = 0;
+ ssize_t result;
+ raw_assert(count < SSIZE_MAX);
+
+ while (written != count) {
+ result = tor_socket_send(fd, buf+written, count-written, 0);
+ if (result<0)
+ return -1;
+ written += result;
+ }
+ return (ssize_t)count;
+}
+
+/**
+ * On Windows, WSAEWOULDBLOCK is not always correct: when you see it,
+ * you need to ask the socket for its actual errno. Also, you need to
+ * get your errors from WSAGetLastError, not errno. (If you supply a
+ * socket of -1, we check WSAGetLastError, but don't correct
+ * WSAEWOULDBLOCKs.)
+ *
+ * The upshot of all of this is that when a socket call fails, you
+ * should call tor_socket_errno <em>at most once</em> on the failing
+ * socket to get the error.
+ */
+#if defined(_WIN32)
+int
+tor_socket_errno(tor_socket_t sock)
+{
+ int optval, optvallen=sizeof(optval);
+ int err = WSAGetLastError();
+ if (err == WSAEWOULDBLOCK && SOCKET_OK(sock)) {
+ if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, &optvallen))
+ return err;
+ if (optval)
+ return optval;
+ }
+ return err;
+}
+#endif /* defined(_WIN32) */
+
+#if defined(_WIN32)
+#define E(code, s) { code, (s " [" #code " ]") }
+struct { int code; const char *msg; } windows_socket_errors[] = {
+ E(WSAEINTR, "Interrupted function call"),
+ E(WSAEACCES, "Permission denied"),
+ E(WSAEFAULT, "Bad address"),
+ E(WSAEINVAL, "Invalid argument"),
+ E(WSAEMFILE, "Too many open files"),
+ E(WSAEWOULDBLOCK, "Resource temporarily unavailable"),
+ E(WSAEINPROGRESS, "Operation now in progress"),
+ E(WSAEALREADY, "Operation already in progress"),
+ E(WSAENOTSOCK, "Socket operation on nonsocket"),
+ E(WSAEDESTADDRREQ, "Destination address required"),
+ E(WSAEMSGSIZE, "Message too long"),
+ E(WSAEPROTOTYPE, "Protocol wrong for socket"),
+ E(WSAENOPROTOOPT, "Bad protocol option"),
+ E(WSAEPROTONOSUPPORT, "Protocol not supported"),
+ E(WSAESOCKTNOSUPPORT, "Socket type not supported"),
+ /* What's the difference between NOTSUPP and NOSUPPORT? :) */
+ E(WSAEOPNOTSUPP, "Operation not supported"),
+ E(WSAEPFNOSUPPORT, "Protocol family not supported"),
+ E(WSAEAFNOSUPPORT, "Address family not supported by protocol family"),
+ E(WSAEADDRINUSE, "Address already in use"),
+ E(WSAEADDRNOTAVAIL, "Cannot assign requested address"),
+ E(WSAENETDOWN, "Network is down"),
+ E(WSAENETUNREACH, "Network is unreachable"),
+ E(WSAENETRESET, "Network dropped connection on reset"),
+ E(WSAECONNABORTED, "Software caused connection abort"),
+ E(WSAECONNRESET, "Connection reset by peer"),
+ E(WSAENOBUFS, "No buffer space available"),
+ E(WSAEISCONN, "Socket is already connected"),
+ E(WSAENOTCONN, "Socket is not connected"),
+ E(WSAESHUTDOWN, "Cannot send after socket shutdown"),
+ E(WSAETIMEDOUT, "Connection timed out"),
+ E(WSAECONNREFUSED, "Connection refused"),
+ E(WSAEHOSTDOWN, "Host is down"),
+ E(WSAEHOSTUNREACH, "No route to host"),
+ E(WSAEPROCLIM, "Too many processes"),
+ /* Yes, some of these start with WSA, not WSAE. No, I don't know why. */
+ E(WSASYSNOTREADY, "Network subsystem is unavailable"),
+ E(WSAVERNOTSUPPORTED, "Winsock.dll out of range"),
+ E(WSANOTINITIALISED, "Successful WSAStartup not yet performed"),
+ E(WSAEDISCON, "Graceful shutdown now in progress"),
+#ifdef WSATYPE_NOT_FOUND
+ E(WSATYPE_NOT_FOUND, "Class type not found"),
+#endif
+ E(WSAHOST_NOT_FOUND, "Host not found"),
+ E(WSATRY_AGAIN, "Nonauthoritative host not found"),
+ E(WSANO_RECOVERY, "This is a nonrecoverable error"),
+ E(WSANO_DATA, "Valid name, no data record of requested type)"),
+
+ /* There are some more error codes whose numeric values are marked
+ * <b>OS dependent</b>. They start with WSA_, apparently for the same
+ * reason that practitioners of some craft traditions deliberately
+ * introduce imperfections into their baskets and rugs "to allow the
+ * evil spirits to escape." If we catch them, then our binaries
+ * might not report consistent results across versions of Windows.
+ * Thus, I'm going to let them all fall through.
+ */
+ { -1, NULL },
+};
+/** There does not seem to be a strerror equivalent for Winsock errors.
+ * Naturally, we have to roll our own.
+ */
+const char *
+tor_socket_strerror(int e)
+{
+ int i;
+ for (i=0; windows_socket_errors[i].code >= 0; ++i) {
+ if (e == windows_socket_errors[i].code)
+ return windows_socket_errors[i].msg;
+ }
+ return strerror(e);
+}
+#endif /* defined(_WIN32) */
diff --git a/src/lib/net/socket.h b/src/lib/net/socket.h
new file mode 100644
index 0000000000..cb0ccbe817
--- /dev/null
+++ b/src/lib/net/socket.h
@@ -0,0 +1,120 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_SOCKET_H
+#define TOR_SOCKET_H
+
+#include "orconfig.h"
+#include "lib/cc/torint.h"
+#include "lib/net/nettypes.h"
+#include "lib/testsupport/testsupport.h"
+
+#include <errno.h>
+
+struct sockaddr;
+
+int tor_close_socket_simple(tor_socket_t s);
+MOCK_DECL(int, tor_close_socket, (tor_socket_t s));
+void tor_take_socket_ownership(tor_socket_t s);
+tor_socket_t tor_open_socket_with_extensions(
+ int domain, int type, int protocol,
+ int cloexec, int nonblock);
+MOCK_DECL(tor_socket_t,tor_open_socket,(int domain, int type, int protocol));
+tor_socket_t tor_open_socket_nonblocking(int domain, int type, int protocol);
+tor_socket_t tor_accept_socket(tor_socket_t sockfd, struct sockaddr *addr,
+ socklen_t *len);
+tor_socket_t tor_accept_socket_nonblocking(tor_socket_t sockfd,
+ struct sockaddr *addr,
+ socklen_t *len);
+tor_socket_t tor_accept_socket_with_extensions(tor_socket_t sockfd,
+ struct sockaddr *addr,
+ socklen_t *len,
+ int cloexec, int nonblock);
+MOCK_DECL(tor_socket_t, tor_connect_socket,(tor_socket_t socket,
+ const struct sockaddr *address,
+ socklen_t address_len));
+int get_n_open_sockets(void);
+
+MOCK_DECL(int,tor_getsockname,(tor_socket_t socket, struct sockaddr *address,
+ socklen_t *address_len));
+struct tor_addr_t;
+int tor_addr_from_getsockname(struct tor_addr_t *addr_out, tor_socket_t sock);
+
+#define tor_socket_send(s, buf, len, flags) send(s, buf, len, flags)
+#define tor_socket_recv(s, buf, len, flags) recv(s, buf, len, flags)
+
+int set_socket_nonblocking(tor_socket_t socket);
+int tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]);
+int network_init(void);
+
+int get_max_sockets(void);
+void set_max_sockets(int);
+
+ssize_t write_all_to_socket(tor_socket_t fd, const char *buf, size_t count);
+ssize_t read_all_from_socket(tor_socket_t fd, char *buf, size_t count);
+
+/* For stupid historical reasons, windows sockets have an independent
+ * set of errnos, and an independent way to get them. Also, you can't
+ * always believe WSAEWOULDBLOCK. Use the macros below to compare
+ * errnos against expected values, and use tor_socket_errno to find
+ * the actual errno after a socket operation fails.
+ */
+#if defined(_WIN32)
+/** Expands to WSA<b>e</b> on Windows, and to <b>e</b> elsewhere. */
+#define SOCK_ERRNO(e) WSA##e
+/** Return true if e is EAGAIN or the local equivalent. */
+#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN || (e) == WSAEWOULDBLOCK)
+/** Return true if e is EINPROGRESS or the local equivalent. */
+#define ERRNO_IS_EINPROGRESS(e) ((e) == WSAEINPROGRESS)
+/** Return true if e is EINPROGRESS or the local equivalent as returned by
+ * a call to connect(). */
+#define ERRNO_IS_CONN_EINPROGRESS(e) \
+ ((e) == WSAEINPROGRESS || (e)== WSAEINVAL || (e) == WSAEWOULDBLOCK)
+/** Return true if e is EAGAIN or another error indicating that a call to
+ * accept() has no pending connections to return. */
+#define ERRNO_IS_ACCEPT_EAGAIN(e) ERRNO_IS_EAGAIN(e)
+/** Return true if e is EMFILE or another error indicating that a call to
+ * accept() has failed because we're out of fds or something. */
+#define ERRNO_IS_RESOURCE_LIMIT(e) \
+ ((e) == WSAEMFILE || (e) == WSAENOBUFS)
+/** Return true if e is EADDRINUSE or the local equivalent. */
+#define ERRNO_IS_EADDRINUSE(e) ((e) == WSAEADDRINUSE)
+/** Return true if e is EINTR or the local equivalent */
+#define ERRNO_IS_EINTR(e) ((e) == WSAEINTR || 0)
+int tor_socket_errno(tor_socket_t sock);
+const char *tor_socket_strerror(int e);
+#else /* !(defined(_WIN32)) */
+#define SOCK_ERRNO(e) e
+#if EAGAIN == EWOULDBLOCK
+/* || 0 is for -Wparentheses-equality (-Wall?) appeasement under clang */
+#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN || 0)
+#else
+#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN || (e) == EWOULDBLOCK)
+#endif /* EAGAIN == EWOULDBLOCK */
+#define ERRNO_IS_EINTR(e) ((e) == EINTR || 0)
+#define ERRNO_IS_EINPROGRESS(e) ((e) == EINPROGRESS || 0)
+#define ERRNO_IS_CONN_EINPROGRESS(e) ((e) == EINPROGRESS || 0)
+#define ERRNO_IS_ACCEPT_EAGAIN(e) \
+ (ERRNO_IS_EAGAIN(e) || (e) == ECONNABORTED)
+#define ERRNO_IS_RESOURCE_LIMIT(e) \
+ ((e) == EMFILE || (e) == ENFILE || (e) == ENOBUFS || (e) == ENOMEM)
+#define ERRNO_IS_EADDRINUSE(e) (((e) == EADDRINUSE) || 0)
+#define tor_socket_errno(sock) (errno)
+#define tor_socket_strerror(e) strerror(e)
+#endif /* defined(_WIN32) */
+
+#ifdef SOCKET_PRIVATE
+#if !defined(HAVE_SOCKETPAIR) || defined(_WIN32) || defined(TOR_UNIT_TESTS)
+#define NEED_ERSATZ_SOCKETPAIR
+STATIC int tor_ersatz_socketpair(int family, int type, int protocol,
+ tor_socket_t fd[2]);
+#endif
+#endif /* defined(COMPAT_PRIVATE) */
+
+#if defined(_WIN32) && !defined(SIO_IDEAL_SEND_BACKLOG_QUERY)
+#define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747b
+#endif
+
+#endif
diff --git a/src/lib/net/socks5_status.h b/src/lib/net/socks5_status.h
new file mode 100644
index 0000000000..74b9c91023
--- /dev/null
+++ b/src/lib/net/socks5_status.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_SOCKS5_STATUS_H
+#define TOR_SOCKS5_STATUS_H
+
+/** Specified SOCKS5 status codes. */
+typedef enum {
+ SOCKS5_SUCCEEDED = 0x00,
+ SOCKS5_GENERAL_ERROR = 0x01,
+ SOCKS5_NOT_ALLOWED = 0x02,
+ SOCKS5_NET_UNREACHABLE = 0x03,
+ SOCKS5_HOST_UNREACHABLE = 0x04,
+ SOCKS5_CONNECTION_REFUSED = 0x05,
+ SOCKS5_TTL_EXPIRED = 0x06,
+ SOCKS5_COMMAND_NOT_SUPPORTED = 0x07,
+ SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED = 0x08,
+} socks5_reply_status_t;
+
+#endif
diff --git a/src/lib/osinfo/.may_include b/src/lib/osinfo/.may_include
new file mode 100644
index 0000000000..058f6eb89c
--- /dev/null
+++ b/src/lib/osinfo/.may_include
@@ -0,0 +1,5 @@
+orconfig.h
+
+lib/osinfo/*.h
+lib/string/*.h
+lib/testsupport/*.h
diff --git a/src/lib/osinfo/include.am b/src/lib/osinfo/include.am
new file mode 100644
index 0000000000..16c5812604
--- /dev/null
+++ b/src/lib/osinfo/include.am
@@ -0,0 +1,17 @@
+
+noinst_LIBRARIES += src/lib/libtor-osinfo.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-osinfo-testing.a
+endif
+
+src_lib_libtor_osinfo_a_SOURCES = \
+ src/lib/osinfo/uname.c
+
+src_lib_libtor_osinfo_testing_a_SOURCES = \
+ $(src_lib_libtor_osinfo_a_SOURCES)
+src_lib_libtor_osinfo_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_osinfo_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/osinfo/uname.h
diff --git a/src/lib/osinfo/uname.c b/src/lib/osinfo/uname.c
new file mode 100644
index 0000000000..a0fa26d1d2
--- /dev/null
+++ b/src/lib/osinfo/uname.c
@@ -0,0 +1,111 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "lib/osinfo/uname.h"
+
+#include "lib/string/compat_string.h"
+#include "lib/string/printf.h"
+
+#ifdef HAVE_UNAME
+#include <sys/utsname.h>
+#endif
+#ifdef _WIN32
+#include <windows.h>
+#endif
+#include <string.h>
+
+/** Hold the result of our call to <b>uname</b>. */
+static char uname_result[256];
+/** True iff uname_result is set. */
+static int uname_result_is_set = 0;
+
+/** Return a pointer to a description of our platform.
+ */
+MOCK_IMPL(const char *,
+get_uname,(void))
+{
+#ifdef HAVE_UNAME
+ struct utsname u;
+#endif
+ if (!uname_result_is_set) {
+#ifdef HAVE_UNAME
+ if (uname(&u) != -1) {
+ /* (Linux says 0 is success, Solaris says 1 is success) */
+ strlcpy(uname_result, u.sysname, sizeof(uname_result));
+ } else
+#endif /* defined(HAVE_UNAME) */
+ {
+#ifdef _WIN32
+ OSVERSIONINFOEX info;
+ int i;
+ const char *plat = NULL;
+ static struct {
+ unsigned major; unsigned minor; const char *version;
+ } win_version_table[] = {
+ { 6, 2, "Windows 8" },
+ { 6, 1, "Windows 7" },
+ { 6, 0, "Windows Vista" },
+ { 5, 2, "Windows Server 2003" },
+ { 5, 1, "Windows XP" },
+ { 5, 0, "Windows 2000" },
+ /* { 4, 0, "Windows NT 4.0" }, */
+ { 4, 90, "Windows Me" },
+ { 4, 10, "Windows 98" },
+ /* { 4, 0, "Windows 95" } */
+ { 3, 51, "Windows NT 3.51" },
+ { 0, 0, NULL }
+ };
+ memset(&info, 0, sizeof(info));
+ info.dwOSVersionInfoSize = sizeof(info);
+ if (! GetVersionEx((LPOSVERSIONINFO)&info)) {
+ strlcpy(uname_result, "Bizarre version of Windows where GetVersionEx"
+ " doesn't work.", sizeof(uname_result));
+ uname_result_is_set = 1;
+ return uname_result;
+ }
+ if (info.dwMajorVersion == 4 && info.dwMinorVersion == 0) {
+ if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ plat = "Windows NT 4.0";
+ else
+ plat = "Windows 95";
+ } else {
+ for (i=0; win_version_table[i].major>0; ++i) {
+ if (win_version_table[i].major == info.dwMajorVersion &&
+ win_version_table[i].minor == info.dwMinorVersion) {
+ plat = win_version_table[i].version;
+ break;
+ }
+ }
+ }
+ if (plat) {
+ strlcpy(uname_result, plat, sizeof(uname_result));
+ } else {
+ if (info.dwMajorVersion > 6 ||
+ (info.dwMajorVersion==6 && info.dwMinorVersion>2))
+ tor_snprintf(uname_result, sizeof(uname_result),
+ "Very recent version of Windows [major=%d,minor=%d]",
+ (int)info.dwMajorVersion,(int)info.dwMinorVersion);
+ else
+ tor_snprintf(uname_result, sizeof(uname_result),
+ "Unrecognized version of Windows [major=%d,minor=%d]",
+ (int)info.dwMajorVersion,(int)info.dwMinorVersion);
+ }
+#ifdef VER_NT_SERVER
+ if (info.wProductType == VER_NT_SERVER ||
+ info.wProductType == VER_NT_DOMAIN_CONTROLLER) {
+ strlcat(uname_result, " [server]", sizeof(uname_result));
+ }
+#endif /* defined(VER_NT_SERVER) */
+#else /* !(defined(_WIN32)) */
+ /* LCOV_EXCL_START -- can't provoke uname failure */
+ strlcpy(uname_result, "Unknown platform", sizeof(uname_result));
+ /* LCOV_EXCL_STOP */
+#endif /* defined(_WIN32) */
+ }
+ uname_result_is_set = 1;
+ }
+ return uname_result;
+}
diff --git a/src/lib/osinfo/uname.h b/src/lib/osinfo/uname.h
new file mode 100644
index 0000000000..1f0b78385f
--- /dev/null
+++ b/src/lib/osinfo/uname.h
@@ -0,0 +1,9 @@
+
+#ifndef HAVE_TOR_UNAME_H
+#define HAVE_TOR_UNAME_H
+
+#include "lib/testsupport/testsupport.h"
+
+MOCK_DECL(const char *, get_uname,(void));
+
+#endif
diff --git a/src/lib/process/.may_include b/src/lib/process/.may_include
new file mode 100644
index 0000000000..05414d2a96
--- /dev/null
+++ b/src/lib/process/.may_include
@@ -0,0 +1,17 @@
+orconfig.h
+
+lib/cc/*.h
+lib/container/*.h
+lib/ctime/*.h
+lib/err/*.h
+lib/intmath/*.h
+lib/fs/*.h
+lib/log/*.h
+lib/malloc/*.h
+lib/net/*.h
+lib/process/*.h
+lib/string/*.h
+lib/testsupport/*.h
+lib/thread/*.h
+
+ht.h \ No newline at end of file
diff --git a/src/lib/process/daemon.c b/src/lib/process/daemon.c
new file mode 100644
index 0000000000..edffb04683
--- /dev/null
+++ b/src/lib/process/daemon.c
@@ -0,0 +1,159 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "lib/process/daemon.h"
+
+#ifndef _WIN32
+
+#include "lib/fs/files.h"
+#include "lib/log/torlog.h"
+#include "lib/thread/threads.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Based on code contributed by christian grothoff */
+/** True iff we've called start_daemon(). */
+static int start_daemon_called = 0;
+/** True iff we've called finish_daemon(). */
+static int finish_daemon_called = 0;
+/** Socketpair used to communicate between parent and child process while
+ * daemonizing. */
+static int daemon_filedes[2];
+/** Start putting the process into daemon mode: fork and drop all resources
+ * except standard fds. The parent process never returns, but stays around
+ * until finish_daemon is called. (Note: it's safe to call this more
+ * than once: calls after the first are ignored.)
+ */
+void
+start_daemon(void)
+{
+ pid_t pid;
+
+ if (start_daemon_called)
+ return;
+ start_daemon_called = 1;
+
+ if (pipe(daemon_filedes)) {
+ /* LCOV_EXCL_START */
+ log_err(LD_GENERAL,"pipe failed; exiting. Error was %s", strerror(errno));
+ exit(1); // exit ok: during daemonize, pipe failed.
+ /* LCOV_EXCL_STOP */
+ }
+ pid = fork();
+ if (pid < 0) {
+ /* LCOV_EXCL_START */
+ log_err(LD_GENERAL,"fork failed. Exiting.");
+ exit(1); // exit ok: during daemonize, fork failed
+ /* LCOV_EXCL_STOP */
+ }
+ if (pid) { /* Parent */
+ int ok;
+ char c;
+
+ close(daemon_filedes[1]); /* we only read */
+ ok = -1;
+ while (0 < read(daemon_filedes[0], &c, sizeof(char))) {
+ if (c == '.')
+ ok = 1;
+ }
+ fflush(stdout);
+ if (ok == 1)
+ exit(0); // exit ok: during daemonize, daemonizing.
+ else
+ exit(1); /* child reported error. exit ok: daemonize failed. */
+ } else { /* Child */
+ close(daemon_filedes[0]); /* we only write */
+
+ (void) setsid(); /* Detach from controlling terminal */
+ /*
+ * Fork one more time, so the parent (the session group leader) can exit.
+ * This means that we, as a non-session group leader, can never regain a
+ * controlling terminal. This part is recommended by Stevens's
+ * _Advanced Programming in the Unix Environment_.
+ */
+ if (fork() != 0) {
+ exit(0); // exit ok: during daemonize, fork failed (2)
+ }
+ set_main_thread(); /* We are now the main thread. */
+
+ return;
+ }
+}
+
+/** Finish putting the process into daemon mode: drop standard fds, and tell
+ * the parent process to exit. (Note: it's safe to call this more than once:
+ * calls after the first are ignored. Calls start_daemon first if it hasn't
+ * been called already.)
+ */
+void
+finish_daemon(const char *desired_cwd)
+{
+ int nullfd;
+ char c = '.';
+ if (finish_daemon_called)
+ return;
+ if (!start_daemon_called)
+ start_daemon();
+ finish_daemon_called = 1;
+
+ if (!desired_cwd)
+ desired_cwd = "/";
+ /* Don't hold the wrong FS mounted */
+ if (chdir(desired_cwd) < 0) {
+ log_err(LD_GENERAL,"chdir to \"%s\" failed. Exiting.",desired_cwd);
+ exit(1); // exit ok: during daemonize, chdir failed.
+ }
+
+ nullfd = tor_open_cloexec("/dev/null", O_RDWR, 0);
+ if (nullfd < 0) {
+ /* LCOV_EXCL_START */
+ log_err(LD_GENERAL,"/dev/null can't be opened. Exiting.");
+ exit(1); // exit ok: during daemonize, couldn't open /dev/null
+ /* LCOV_EXCL_STOP */
+ }
+ /* close fds linking to invoking terminal, but
+ * close usual incoming fds, but redirect them somewhere
+ * useful so the fds don't get reallocated elsewhere.
+ */
+ if (dup2(nullfd,0) < 0 ||
+ dup2(nullfd,1) < 0 ||
+ dup2(nullfd,2) < 0) {
+ /* LCOV_EXCL_START */
+ log_err(LD_GENERAL,"dup2 failed. Exiting.");
+ exit(1); // exit ok: during daemonize, dup2 failed.
+ /* LCOV_EXCL_STOP */
+ }
+ if (nullfd > 2)
+ close(nullfd);
+ /* signal success */
+ if (write(daemon_filedes[1], &c, sizeof(char)) != sizeof(char)) {
+ log_err(LD_GENERAL,"write failed. Exiting.");
+ }
+ close(daemon_filedes[1]);
+}
+#else /* !(!defined(_WIN32)) */
+/* defined(_WIN32) */
+void
+start_daemon(void)
+{
+}
+void
+finish_daemon(const char *cp)
+{
+ (void)cp;
+}
+#endif /* !defined(_WIN32) */
diff --git a/src/lib/process/daemon.h b/src/lib/process/daemon.h
new file mode 100644
index 0000000000..48a65b22e6
--- /dev/null
+++ b/src/lib/process/daemon.h
@@ -0,0 +1,12 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_DAEMON_H
+#define TOR_DAEMON_H
+
+void start_daemon(void);
+void finish_daemon(const char *desired_cwd);
+
+#endif
diff --git a/src/lib/process/env.c b/src/lib/process/env.c
new file mode 100644
index 0000000000..731f609ac1
--- /dev/null
+++ b/src/lib/process/env.c
@@ -0,0 +1,219 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "lib/process/env.h"
+
+#include "lib/malloc/util_malloc.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/container/smartlist.h"
+#include "lib/log/util_bug.h"
+#include "lib/log/torlog.h"
+#include "lib/malloc/util_malloc.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_CRT_EXTERNS_H
+/* For _NSGetEnviron on macOS */
+#include <crt_externs.h>
+#endif
+
+#ifndef HAVE__NSGETENVIRON
+#ifndef HAVE_EXTERN_ENVIRON_DECLARED
+/* Some platforms declare environ under some circumstances, others don't. */
+#ifndef RUNNING_DOXYGEN
+extern char **environ;
+#endif
+#endif /* !defined(HAVE_EXTERN_ENVIRON_DECLARED) */
+#endif /* !defined(HAVE__NSGETENVIRON) */
+
+/** Return the current environment. This is a portable replacement for
+ * 'environ'. */
+char **
+get_environment(void)
+{
+#ifdef HAVE__NSGETENVIRON
+ /* This is for compatibility between OSX versions. Otherwise (for example)
+ * when we do a mostly-static build on OSX 10.7, the resulting binary won't
+ * work on OSX 10.6. */
+ return *_NSGetEnviron();
+#else /* !(defined(HAVE__NSGETENVIRON)) */
+ return environ;
+#endif /* defined(HAVE__NSGETENVIRON) */
+}
+
+/** Helper: return the number of characters in <b>s</b> preceding the first
+ * occurrence of <b>ch</b>. If <b>ch</b> does not occur in <b>s</b>, return
+ * the length of <b>s</b>. Should be equivalent to strspn(s, "ch"). */
+static inline size_t
+str_num_before(const char *s, char ch)
+{
+ const char *cp = strchr(s, ch);
+ if (cp)
+ return cp - s;
+ else
+ return strlen(s);
+}
+
+/** Return non-zero iff getenv would consider <b>s1</b> and <b>s2</b>
+ * to have the same name as strings in a process's environment. */
+int
+environment_variable_names_equal(const char *s1, const char *s2)
+{
+ size_t s1_name_len = str_num_before(s1, '=');
+ size_t s2_name_len = str_num_before(s2, '=');
+
+ return (s1_name_len == s2_name_len &&
+ tor_memeq(s1, s2, s1_name_len));
+}
+
+/** Free <b>env</b> (assuming it was produced by
+ * process_environment_make). */
+void
+process_environment_free_(process_environment_t *env)
+{
+ if (env == NULL) return;
+
+ /* As both an optimization hack to reduce consing on Unixoid systems
+ * and a nice way to ensure that some otherwise-Windows-specific
+ * code will always get tested before changes to it get merged, the
+ * strings which env->unixoid_environment_block points to are packed
+ * into env->windows_environment_block. */
+ tor_free(env->unixoid_environment_block);
+ tor_free(env->windows_environment_block);
+
+ tor_free(env);
+}
+
+/** Make a process_environment_t containing the environment variables
+ * specified in <b>env_vars</b> (as C strings of the form
+ * "NAME=VALUE"). */
+process_environment_t *
+process_environment_make(struct smartlist_t *env_vars)
+{
+ process_environment_t *env = tor_malloc_zero(sizeof(process_environment_t));
+ int n_env_vars = smartlist_len(env_vars);
+ int i;
+ size_t total_env_length;
+ smartlist_t *env_vars_sorted;
+
+ tor_assert(n_env_vars + 1 != 0);
+ env->unixoid_environment_block = tor_calloc(n_env_vars + 1, sizeof(char *));
+ /* env->unixoid_environment_block is already NULL-terminated,
+ * because we assume that NULL == 0 (and check that during compilation). */
+
+ total_env_length = 1; /* terminating NUL of terminating empty string */
+ for (i = 0; i < n_env_vars; ++i) {
+ const char *s = smartlist_get(env_vars, (int)i);
+ size_t slen = strlen(s);
+
+ tor_assert(slen + 1 != 0);
+ tor_assert(slen + 1 < SIZE_MAX - total_env_length);
+ total_env_length += slen + 1;
+ }
+
+ env->windows_environment_block = tor_malloc_zero(total_env_length);
+ /* env->windows_environment_block is already
+ * (NUL-terminated-empty-string)-terminated. */
+
+ /* Some versions of Windows supposedly require that environment
+ * blocks be sorted. Or maybe some Windows programs (or their
+ * runtime libraries) fail to look up strings in non-sorted
+ * environment blocks.
+ *
+ * Also, sorting strings makes it easy to find duplicate environment
+ * variables and environment-variable strings without an '=' on all
+ * OSes, and they can cause badness. Let's complain about those. */
+ env_vars_sorted = smartlist_new();
+ smartlist_add_all(env_vars_sorted, env_vars);
+ smartlist_sort_strings(env_vars_sorted);
+
+ /* Now copy the strings into the environment blocks. */
+ {
+ char *cp = env->windows_environment_block;
+ const char *prev_env_var = NULL;
+
+ for (i = 0; i < n_env_vars; ++i) {
+ const char *s = smartlist_get(env_vars_sorted, (int)i);
+ size_t slen = strlen(s);
+ size_t s_name_len = str_num_before(s, '=');
+
+ if (s_name_len == slen) {
+ log_warn(LD_GENERAL,
+ "Preparing an environment containing a variable "
+ "without a value: %s",
+ s);
+ }
+ if (prev_env_var != NULL &&
+ environment_variable_names_equal(s, prev_env_var)) {
+ log_warn(LD_GENERAL,
+ "Preparing an environment containing two variables "
+ "with the same name: %s and %s",
+ prev_env_var, s);
+ }
+
+ prev_env_var = s;
+
+ /* Actually copy the string into the environment. */
+ memcpy(cp, s, slen+1);
+ env->unixoid_environment_block[i] = cp;
+ cp += slen+1;
+ }
+
+ tor_assert(cp == env->windows_environment_block + total_env_length - 1);
+ }
+
+ smartlist_free(env_vars_sorted);
+
+ return env;
+}
+
+/** Return a newly allocated smartlist containing every variable in
+ * this process's environment, as a NUL-terminated string of the form
+ * "NAME=VALUE". Note that on some/many/most/all OSes, the parent
+ * process can put strings not of that form in our environment;
+ * callers should try to not get crashed by that.
+ *
+ * The returned strings are heap-allocated, and must be freed by the
+ * caller. */
+struct smartlist_t *
+get_current_process_environment_variables(void)
+{
+ smartlist_t *sl = smartlist_new();
+
+ char **environ_tmp; /* Not const char ** ? Really? */
+ for (environ_tmp = get_environment(); *environ_tmp; ++environ_tmp) {
+ smartlist_add_strdup(sl, *environ_tmp);
+ }
+
+ return sl;
+}
+
+/** For each string s in <b>env_vars</b> such that
+ * environment_variable_names_equal(s, <b>new_var</b>), remove it; if
+ * <b>free_p</b> is non-zero, call <b>free_old</b>(s). If
+ * <b>new_var</b> contains '=', insert it into <b>env_vars</b>. */
+void
+set_environment_variable_in_smartlist(struct smartlist_t *env_vars,
+ const char *new_var,
+ void (*free_old)(void*),
+ int free_p)
+{
+ SMARTLIST_FOREACH_BEGIN(env_vars, const char *, s) {
+ if (environment_variable_names_equal(s, new_var)) {
+ SMARTLIST_DEL_CURRENT(env_vars, s);
+ if (free_p) {
+ free_old((void *)s);
+ }
+ }
+ } SMARTLIST_FOREACH_END(s);
+
+ if (strchr(new_var, '=') != NULL) {
+ smartlist_add(env_vars, (void *)new_var);
+ }
+}
diff --git a/src/lib/process/env.h b/src/lib/process/env.h
new file mode 100644
index 0000000000..f22599355d
--- /dev/null
+++ b/src/lib/process/env.h
@@ -0,0 +1,36 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_ENV_H
+#define TOR_ENV_H
+
+char **get_environment(void);
+
+struct smartlist_t;
+
+int environment_variable_names_equal(const char *s1, const char *s2);
+
+/* DOCDOC process_environment_t */
+typedef struct process_environment_t {
+ /** A pointer to a sorted empty-string-terminated sequence of
+ * NUL-terminated strings of the form "NAME=VALUE". */
+ char *windows_environment_block;
+ /** A pointer to a NULL-terminated array of pointers to
+ * NUL-terminated strings of the form "NAME=VALUE". */
+ char **unixoid_environment_block;
+} process_environment_t;
+
+process_environment_t *process_environment_make(struct smartlist_t *env_vars);
+void process_environment_free_(process_environment_t *env);
+#define process_environment_free(env) \
+ FREE_AND_NULL(process_environment_t, process_environment_free_, (env))
+
+struct smartlist_t *get_current_process_environment_variables(void);
+
+void set_environment_variable_in_smartlist(struct smartlist_t *env_vars,
+ const char *new_var,
+ void (*free_old)(void*),
+ int free_p);
+#endif
diff --git a/src/lib/process/include.am b/src/lib/process/include.am
new file mode 100644
index 0000000000..c6cc3a6699
--- /dev/null
+++ b/src/lib/process/include.am
@@ -0,0 +1,29 @@
+
+noinst_LIBRARIES += src/lib/libtor-process.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-process-testing.a
+endif
+
+src_lib_libtor_process_a_SOURCES = \
+ src/lib/process/daemon.c \
+ src/lib/process/env.c \
+ src/lib/process/pidfile.c \
+ src/lib/process/restrict.c \
+ src/lib/process/setuid.c \
+ src/lib/process/subprocess.c \
+ src/lib/process/waitpid.c
+
+src_lib_libtor_process_testing_a_SOURCES = \
+ $(src_lib_libtor_process_a_SOURCES)
+src_lib_libtor_process_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_process_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/process/daemon.h \
+ src/lib/process/env.h \
+ src/lib/process/pidfile.h \
+ src/lib/process/restrict.h \
+ src/lib/process/setuid.h \
+ src/lib/process/subprocess.h \
+ src/lib/process/waitpid.h
diff --git a/src/lib/process/pidfile.c b/src/lib/process/pidfile.c
new file mode 100644
index 0000000000..f016f21697
--- /dev/null
+++ b/src/lib/process/pidfile.c
@@ -0,0 +1,47 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "lib/process/pidfile.h"
+
+#include "lib/log/torlog.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+/** Write the current process ID, followed by NL, into <b>filename</b>.
+ * Return 0 on success, -1 on failure.
+ */
+int
+write_pidfile(const char *filename)
+{
+ FILE *pidfile;
+
+ if ((pidfile = fopen(filename, "w")) == NULL) {
+ log_warn(LD_FS, "Unable to open \"%s\" for writing: %s", filename,
+ strerror(errno));
+ return -1;
+ } else {
+#ifdef _WIN32
+ int pid = (int)_getpid();
+#else
+ int pid = (int)getpid();
+#endif
+ int rv = 0;
+ if (fprintf(pidfile, "%d\n", pid) < 0)
+ rv = -1;
+ if (fclose(pidfile) < 0)
+ rv = -1;
+ return rv;
+ }
+}
diff --git a/src/lib/process/pidfile.h b/src/lib/process/pidfile.h
new file mode 100644
index 0000000000..c85cd1905e
--- /dev/null
+++ b/src/lib/process/pidfile.h
@@ -0,0 +1,11 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_PIDFILE_H
+#define TOR_PIDFILE_H
+
+int write_pidfile(const char *filename);
+
+#endif
diff --git a/src/lib/process/restrict.c b/src/lib/process/restrict.c
new file mode 100644
index 0000000000..bb44cc3d15
--- /dev/null
+++ b/src/lib/process/restrict.c
@@ -0,0 +1,280 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "lib/process/restrict.h"
+#include "lib/intmath/cmp.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/net/socket.h"
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* We only use the linux prctl for now. There is no Win32 support; this may
+ * also work on various BSD systems and Mac OS X - send testing feedback!
+ *
+ * On recent Gnu/Linux kernels it is possible to create a system-wide policy
+ * that will prevent non-root processes from attaching to other processes
+ * unless they are the parent process; thus gdb can attach to programs that
+ * they execute but they cannot attach to other processes running as the same
+ * user. The system wide policy may be set with the sysctl
+ * kernel.yama.ptrace_scope or by inspecting
+ * /proc/sys/kernel/yama/ptrace_scope and it is 1 by default on Ubuntu 11.04.
+ *
+ * This ptrace scope will be ignored on Gnu/Linux for users with
+ * CAP_SYS_PTRACE and so it is very likely that root will still be able to
+ * attach to the Tor process.
+ */
+/** Attempt to disable debugger attachment: return 1 on success, -1 on
+ * failure, and 0 if we don't know how to try on this platform. */
+int
+tor_disable_debugger_attach(void)
+{
+ int r = -1;
+ log_debug(LD_CONFIG,
+ "Attemping to disable debugger attachment to Tor for "
+ "unprivileged users.");
+#if defined(__linux__) && defined(HAVE_SYS_PRCTL_H) \
+ && defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
+#define TRIED_TO_DISABLE
+ r = prctl(PR_SET_DUMPABLE, 0);
+#elif defined(__APPLE__) && defined(PT_DENY_ATTACH)
+#define TRIED_TO_ATTACH
+ r = ptrace(PT_DENY_ATTACH, 0, 0, 0);
+#endif /* defined(__linux__) && defined(HAVE_SYS_PRCTL_H) ... || ... */
+
+ // XXX: TODO - Mac OS X has dtrace and this may be disabled.
+ // XXX: TODO - Windows probably has something similar
+#ifdef TRIED_TO_DISABLE
+ if (r == 0) {
+ log_debug(LD_CONFIG,"Debugger attachment disabled for "
+ "unprivileged users.");
+ return 1;
+ } else {
+ log_warn(LD_CONFIG, "Unable to disable debugger attaching: %s",
+ strerror(errno));
+ }
+#endif /* defined(TRIED_TO_DISABLE) */
+#undef TRIED_TO_DISABLE
+ return r;
+}
+
+#if defined(HAVE_MLOCKALL) && HAVE_DECL_MLOCKALL && defined(RLIMIT_MEMLOCK)
+#define HAVE_UNIX_MLOCKALL
+#endif
+
+#ifdef HAVE_UNIX_MLOCKALL
+/** Attempt to raise the current and max rlimit to infinity for our process.
+ * This only needs to be done once and can probably only be done when we have
+ * not already dropped privileges.
+ */
+static int
+tor_set_max_memlock(void)
+{
+ /* Future consideration for Windows is probably SetProcessWorkingSetSize
+ * This is similar to setting the memory rlimit of RLIMIT_MEMLOCK
+ * http://msdn.microsoft.com/en-us/library/ms686234(VS.85).aspx
+ */
+
+ struct rlimit limit;
+
+ /* RLIM_INFINITY is -1 on some platforms. */
+ limit.rlim_cur = RLIM_INFINITY;
+ limit.rlim_max = RLIM_INFINITY;
+
+ if (setrlimit(RLIMIT_MEMLOCK, &limit) == -1) {
+ if (errno == EPERM) {
+ log_warn(LD_GENERAL, "You appear to lack permissions to change memory "
+ "limits. Are you root?");
+ }
+ log_warn(LD_GENERAL, "Unable to raise RLIMIT_MEMLOCK: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+#endif /* defined(HAVE_UNIX_MLOCKALL) */
+
+/** Attempt to lock all current and all future memory pages.
+ * This should only be called once and while we're privileged.
+ * Like mlockall() we return 0 when we're successful and -1 when we're not.
+ * Unlike mlockall() we return 1 if we've already attempted to lock memory.
+ */
+int
+tor_mlockall(void)
+{
+ static int memory_lock_attempted = 0;
+
+ if (memory_lock_attempted) {
+ return 1;
+ }
+
+ memory_lock_attempted = 1;
+
+ /*
+ * Future consideration for Windows may be VirtualLock
+ * VirtualLock appears to implement mlock() but not mlockall()
+ *
+ * http://msdn.microsoft.com/en-us/library/aa366895(VS.85).aspx
+ */
+
+#ifdef HAVE_UNIX_MLOCKALL
+ if (tor_set_max_memlock() == 0) {
+ log_debug(LD_GENERAL, "RLIMIT_MEMLOCK is now set to RLIM_INFINITY.");
+ }
+
+ if (mlockall(MCL_CURRENT|MCL_FUTURE) == 0) {
+ log_info(LD_GENERAL, "Insecure OS paging is effectively disabled.");
+ return 0;
+ } else {
+ if (errno == ENOSYS) {
+ /* Apple - it's 2009! I'm looking at you. Grrr. */
+ log_notice(LD_GENERAL, "It appears that mlockall() is not available on "
+ "your platform.");
+ } else if (errno == EPERM) {
+ log_notice(LD_GENERAL, "It appears that you lack the permissions to "
+ "lock memory. Are you root?");
+ }
+ log_notice(LD_GENERAL, "Unable to lock all current and future memory "
+ "pages: %s", strerror(errno));
+ return -1;
+ }
+#else /* !(defined(HAVE_UNIX_MLOCKALL)) */
+ log_warn(LD_GENERAL, "Unable to lock memory pages. mlockall() unsupported?");
+ return -1;
+#endif /* defined(HAVE_UNIX_MLOCKALL) */
+}
+
+/** Number of extra file descriptors to keep in reserve beyond those that we
+ * tell Tor it's allowed to use. */
+#define ULIMIT_BUFFER 32 /* keep 32 extra fd's beyond ConnLimit_ */
+
+/** Learn the maximum allowed number of file descriptors, and tell the
+ * system we want to use up to that number. (Some systems have a low soft
+ * limit, and let us set it higher.) We compute this by finding the largest
+ * number that we can use.
+ *
+ * If the limit is below the reserved file descriptor value (ULIMIT_BUFFER),
+ * return -1 and <b>max_out</b> is untouched.
+ *
+ * If we can't find a number greater than or equal to <b>limit</b>, then we
+ * fail by returning -1 and <b>max_out</b> is untouched.
+ *
+ * If we are unable to set the limit value because of setrlimit() failing,
+ * return 0 and <b>max_out</b> is set to the current maximum value returned
+ * by getrlimit().
+ *
+ * Otherwise, return 0 and store the maximum we found inside <b>max_out</b>
+ * and set <b>max_sockets</b> with that value as well.*/
+int
+set_max_file_descriptors(rlim_t limit, int *max_out)
+{
+ if (limit < ULIMIT_BUFFER) {
+ log_warn(LD_CONFIG,
+ "ConnLimit must be at least %d. Failing.", ULIMIT_BUFFER);
+ return -1;
+ }
+
+ /* Define some maximum connections values for systems where we cannot
+ * automatically determine a limit. Re Cygwin, see
+ * http://archives.seul.org/or/talk/Aug-2006/msg00210.html
+ * For an iPhone, 9999 should work. For Windows and all other unknown
+ * systems we use 15000 as the default. */
+#ifndef HAVE_GETRLIMIT
+#if defined(CYGWIN) || defined(__CYGWIN__)
+ const char *platform = "Cygwin";
+ const unsigned long MAX_CONNECTIONS = 3200;
+#elif defined(_WIN32)
+ const char *platform = "Windows";
+ const unsigned long MAX_CONNECTIONS = 15000;
+#else
+ const char *platform = "unknown platforms with no getrlimit()";
+ const unsigned long MAX_CONNECTIONS = 15000;
+#endif /* defined(CYGWIN) || defined(__CYGWIN__) || ... */
+ log_fn(LOG_INFO, LD_NET,
+ "This platform is missing getrlimit(). Proceeding.");
+ if (limit > MAX_CONNECTIONS) {
+ log_warn(LD_CONFIG,
+ "We do not support more than %lu file descriptors "
+ "on %s. Tried to raise to %lu.",
+ (unsigned long)MAX_CONNECTIONS, platform, (unsigned long)limit);
+ return -1;
+ }
+ limit = MAX_CONNECTIONS;
+#else /* !(!defined(HAVE_GETRLIMIT)) */
+ struct rlimit rlim;
+
+ if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
+ log_warn(LD_NET, "Could not get maximum number of file descriptors: %s",
+ strerror(errno));
+ return -1;
+ }
+ if (rlim.rlim_max < limit) {
+ log_warn(LD_CONFIG,"We need %lu file descriptors available, and we're "
+ "limited to %lu. Please change your ulimit -n.",
+ (unsigned long)limit, (unsigned long)rlim.rlim_max);
+ return -1;
+ }
+
+ if (rlim.rlim_max > rlim.rlim_cur) {
+ log_info(LD_NET,"Raising max file descriptors from %lu to %lu.",
+ (unsigned long)rlim.rlim_cur, (unsigned long)rlim.rlim_max);
+ }
+ /* Set the current limit value so if the attempt to set the limit to the
+ * max fails at least we'll have a valid value of maximum sockets. */
+ *max_out = (int)rlim.rlim_cur - ULIMIT_BUFFER;
+ set_max_sockets(*max_out);
+ rlim.rlim_cur = rlim.rlim_max;
+
+ if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
+ int couldnt_set = 1;
+ const int setrlimit_errno = errno;
+#ifdef OPEN_MAX
+ uint64_t try_limit = OPEN_MAX - ULIMIT_BUFFER;
+ if (errno == EINVAL && try_limit < (uint64_t) rlim.rlim_cur) {
+ /* On some platforms, OPEN_MAX is the real limit, and getrlimit() is
+ * full of nasty lies. I'm looking at you, OSX 10.5.... */
+ rlim.rlim_cur = MIN((rlim_t) try_limit, rlim.rlim_cur);
+ if (setrlimit(RLIMIT_NOFILE, &rlim) == 0) {
+ if (rlim.rlim_cur < (rlim_t)limit) {
+ log_warn(LD_CONFIG, "We are limited to %lu file descriptors by "
+ "OPEN_MAX (%lu), and ConnLimit is %lu. Changing "
+ "ConnLimit; sorry.",
+ (unsigned long)try_limit, (unsigned long)OPEN_MAX,
+ (unsigned long)limit);
+ } else {
+ log_info(LD_CONFIG, "Dropped connection limit to %lu based on "
+ "OPEN_MAX (%lu); Apparently, %lu was too high and rlimit "
+ "lied to us.",
+ (unsigned long)try_limit, (unsigned long)OPEN_MAX,
+ (unsigned long)rlim.rlim_max);
+ }
+ couldnt_set = 0;
+ }
+ }
+#endif /* defined(OPEN_MAX) */
+ if (couldnt_set) {
+ log_warn(LD_CONFIG,"Couldn't set maximum number of file descriptors: %s",
+ strerror(setrlimit_errno));
+ }
+ }
+ /* leave some overhead for logs, etc, */
+ limit = rlim.rlim_cur;
+#endif /* !defined(HAVE_GETRLIMIT) */
+
+ if (limit > INT_MAX)
+ limit = INT_MAX;
+ tor_assert(max_out);
+ *max_out = (int)limit - ULIMIT_BUFFER;
+ set_max_sockets(*max_out);
+
+ return 0;
+}
diff --git a/src/lib/process/restrict.h b/src/lib/process/restrict.h
new file mode 100644
index 0000000000..c7f76f8233
--- /dev/null
+++ b/src/lib/process/restrict.h
@@ -0,0 +1,27 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file waitpid.h
+ * \brief Headers for waitpid.c
+ **/
+
+#ifndef TOR_RESTRICT_H
+#define TOR_RESTRICT_H
+
+#include "orconfig.h"
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+int tor_disable_debugger_attach(void);
+int tor_mlockall(void);
+
+#if !defined(HAVE_RLIM_T)
+typedef unsigned long rlim_t;
+#endif
+int set_max_file_descriptors(rlim_t limit, int *max_out);
+
+#endif /* !defined(TOR_RESTRICT_H) */
diff --git a/src/lib/process/setuid.c b/src/lib/process/setuid.c
new file mode 100644
index 0000000000..fa1cdc0f3f
--- /dev/null
+++ b/src/lib/process/setuid.c
@@ -0,0 +1,381 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "lib/process/setuid.h"
+
+#if defined(HAVE_SYS_CAPABILITY_H) && defined(HAVE_CAP_SET_PROC)
+#define HAVE_LINUX_CAPABILITIES
+#endif
+
+#include "lib/container/smartlist.h"
+#include "lib/fs/userdb.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/malloc/util_malloc.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#ifdef HAVE_SYS_CAPABILITY_H
+#include <sys/capability.h>
+#endif
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+
+#ifndef _WIN32
+/** Log details of current user and group credentials. Return 0 on
+ * success. Logs and return -1 on failure.
+ */
+static int
+log_credential_status(void)
+{
+/** Log level to use when describing non-error UID/GID status. */
+#define CREDENTIAL_LOG_LEVEL LOG_INFO
+ /* Real, effective and saved UIDs */
+ uid_t ruid, euid, suid;
+ /* Read, effective and saved GIDs */
+ gid_t rgid, egid, sgid;
+ /* Supplementary groups */
+ gid_t *sup_gids = NULL;
+ int sup_gids_size;
+ /* Number of supplementary groups */
+ int ngids;
+
+ /* log UIDs */
+#ifdef HAVE_GETRESUID
+ if (getresuid(&ruid, &euid, &suid) != 0 ) {
+ log_warn(LD_GENERAL, "Error getting changed UIDs: %s", strerror(errno));
+ return -1;
+ } else {
+ log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL,
+ "UID is %u (real), %u (effective), %u (saved)",
+ (unsigned)ruid, (unsigned)euid, (unsigned)suid);
+ }
+#else /* !(defined(HAVE_GETRESUID)) */
+ /* getresuid is not present on MacOS X, so we can't get the saved (E)UID */
+ ruid = getuid();
+ euid = geteuid();
+ (void)suid;
+
+ log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL,
+ "UID is %u (real), %u (effective), unknown (saved)",
+ (unsigned)ruid, (unsigned)euid);
+#endif /* defined(HAVE_GETRESUID) */
+
+ /* log GIDs */
+#ifdef HAVE_GETRESGID
+ if (getresgid(&rgid, &egid, &sgid) != 0 ) {
+ log_warn(LD_GENERAL, "Error getting changed GIDs: %s", strerror(errno));
+ return -1;
+ } else {
+ log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL,
+ "GID is %u (real), %u (effective), %u (saved)",
+ (unsigned)rgid, (unsigned)egid, (unsigned)sgid);
+ }
+#else /* !(defined(HAVE_GETRESGID)) */
+ /* getresgid is not present on MacOS X, so we can't get the saved (E)GID */
+ rgid = getgid();
+ egid = getegid();
+ (void)sgid;
+ log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL,
+ "GID is %u (real), %u (effective), unknown (saved)",
+ (unsigned)rgid, (unsigned)egid);
+#endif /* defined(HAVE_GETRESGID) */
+
+ /* log supplementary groups */
+ sup_gids_size = 64;
+ sup_gids = tor_calloc(64, sizeof(gid_t));
+ while ((ngids = getgroups(sup_gids_size, sup_gids)) < 0 &&
+ errno == EINVAL &&
+ sup_gids_size < NGROUPS_MAX) {
+ sup_gids_size *= 2;
+ sup_gids = tor_reallocarray(sup_gids, sizeof(gid_t), sup_gids_size);
+ }
+
+ if (ngids < 0) {
+ log_warn(LD_GENERAL, "Error getting supplementary GIDs: %s",
+ strerror(errno));
+ tor_free(sup_gids);
+ return -1;
+ } else {
+ int i, retval = 0;
+ char *s = NULL;
+ smartlist_t *elts = smartlist_new();
+
+ for (i = 0; i<ngids; i++) {
+ smartlist_add_asprintf(elts, "%u", (unsigned)sup_gids[i]);
+ }
+
+ s = smartlist_join_strings(elts, " ", 0, NULL);
+
+ log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL, "Supplementary groups are: %s",s);
+
+ tor_free(s);
+ SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
+ smartlist_free(elts);
+ tor_free(sup_gids);
+
+ return retval;
+ }
+
+ return 0;
+}
+#endif /* !defined(_WIN32) */
+
+/** Return true iff we were compiled with capability support, and capabilities
+ * seem to work. **/
+int
+have_capability_support(void)
+{
+#ifdef HAVE_LINUX_CAPABILITIES
+ cap_t caps = cap_get_proc();
+ if (caps == NULL)
+ return 0;
+ cap_free(caps);
+ return 1;
+#else /* !(defined(HAVE_LINUX_CAPABILITIES)) */
+ return 0;
+#endif /* defined(HAVE_LINUX_CAPABILITIES) */
+}
+
+#ifdef HAVE_LINUX_CAPABILITIES
+/** Helper. Drop all capabilities but a small set, and set PR_KEEPCAPS as
+ * appropriate.
+ *
+ * If pre_setuid, retain only CAP_NET_BIND_SERVICE, CAP_SETUID, and
+ * CAP_SETGID, and use PR_KEEPCAPS to ensure that capabilities persist across
+ * setuid().
+ *
+ * If not pre_setuid, retain only CAP_NET_BIND_SERVICE, and disable
+ * PR_KEEPCAPS.
+ *
+ * Return 0 on success, and -1 on failure.
+ */
+static int
+drop_capabilities(int pre_setuid)
+{
+ /* We keep these three capabilities, and these only, as we setuid.
+ * After we setuid, we drop all but the first. */
+ const cap_value_t caplist[] = {
+ CAP_NET_BIND_SERVICE, CAP_SETUID, CAP_SETGID
+ };
+ const char *where = pre_setuid ? "pre-setuid" : "post-setuid";
+ const int n_effective = pre_setuid ? 3 : 1;
+ const int n_permitted = pre_setuid ? 3 : 1;
+ const int n_inheritable = 1;
+ const int keepcaps = pre_setuid ? 1 : 0;
+
+ /* Sets whether we keep capabilities across a setuid. */
+ if (prctl(PR_SET_KEEPCAPS, keepcaps) < 0) {
+ log_warn(LD_CONFIG, "Unable to call prctl() %s: %s",
+ where, strerror(errno));
+ return -1;
+ }
+
+ cap_t caps = cap_get_proc();
+ if (!caps) {
+ log_warn(LD_CONFIG, "Unable to call cap_get_proc() %s: %s",
+ where, strerror(errno));
+ return -1;
+ }
+ cap_clear(caps);
+
+ cap_set_flag(caps, CAP_EFFECTIVE, n_effective, caplist, CAP_SET);
+ cap_set_flag(caps, CAP_PERMITTED, n_permitted, caplist, CAP_SET);
+ cap_set_flag(caps, CAP_INHERITABLE, n_inheritable, caplist, CAP_SET);
+
+ int r = cap_set_proc(caps);
+ cap_free(caps);
+ if (r < 0) {
+ log_warn(LD_CONFIG, "No permission to set capabilities %s: %s",
+ where, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+#endif /* defined(HAVE_LINUX_CAPABILITIES) */
+
+/** Call setuid and setgid to run as <b>user</b> and switch to their
+ * primary group. Return 0 on success. On failure, log and return -1.
+ *
+ * If SWITCH_ID_KEEP_BINDLOW is set in 'flags', try to use the capability
+ * system to retain the abilitity to bind low ports.
+ *
+ * If SWITCH_ID_WARN_IF_NO_CAPS is set in flags, also warn if we have
+ * don't have capability support.
+ */
+int
+switch_id(const char *user, const unsigned flags)
+{
+#ifndef _WIN32
+ const struct passwd *pw = NULL;
+ uid_t old_uid;
+ gid_t old_gid;
+ static int have_already_switched_id = 0;
+ const int keep_bindlow = !!(flags & SWITCH_ID_KEEP_BINDLOW);
+ const int warn_if_no_caps = !!(flags & SWITCH_ID_WARN_IF_NO_CAPS);
+
+ tor_assert(user);
+
+ if (have_already_switched_id)
+ return 0;
+
+ /* Log the initial credential state */
+ if (log_credential_status())
+ return -1;
+
+ log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL, "Changing user and groups");
+
+ /* Get old UID/GID to check if we changed correctly */
+ old_uid = getuid();
+ old_gid = getgid();
+
+ /* Lookup the user and group information, if we have a problem, bail out. */
+ pw = tor_getpwnam(user);
+ if (pw == NULL) {
+ log_warn(LD_CONFIG, "Error setting configured user: %s not found", user);
+ return -1;
+ }
+
+#ifdef HAVE_LINUX_CAPABILITIES
+ (void) warn_if_no_caps;
+ if (keep_bindlow) {
+ if (drop_capabilities(1))
+ return -1;
+ }
+#else /* !(defined(HAVE_LINUX_CAPABILITIES)) */
+ (void) keep_bindlow;
+ if (warn_if_no_caps) {
+ log_warn(LD_CONFIG, "KeepBindCapabilities set, but no capability support "
+ "on this system.");
+ }
+#endif /* defined(HAVE_LINUX_CAPABILITIES) */
+
+ /* Properly switch egid,gid,euid,uid here or bail out */
+ if (setgroups(1, &pw->pw_gid)) {
+ log_warn(LD_GENERAL, "Error setting groups to gid %d: \"%s\".",
+ (int)pw->pw_gid, strerror(errno));
+ if (old_uid == pw->pw_uid) {
+ log_warn(LD_GENERAL, "Tor is already running as %s. You do not need "
+ "the \"User\" option if you are already running as the user "
+ "you want to be. (If you did not set the User option in your "
+ "torrc, check whether it was specified on the command line "
+ "by a startup script.)", user);
+ } else {
+ log_warn(LD_GENERAL, "If you set the \"User\" option, you must start Tor"
+ " as root.");
+ }
+ return -1;
+ }
+
+ if (setegid(pw->pw_gid)) {
+ log_warn(LD_GENERAL, "Error setting egid to %d: %s",
+ (int)pw->pw_gid, strerror(errno));
+ return -1;
+ }
+
+ if (setgid(pw->pw_gid)) {
+ log_warn(LD_GENERAL, "Error setting gid to %d: %s",
+ (int)pw->pw_gid, strerror(errno));
+ return -1;
+ }
+
+ if (setuid(pw->pw_uid)) {
+ log_warn(LD_GENERAL, "Error setting configured uid to %s (%d): %s",
+ user, (int)pw->pw_uid, strerror(errno));
+ return -1;
+ }
+
+ if (seteuid(pw->pw_uid)) {
+ log_warn(LD_GENERAL, "Error setting configured euid to %s (%d): %s",
+ user, (int)pw->pw_uid, strerror(errno));
+ return -1;
+ }
+
+ /* This is how OpenBSD rolls:
+ if (setgroups(1, &pw->pw_gid) || setegid(pw->pw_gid) ||
+ setgid(pw->pw_gid) || setuid(pw->pw_uid) || seteuid(pw->pw_uid)) {
+ setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) {
+ log_warn(LD_GENERAL, "Error setting configured UID/GID: %s",
+ strerror(errno));
+ return -1;
+ }
+ */
+
+ /* We've properly switched egid, gid, euid, uid, and supplementary groups if
+ * we're here. */
+#ifdef HAVE_LINUX_CAPABILITIES
+ if (keep_bindlow) {
+ if (drop_capabilities(0))
+ return -1;
+ }
+#endif /* defined(HAVE_LINUX_CAPABILITIES) */
+
+#if !defined(CYGWIN) && !defined(__CYGWIN__)
+ /* If we tried to drop privilege to a group/user other than root, attempt to
+ * restore root (E)(U|G)ID, and abort if the operation succeeds */
+
+ /* Only check for privilege dropping if we were asked to be non-root */
+ if (pw->pw_uid) {
+ /* Try changing GID/EGID */
+ if (pw->pw_gid != old_gid &&
+ (setgid(old_gid) != -1 || setegid(old_gid) != -1)) {
+ log_warn(LD_GENERAL, "Was able to restore group credentials even after "
+ "switching GID: this means that the setgid code didn't work.");
+ return -1;
+ }
+
+ /* Try changing UID/EUID */
+ if (pw->pw_uid != old_uid &&
+ (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) {
+ log_warn(LD_GENERAL, "Was able to restore user credentials even after "
+ "switching UID: this means that the setuid code didn't work.");
+ return -1;
+ }
+ }
+#endif /* !defined(CYGWIN) && !defined(__CYGWIN__) */
+
+ /* Check what really happened */
+ if (log_credential_status()) {
+ return -1;
+ }
+
+ have_already_switched_id = 1; /* mark success so we never try again */
+
+#if defined(__linux__) && defined(HAVE_SYS_PRCTL_H) && \
+ defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
+ if (pw->pw_uid) {
+ /* Re-enable core dumps if we're not running as root. */
+ log_info(LD_CONFIG, "Re-enabling coredumps");
+ if (prctl(PR_SET_DUMPABLE, 1)) {
+ log_warn(LD_CONFIG, "Unable to re-enable coredumps: %s",strerror(errno));
+ }
+ }
+#endif /* defined(__linux__) && defined(HAVE_SYS_PRCTL_H) && ... */
+ return 0;
+
+#else /* !(!defined(_WIN32)) */
+ (void)user;
+ (void)flags;
+
+ log_warn(LD_CONFIG, "Switching users is unsupported on your OS.");
+ return -1;
+#endif /* !defined(_WIN32) */
+}
diff --git a/src/lib/process/setuid.h b/src/lib/process/setuid.h
new file mode 100644
index 0000000000..61aeefe1b7
--- /dev/null
+++ b/src/lib/process/setuid.h
@@ -0,0 +1,17 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_SETUID_H
+#define TOR_SETUID_H
+
+int have_capability_support(void);
+
+/** Flag for switch_id; see switch_id() for documentation */
+#define SWITCH_ID_KEEP_BINDLOW (1<<0)
+/** Flag for switch_id; see switch_id() for documentation */
+#define SWITCH_ID_WARN_IF_NO_CAPS (1<<1)
+int switch_id(const char *user, unsigned flags);
+
+#endif
diff --git a/src/lib/process/subprocess.c b/src/lib/process/subprocess.c
new file mode 100644
index 0000000000..516494d105
--- /dev/null
+++ b/src/lib/process/subprocess.c
@@ -0,0 +1,1231 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define SUBPROCESS_PRIVATE
+#include "lib/process/subprocess.h"
+
+#include "lib/container/smartlist.h"
+#include "lib/err/torerr.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/log/win32err.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/process/env.h"
+#include "lib/process/waitpid.h"
+#include "lib/string/compat_ctype.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#include <errno.h>
+#include <string.h>
+
+/** Format a single argument for being put on a Windows command line.
+ * Returns a newly allocated string */
+static char *
+format_win_cmdline_argument(const char *arg)
+{
+ char *formatted_arg;
+ char need_quotes;
+ const char *c;
+ int i;
+ int bs_counter = 0;
+ /* Backslash we can point to when one is inserted into the string */
+ const char backslash = '\\';
+
+ /* Smartlist of *char */
+ smartlist_t *arg_chars;
+ arg_chars = smartlist_new();
+
+ /* Quote string if it contains whitespace or is empty */
+ need_quotes = (strchr(arg, ' ') || strchr(arg, '\t') || '\0' == arg[0]);
+
+ /* Build up smartlist of *chars */
+ for (c=arg; *c != '\0'; c++) {
+ if ('"' == *c) {
+ /* Double up backslashes preceding a quote */
+ for (i=0; i<(bs_counter*2); i++)
+ smartlist_add(arg_chars, (void*)&backslash);
+ bs_counter = 0;
+ /* Escape the quote */
+ smartlist_add(arg_chars, (void*)&backslash);
+ smartlist_add(arg_chars, (void*)c);
+ } else if ('\\' == *c) {
+ /* Count backslashes until we know whether to double up */
+ bs_counter++;
+ } else {
+ /* Don't double up slashes preceding a non-quote */
+ for (i=0; i<bs_counter; i++)
+ smartlist_add(arg_chars, (void*)&backslash);
+ bs_counter = 0;
+ smartlist_add(arg_chars, (void*)c);
+ }
+ }
+ /* Don't double up trailing backslashes */
+ for (i=0; i<bs_counter; i++)
+ smartlist_add(arg_chars, (void*)&backslash);
+
+ /* Allocate space for argument, quotes (if needed), and terminator */
+ const size_t formatted_arg_len = smartlist_len(arg_chars) +
+ (need_quotes ? 2 : 0) + 1;
+ formatted_arg = tor_malloc_zero(formatted_arg_len);
+
+ /* Add leading quote */
+ i=0;
+ if (need_quotes)
+ formatted_arg[i++] = '"';
+
+ /* Add characters */
+ SMARTLIST_FOREACH(arg_chars, char*, ch,
+ {
+ formatted_arg[i++] = *ch;
+ });
+
+ /* Add trailing quote */
+ if (need_quotes)
+ formatted_arg[i++] = '"';
+ formatted_arg[i] = '\0';
+
+ smartlist_free(arg_chars);
+ return formatted_arg;
+}
+
+/** Format a command line for use on Windows, which takes the command as a
+ * string rather than string array. Follows the rules from "Parsing C++
+ * Command-Line Arguments" in MSDN. Algorithm based on list2cmdline in the
+ * Python subprocess module. Returns a newly allocated string */
+char *
+tor_join_win_cmdline(const char *argv[])
+{
+ smartlist_t *argv_list;
+ char *joined_argv;
+ int i;
+
+ /* Format each argument and put the result in a smartlist */
+ argv_list = smartlist_new();
+ for (i=0; argv[i] != NULL; i++) {
+ smartlist_add(argv_list, (void *)format_win_cmdline_argument(argv[i]));
+ }
+
+ /* Join the arguments with whitespace */
+ joined_argv = smartlist_join_strings(argv_list, " ", 0, NULL);
+
+ /* Free the newly allocated arguments, and the smartlist */
+ SMARTLIST_FOREACH(argv_list, char *, arg,
+ {
+ tor_free(arg);
+ });
+ smartlist_free(argv_list);
+
+ return joined_argv;
+}
+
+#ifndef _WIN32
+/** Format <b>child_state</b> and <b>saved_errno</b> as a hex string placed in
+ * <b>hex_errno</b>. Called between fork and _exit, so must be signal-handler
+ * safe.
+ *
+ * <b>hex_errno</b> must have at least HEX_ERRNO_SIZE+1 bytes available.
+ *
+ * The format of <b>hex_errno</b> is: "CHILD_STATE/ERRNO\n", left-padded
+ * with spaces. CHILD_STATE indicates where
+ * in the process of starting the child process did the failure occur (see
+ * CHILD_STATE_* macros for definition), and SAVED_ERRNO is the value of
+ * errno when the failure occurred.
+ *
+ * On success return the number of characters added to hex_errno, not counting
+ * the terminating NUL; return -1 on error.
+ */
+STATIC int
+format_helper_exit_status(unsigned char child_state, int saved_errno,
+ char *hex_errno)
+{
+ unsigned int unsigned_errno;
+ int written, left;
+ char *cur;
+ size_t i;
+ int res = -1;
+
+ /* Fill hex_errno with spaces, and a trailing newline (memset may
+ not be signal handler safe, so we can't use it) */
+ for (i = 0; i < (HEX_ERRNO_SIZE - 1); i++)
+ hex_errno[i] = ' ';
+ hex_errno[HEX_ERRNO_SIZE - 1] = '\n';
+
+ /* Convert errno to be unsigned for hex conversion */
+ if (saved_errno < 0) {
+ // Avoid overflow on the cast to unsigned int when result is INT_MIN
+ // by adding 1 to the signed int negative value,
+ // then, after it has been negated and cast to unsigned,
+ // adding the original 1 back (the double-addition is intentional).
+ // Otherwise, the cast to signed could cause a temporary int
+ // to equal INT_MAX + 1, which is undefined.
+ unsigned_errno = ((unsigned int) -(saved_errno + 1)) + 1;
+ } else {
+ unsigned_errno = (unsigned int) saved_errno;
+ }
+
+ /*
+ * Count how many chars of space we have left, and keep a pointer into the
+ * current point in the buffer.
+ */
+ left = HEX_ERRNO_SIZE+1;
+ cur = hex_errno;
+
+ /* Emit child_state */
+ written = format_hex_number_sigsafe(child_state, cur, left);
+
+ if (written <= 0)
+ goto err;
+
+ /* Adjust left and cur */
+ left -= written;
+ cur += written;
+ if (left <= 0)
+ goto err;
+
+ /* Now the '/' */
+ *cur = '/';
+
+ /* Adjust left and cur */
+ ++cur;
+ --left;
+ if (left <= 0)
+ goto err;
+
+ /* Need minus? */
+ if (saved_errno < 0) {
+ *cur = '-';
+ ++cur;
+ --left;
+ if (left <= 0)
+ goto err;
+ }
+
+ /* Emit unsigned_errno */
+ written = format_hex_number_sigsafe(unsigned_errno, cur, left);
+
+ if (written <= 0)
+ goto err;
+
+ /* Adjust left and cur */
+ left -= written;
+ cur += written;
+
+ /* Check that we have enough space left for a newline and a NUL */
+ if (left <= 1)
+ goto err;
+
+ /* Emit the newline and NUL */
+ *cur++ = '\n';
+ *cur++ = '\0';
+
+ res = (int)(cur - hex_errno - 1);
+
+ goto done;
+
+ err:
+ /*
+ * In error exit, just write a '\0' in the first char so whatever called
+ * this at least won't fall off the end.
+ */
+ *hex_errno = '\0';
+
+ done:
+ return res;
+}
+#endif /* !defined(_WIN32) */
+
+/* Maximum number of file descriptors, if we cannot get it via sysconf() */
+#define DEFAULT_MAX_FD 256
+
+/** Terminate the process of <b>process_handle</b>, if that process has not
+ * already exited.
+ *
+ * Return 0 if we succeeded in terminating the process (or if the process
+ * already exited), and -1 if we tried to kill the process but failed.
+ *
+ * Based on code originally borrowed from Python's os.kill. */
+int
+tor_terminate_process(process_handle_t *process_handle)
+{
+#ifdef _WIN32
+ if (tor_get_exit_code(process_handle, 0, NULL) == PROCESS_EXIT_RUNNING) {
+ HANDLE handle = process_handle->pid.hProcess;
+
+ if (!TerminateProcess(handle, 0))
+ return -1;
+ else
+ return 0;
+ }
+#else /* !(defined(_WIN32)) */
+ if (process_handle->waitpid_cb) {
+ /* We haven't got a waitpid yet, so we can just kill off the process. */
+ return kill(process_handle->pid, SIGTERM);
+ }
+#endif /* defined(_WIN32) */
+
+ return 0; /* We didn't need to kill the process, so report success */
+}
+
+/** Return the Process ID of <b>process_handle</b>. */
+int
+tor_process_get_pid(process_handle_t *process_handle)
+{
+#ifdef _WIN32
+ return (int) process_handle->pid.dwProcessId;
+#else
+ return (int) process_handle->pid;
+#endif
+}
+
+#ifdef _WIN32
+HANDLE
+tor_process_get_stdout_pipe(process_handle_t *process_handle)
+{
+ return process_handle->stdout_pipe;
+}
+#else /* !(defined(_WIN32)) */
+/* DOCDOC tor_process_get_stdout_pipe */
+int
+tor_process_get_stdout_pipe(process_handle_t *process_handle)
+{
+ return process_handle->stdout_pipe;
+}
+#endif /* defined(_WIN32) */
+
+/* DOCDOC process_handle_new */
+static process_handle_t *
+process_handle_new(void)
+{
+ process_handle_t *out = tor_malloc_zero(sizeof(process_handle_t));
+
+#ifdef _WIN32
+ out->stdin_pipe = INVALID_HANDLE_VALUE;
+ out->stdout_pipe = INVALID_HANDLE_VALUE;
+ out->stderr_pipe = INVALID_HANDLE_VALUE;
+#else
+ out->stdin_pipe = -1;
+ out->stdout_pipe = -1;
+ out->stderr_pipe = -1;
+#endif /* defined(_WIN32) */
+
+ return out;
+}
+
+#ifndef _WIN32
+/** Invoked when a process that we've launched via tor_spawn_background() has
+ * been found to have terminated.
+ */
+static void
+process_handle_waitpid_cb(int status, void *arg)
+{
+ process_handle_t *process_handle = arg;
+
+ process_handle->waitpid_exit_status = status;
+ clear_waitpid_callback(process_handle->waitpid_cb);
+ if (process_handle->status == PROCESS_STATUS_RUNNING)
+ process_handle->status = PROCESS_STATUS_NOTRUNNING;
+ process_handle->waitpid_cb = 0;
+}
+#endif /* !defined(_WIN32) */
+
+/**
+ * @name child-process states
+ *
+ * Each of these values represents a possible state that a child process can
+ * be in. They're used to determine what to say when telling the parent how
+ * far along we were before failure.
+ *
+ * @{
+ */
+#define CHILD_STATE_INIT 0
+#define CHILD_STATE_PIPE 1
+#define CHILD_STATE_MAXFD 2
+#define CHILD_STATE_FORK 3
+#define CHILD_STATE_DUPOUT 4
+#define CHILD_STATE_DUPERR 5
+#define CHILD_STATE_DUPIN 6
+#define CHILD_STATE_CLOSEFD 7
+#define CHILD_STATE_EXEC 8
+#define CHILD_STATE_FAILEXEC 9
+/** @} */
+/**
+ * Boolean. If true, then Tor may call execve or CreateProcess via
+ * tor_spawn_background.
+ **/
+static int may_spawn_background_process = 1;
+/**
+ * Turn off may_spawn_background_process, so that all future calls to
+ * tor_spawn_background are guaranteed to fail.
+ **/
+void
+tor_disable_spawning_background_processes(void)
+{
+ may_spawn_background_process = 0;
+}
+/** Start a program in the background. If <b>filename</b> contains a '/', then
+ * it will be treated as an absolute or relative path. Otherwise, on
+ * non-Windows systems, the system path will be searched for <b>filename</b>.
+ * On Windows, only the current directory will be searched. Here, to search the
+ * system path (as well as the application directory, current working
+ * directory, and system directories), set filename to NULL.
+ *
+ * The strings in <b>argv</b> will be passed as the command line arguments of
+ * the child program (following convention, argv[0] should normally be the
+ * filename of the executable, and this must be the case if <b>filename</b> is
+ * NULL). The last element of argv must be NULL. A handle to the child process
+ * will be returned in process_handle (which must be non-NULL). Read
+ * process_handle.status to find out if the process was successfully launched.
+ * For convenience, process_handle.status is returned by this function.
+ *
+ * Some parts of this code are based on the POSIX subprocess module from
+ * Python, and example code from
+ * http://msdn.microsoft.com/en-us/library/ms682499%28v=vs.85%29.aspx.
+ */
+int
+tor_spawn_background(const char *const filename, const char **argv,
+ process_environment_t *env,
+ process_handle_t **process_handle_out)
+{
+ if (BUG(may_spawn_background_process == 0)) {
+ /* We should never reach this point if we're forbidden to spawn
+ * processes. Instead we should have caught the attempt earlier. */
+ return PROCESS_STATUS_ERROR;
+ }
+
+#ifdef _WIN32
+ HANDLE stdout_pipe_read = NULL;
+ HANDLE stdout_pipe_write = NULL;
+ HANDLE stderr_pipe_read = NULL;
+ HANDLE stderr_pipe_write = NULL;
+ HANDLE stdin_pipe_read = NULL;
+ HANDLE stdin_pipe_write = NULL;
+ process_handle_t *process_handle;
+ int status;
+
+ STARTUPINFOA siStartInfo;
+ BOOL retval = FALSE;
+
+ SECURITY_ATTRIBUTES saAttr;
+ char *joined_argv;
+
+ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ saAttr.bInheritHandle = TRUE;
+ /* TODO: should we set explicit security attributes? (#2046, comment 5) */
+ saAttr.lpSecurityDescriptor = NULL;
+
+ /* Assume failure to start process */
+ status = PROCESS_STATUS_ERROR;
+
+ /* Set up pipe for stdout */
+ if (!CreatePipe(&stdout_pipe_read, &stdout_pipe_write, &saAttr, 0)) {
+ log_warn(LD_GENERAL,
+ "Failed to create pipe for stdout communication with child process: %s",
+ format_win32_error(GetLastError()));
+ return status;
+ }
+ if (!SetHandleInformation(stdout_pipe_read, HANDLE_FLAG_INHERIT, 0)) {
+ log_warn(LD_GENERAL,
+ "Failed to configure pipe for stdout communication with child "
+ "process: %s", format_win32_error(GetLastError()));
+ return status;
+ }
+
+ /* Set up pipe for stderr */
+ if (!CreatePipe(&stderr_pipe_read, &stderr_pipe_write, &saAttr, 0)) {
+ log_warn(LD_GENERAL,
+ "Failed to create pipe for stderr communication with child process: %s",
+ format_win32_error(GetLastError()));
+ return status;
+ }
+ if (!SetHandleInformation(stderr_pipe_read, HANDLE_FLAG_INHERIT, 0)) {
+ log_warn(LD_GENERAL,
+ "Failed to configure pipe for stderr communication with child "
+ "process: %s", format_win32_error(GetLastError()));
+ return status;
+ }
+
+ /* Set up pipe for stdin */
+ if (!CreatePipe(&stdin_pipe_read, &stdin_pipe_write, &saAttr, 0)) {
+ log_warn(LD_GENERAL,
+ "Failed to create pipe for stdin communication with child process: %s",
+ format_win32_error(GetLastError()));
+ return status;
+ }
+ if (!SetHandleInformation(stdin_pipe_write, HANDLE_FLAG_INHERIT, 0)) {
+ log_warn(LD_GENERAL,
+ "Failed to configure pipe for stdin communication with child "
+ "process: %s", format_win32_error(GetLastError()));
+ return status;
+ }
+
+ /* Create the child process */
+
+ /* Windows expects argv to be a whitespace delimited string, so join argv up
+ */
+ joined_argv = tor_join_win_cmdline(argv);
+
+ process_handle = process_handle_new();
+ process_handle->status = status;
+
+ ZeroMemory(&(process_handle->pid), sizeof(PROCESS_INFORMATION));
+ ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
+ siStartInfo.cb = sizeof(STARTUPINFO);
+ siStartInfo.hStdError = stderr_pipe_write;
+ siStartInfo.hStdOutput = stdout_pipe_write;
+ siStartInfo.hStdInput = stdin_pipe_read;
+ siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
+
+ /* Create the child process */
+
+ retval = CreateProcessA(filename, // module name
+ joined_argv, // command line
+ /* TODO: should we set explicit security attributes? (#2046, comment 5) */
+ NULL, // process security attributes
+ NULL, // primary thread security attributes
+ TRUE, // handles are inherited
+ /*(TODO: set CREATE_NEW CONSOLE/PROCESS_GROUP to make GetExitCodeProcess()
+ * work?) */
+ CREATE_NO_WINDOW, // creation flags
+ (env==NULL) ? NULL : env->windows_environment_block,
+ NULL, // use parent's current directory
+ &siStartInfo, // STARTUPINFO pointer
+ &(process_handle->pid)); // receives PROCESS_INFORMATION
+
+ tor_free(joined_argv);
+
+ if (!retval) {
+ log_warn(LD_GENERAL,
+ "Failed to create child process %s: %s", filename?filename:argv[0],
+ format_win32_error(GetLastError()));
+ tor_free(process_handle);
+ } else {
+ /* TODO: Close hProcess and hThread in process_handle->pid? */
+ process_handle->stdout_pipe = stdout_pipe_read;
+ process_handle->stderr_pipe = stderr_pipe_read;
+ process_handle->stdin_pipe = stdin_pipe_write;
+ status = process_handle->status = PROCESS_STATUS_RUNNING;
+ }
+
+ /* TODO: Close pipes on exit */
+ *process_handle_out = process_handle;
+ return status;
+#else /* !(defined(_WIN32)) */
+ pid_t pid;
+ int stdout_pipe[2];
+ int stderr_pipe[2];
+ int stdin_pipe[2];
+ int fd, retval;
+ process_handle_t *process_handle;
+ int status;
+
+ const char *error_message = SPAWN_ERROR_MESSAGE;
+ size_t error_message_length;
+
+ /* Represents where in the process of spawning the program is;
+ this is used for printing out the error message */
+ unsigned char child_state = CHILD_STATE_INIT;
+
+ char hex_errno[HEX_ERRNO_SIZE + 2]; /* + 1 should be sufficient actually */
+
+ static int max_fd = -1;
+
+ status = PROCESS_STATUS_ERROR;
+
+ /* We do the strlen here because strlen() is not signal handler safe,
+ and we are not allowed to use unsafe functions between fork and exec */
+ error_message_length = strlen(error_message);
+
+ // child_state = CHILD_STATE_PIPE;
+
+ /* Set up pipe for redirecting stdout, stderr, and stdin of child */
+ retval = pipe(stdout_pipe);
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to set up pipe for stdout communication with child process: %s",
+ strerror(errno));
+ return status;
+ }
+
+ retval = pipe(stderr_pipe);
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to set up pipe for stderr communication with child process: %s",
+ strerror(errno));
+
+ close(stdout_pipe[0]);
+ close(stdout_pipe[1]);
+
+ return status;
+ }
+
+ retval = pipe(stdin_pipe);
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to set up pipe for stdin communication with child process: %s",
+ strerror(errno));
+
+ close(stdout_pipe[0]);
+ close(stdout_pipe[1]);
+ close(stderr_pipe[0]);
+ close(stderr_pipe[1]);
+
+ return status;
+ }
+
+ // child_state = CHILD_STATE_MAXFD;
+
+#ifdef _SC_OPEN_MAX
+ if (-1 == max_fd) {
+ max_fd = (int) sysconf(_SC_OPEN_MAX);
+ if (max_fd == -1) {
+ max_fd = DEFAULT_MAX_FD;
+ log_warn(LD_GENERAL,
+ "Cannot find maximum file descriptor, assuming %d", max_fd);
+ }
+ }
+#else /* !(defined(_SC_OPEN_MAX)) */
+ max_fd = DEFAULT_MAX_FD;
+#endif /* defined(_SC_OPEN_MAX) */
+
+ // child_state = CHILD_STATE_FORK;
+
+ pid = fork();
+ if (0 == pid) {
+ /* In child */
+
+#if defined(HAVE_SYS_PRCTL_H) && defined(__linux__)
+ /* Attempt to have the kernel issue a SIGTERM if the parent
+ * goes away. Certain attributes of the binary being execve()ed
+ * will clear this during the execve() call, but it's better
+ * than nothing.
+ */
+ prctl(PR_SET_PDEATHSIG, SIGTERM);
+#endif /* defined(HAVE_SYS_PRCTL_H) && defined(__linux__) */
+
+ child_state = CHILD_STATE_DUPOUT;
+
+ /* Link child stdout to the write end of the pipe */
+ retval = dup2(stdout_pipe[1], STDOUT_FILENO);
+ if (-1 == retval)
+ goto error;
+
+ child_state = CHILD_STATE_DUPERR;
+
+ /* Link child stderr to the write end of the pipe */
+ retval = dup2(stderr_pipe[1], STDERR_FILENO);
+ if (-1 == retval)
+ goto error;
+
+ child_state = CHILD_STATE_DUPIN;
+
+ /* Link child stdin to the read end of the pipe */
+ retval = dup2(stdin_pipe[0], STDIN_FILENO);
+ if (-1 == retval)
+ goto error;
+
+ // child_state = CHILD_STATE_CLOSEFD;
+
+ close(stderr_pipe[0]);
+ close(stderr_pipe[1]);
+ close(stdout_pipe[0]);
+ close(stdout_pipe[1]);
+ close(stdin_pipe[0]);
+ close(stdin_pipe[1]);
+
+ /* Close all other fds, including the read end of the pipe */
+ /* XXX: We should now be doing enough FD_CLOEXEC setting to make
+ * this needless. */
+ for (fd = STDERR_FILENO + 1; fd < max_fd; fd++) {
+ close(fd);
+ }
+
+ // child_state = CHILD_STATE_EXEC;
+
+ /* Call the requested program. We need the cast because
+ execvp doesn't define argv as const, even though it
+ does not modify the arguments */
+ if (env)
+ execve(filename, (char *const *) argv, env->unixoid_environment_block);
+ else {
+ static char *new_env[] = { NULL };
+ execve(filename, (char *const *) argv, new_env);
+ }
+
+ /* If we got here, the exec or open(/dev/null) failed */
+
+ child_state = CHILD_STATE_FAILEXEC;
+
+ error:
+ {
+ /* XXX: are we leaking fds from the pipe? */
+ int n, err=0;
+ ssize_t nbytes;
+
+ n = format_helper_exit_status(child_state, errno, hex_errno);
+
+ if (n >= 0) {
+ /* Write the error message. GCC requires that we check the return
+ value, but there is nothing we can do if it fails */
+ /* TODO: Don't use STDOUT, use a pipe set up just for this purpose */
+ nbytes = write(STDOUT_FILENO, error_message, error_message_length);
+ err = (nbytes < 0);
+ nbytes = write(STDOUT_FILENO, hex_errno, n);
+ err += (nbytes < 0);
+ }
+
+ _exit(err?254:255); // exit ok: in child.
+ }
+
+ /* Never reached, but avoids compiler warning */
+ return status; // LCOV_EXCL_LINE
+ }
+
+ /* In parent */
+
+ if (-1 == pid) {
+ log_warn(LD_GENERAL, "Failed to fork child process: %s", strerror(errno));
+ close(stdin_pipe[0]);
+ close(stdin_pipe[1]);
+ close(stdout_pipe[0]);
+ close(stdout_pipe[1]);
+ close(stderr_pipe[0]);
+ close(stderr_pipe[1]);
+ return status;
+ }
+
+ process_handle = process_handle_new();
+ process_handle->status = status;
+ process_handle->pid = pid;
+
+ /* TODO: If the child process forked but failed to exec, waitpid it */
+
+ /* Return read end of the pipes to caller, and close write end */
+ process_handle->stdout_pipe = stdout_pipe[0];
+ retval = close(stdout_pipe[1]);
+
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to close write end of stdout pipe in parent process: %s",
+ strerror(errno));
+ }
+
+ process_handle->waitpid_cb = set_waitpid_callback(pid,
+ process_handle_waitpid_cb,
+ process_handle);
+
+ process_handle->stderr_pipe = stderr_pipe[0];
+ retval = close(stderr_pipe[1]);
+
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to close write end of stderr pipe in parent process: %s",
+ strerror(errno));
+ }
+
+ /* Return write end of the stdin pipe to caller, and close the read end */
+ process_handle->stdin_pipe = stdin_pipe[1];
+ retval = close(stdin_pipe[0]);
+
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to close read end of stdin pipe in parent process: %s",
+ strerror(errno));
+ }
+
+ status = process_handle->status = PROCESS_STATUS_RUNNING;
+ /* Set stdin/stdout/stderr pipes to be non-blocking */
+ if (fcntl(process_handle->stdout_pipe, F_SETFL, O_NONBLOCK) < 0 ||
+ fcntl(process_handle->stderr_pipe, F_SETFL, O_NONBLOCK) < 0 ||
+ fcntl(process_handle->stdin_pipe, F_SETFL, O_NONBLOCK) < 0) {
+ log_warn(LD_GENERAL, "Failed to set stderror/stdout/stdin pipes "
+ "nonblocking in parent process: %s", strerror(errno));
+ }
+
+ *process_handle_out = process_handle;
+ return status;
+#endif /* defined(_WIN32) */
+}
+
+/** Destroy all resources allocated by the process handle in
+ * <b>process_handle</b>.
+ * If <b>also_terminate_process</b> is true, also terminate the
+ * process of the process handle. */
+MOCK_IMPL(void,
+tor_process_handle_destroy,(process_handle_t *process_handle,
+ int also_terminate_process))
+{
+ if (!process_handle)
+ return;
+
+ if (also_terminate_process) {
+ if (tor_terminate_process(process_handle) < 0) {
+ const char *errstr =
+#ifdef _WIN32
+ format_win32_error(GetLastError());
+#else
+ strerror(errno);
+#endif
+ log_notice(LD_GENERAL, "Failed to terminate process with "
+ "PID '%d' ('%s').", tor_process_get_pid(process_handle),
+ errstr);
+ } else {
+ log_info(LD_GENERAL, "Terminated process with PID '%d'.",
+ tor_process_get_pid(process_handle));
+ }
+ }
+
+ process_handle->status = PROCESS_STATUS_NOTRUNNING;
+
+#ifdef _WIN32
+ if (process_handle->stdout_pipe)
+ CloseHandle(process_handle->stdout_pipe);
+
+ if (process_handle->stderr_pipe)
+ CloseHandle(process_handle->stderr_pipe);
+
+ if (process_handle->stdin_pipe)
+ CloseHandle(process_handle->stdin_pipe);
+#else /* !(defined(_WIN32)) */
+ close(process_handle->stdout_pipe);
+ close(process_handle->stderr_pipe);
+ close(process_handle->stdin_pipe);
+
+ clear_waitpid_callback(process_handle->waitpid_cb);
+#endif /* defined(_WIN32) */
+
+ memset(process_handle, 0x0f, sizeof(process_handle_t));
+ tor_free(process_handle);
+}
+
+/** Get the exit code of a process specified by <b>process_handle</b> and store
+ * it in <b>exit_code</b>, if set to a non-NULL value. If <b>block</b> is set
+ * to true, the call will block until the process has exited. Otherwise if
+ * the process is still running, the function will return
+ * PROCESS_EXIT_RUNNING, and exit_code will be left unchanged. Returns
+ * PROCESS_EXIT_EXITED if the process did exit. If there is a failure,
+ * PROCESS_EXIT_ERROR will be returned and the contents of exit_code (if
+ * non-NULL) will be undefined. N.B. Under *nix operating systems, this will
+ * probably not work in Tor, because waitpid() is called in main.c to reap any
+ * terminated child processes.*/
+int
+tor_get_exit_code(process_handle_t *process_handle,
+ int block, int *exit_code)
+{
+#ifdef _WIN32
+ DWORD retval;
+ BOOL success;
+
+ if (block) {
+ /* Wait for the process to exit */
+ retval = WaitForSingleObject(process_handle->pid.hProcess, INFINITE);
+ if (retval != WAIT_OBJECT_0) {
+ log_warn(LD_GENERAL, "WaitForSingleObject() failed (%d): %s",
+ (int)retval, format_win32_error(GetLastError()));
+ return PROCESS_EXIT_ERROR;
+ }
+ } else {
+ retval = WaitForSingleObject(process_handle->pid.hProcess, 0);
+ if (WAIT_TIMEOUT == retval) {
+ /* Process has not exited */
+ return PROCESS_EXIT_RUNNING;
+ } else if (retval != WAIT_OBJECT_0) {
+ log_warn(LD_GENERAL, "WaitForSingleObject() failed (%d): %s",
+ (int)retval, format_win32_error(GetLastError()));
+ return PROCESS_EXIT_ERROR;
+ }
+ }
+
+ if (exit_code != NULL) {
+ success = GetExitCodeProcess(process_handle->pid.hProcess,
+ (PDWORD)exit_code);
+ if (!success) {
+ log_warn(LD_GENERAL, "GetExitCodeProcess() failed: %s",
+ format_win32_error(GetLastError()));
+ return PROCESS_EXIT_ERROR;
+ }
+ }
+#else /* !(defined(_WIN32)) */
+ int stat_loc;
+ int retval;
+
+ if (process_handle->waitpid_cb) {
+ /* We haven't processed a SIGCHLD yet. */
+ retval = waitpid(process_handle->pid, &stat_loc, block?0:WNOHANG);
+ if (retval == process_handle->pid) {
+ clear_waitpid_callback(process_handle->waitpid_cb);
+ process_handle->waitpid_cb = NULL;
+ process_handle->waitpid_exit_status = stat_loc;
+ }
+ } else {
+ /* We already got a SIGCHLD for this process, and handled it. */
+ retval = process_handle->pid;
+ stat_loc = process_handle->waitpid_exit_status;
+ }
+
+ if (!block && 0 == retval) {
+ /* Process has not exited */
+ return PROCESS_EXIT_RUNNING;
+ } else if (retval != process_handle->pid) {
+ log_warn(LD_GENERAL, "waitpid() failed for PID %d: %s",
+ (int)process_handle->pid, strerror(errno));
+ return PROCESS_EXIT_ERROR;
+ }
+
+ if (!WIFEXITED(stat_loc)) {
+ log_warn(LD_GENERAL, "Process %d did not exit normally",
+ (int)process_handle->pid);
+ return PROCESS_EXIT_ERROR;
+ }
+
+ if (exit_code != NULL)
+ *exit_code = WEXITSTATUS(stat_loc);
+#endif /* defined(_WIN32) */
+
+ return PROCESS_EXIT_EXITED;
+}
+
+#ifdef _WIN32
+/** Read from a handle <b>h</b> into <b>buf</b>, up to <b>count</b> bytes. If
+ * <b>hProcess</b> is NULL, the function will return immediately if there is
+ * nothing more to read. Otherwise <b>hProcess</b> should be set to the handle
+ * to the process owning the <b>h</b>. In this case, the function will exit
+ * only once the process has exited, or <b>count</b> bytes are read. Returns
+ * the number of bytes read, or -1 on error. */
+ssize_t
+tor_read_all_handle(HANDLE h, char *buf, size_t count,
+ const process_handle_t *process)
+{
+ size_t numread = 0;
+ BOOL retval;
+ DWORD byte_count;
+ BOOL process_exited = FALSE;
+
+ if (count > SIZE_T_CEILING || count > SSIZE_MAX)
+ return -1;
+
+ while (numread < count) {
+ /* Check if there is anything to read */
+ retval = PeekNamedPipe(h, NULL, 0, NULL, &byte_count, NULL);
+ if (!retval) {
+ log_warn(LD_GENERAL,
+ "Failed to peek from handle: %s",
+ format_win32_error(GetLastError()));
+ return -1;
+ } else if (0 == byte_count) {
+ /* Nothing available: process exited or it is busy */
+
+ /* Exit if we don't know whether the process is running */
+ if (NULL == process)
+ break;
+
+ /* The process exited and there's nothing left to read from it */
+ if (process_exited)
+ break;
+
+ /* If process is not running, check for output one more time in case
+ it wrote something after the peek was performed. Otherwise keep on
+ waiting for output */
+ tor_assert(process != NULL);
+ byte_count = WaitForSingleObject(process->pid.hProcess, 0);
+ if (WAIT_TIMEOUT != byte_count)
+ process_exited = TRUE;
+
+ continue;
+ }
+
+ /* There is data to read; read it */
+ retval = ReadFile(h, buf+numread, count-numread, &byte_count, NULL);
+ tor_assert(byte_count + numread <= count);
+ if (!retval) {
+ log_warn(LD_GENERAL, "Failed to read from handle: %s",
+ format_win32_error(GetLastError()));
+ return -1;
+ } else if (0 == byte_count) {
+ /* End of file */
+ break;
+ }
+ numread += byte_count;
+ }
+ return (ssize_t)numread;
+}
+#else /* !(defined(_WIN32)) */
+/** Read from a handle <b>fd</b> into <b>buf</b>, up to <b>count</b> bytes. If
+ * <b>process</b> is NULL, the function will return immediately if there is
+ * nothing more to read. Otherwise data will be read until end of file, or
+ * <b>count</b> bytes are read. Returns the number of bytes read, or -1 on
+ * error. Sets <b>eof</b> to true if <b>eof</b> is not NULL and the end of the
+ * file has been reached. */
+ssize_t
+tor_read_all_handle(int fd, char *buf, size_t count,
+ const process_handle_t *process,
+ int *eof)
+{
+ size_t numread = 0;
+ ssize_t result;
+
+ if (eof)
+ *eof = 0;
+
+ if (count > SIZE_T_CEILING || count > SSIZE_MAX)
+ return -1;
+
+ while (numread < count) {
+ result = read(fd, buf+numread, count-numread);
+
+ if (result == 0) {
+ log_debug(LD_GENERAL, "read() reached end of file");
+ if (eof)
+ *eof = 1;
+ break;
+ } else if (result < 0 && errno == EAGAIN) {
+ if (process)
+ continue;
+ else
+ break;
+ } else if (result < 0) {
+ log_warn(LD_GENERAL, "read() failed: %s", strerror(errno));
+ return -1;
+ }
+
+ numread += result;
+ }
+
+ log_debug(LD_GENERAL, "read() read %d bytes from handle", (int)numread);
+ return (ssize_t)numread;
+}
+#endif /* defined(_WIN32) */
+
+/** Read from stdout of a process until the process exits. */
+ssize_t
+tor_read_all_from_process_stdout(const process_handle_t *process_handle,
+ char *buf, size_t count)
+{
+#ifdef _WIN32
+ return tor_read_all_handle(process_handle->stdout_pipe, buf, count,
+ process_handle);
+#else
+ return tor_read_all_handle(process_handle->stdout_pipe, buf, count,
+ process_handle, NULL);
+#endif /* defined(_WIN32) */
+}
+
+/** Read from stdout of a process until the process exits. */
+ssize_t
+tor_read_all_from_process_stderr(const process_handle_t *process_handle,
+ char *buf, size_t count)
+{
+#ifdef _WIN32
+ return tor_read_all_handle(process_handle->stderr_pipe, buf, count,
+ process_handle);
+#else
+ return tor_read_all_handle(process_handle->stderr_pipe, buf, count,
+ process_handle, NULL);
+#endif /* defined(_WIN32) */
+}
+
+/** Return a string corresponding to <b>stream_status</b>. */
+const char *
+stream_status_to_string(enum stream_status stream_status)
+{
+ switch (stream_status) {
+ case IO_STREAM_OKAY:
+ return "okay";
+ case IO_STREAM_EAGAIN:
+ return "temporarily unavailable";
+ case IO_STREAM_TERM:
+ return "terminated";
+ case IO_STREAM_CLOSED:
+ return "closed";
+ default:
+ tor_fragile_assert();
+ return "unknown";
+ }
+}
+
+/** Split buf into lines, and add to smartlist. The buffer <b>buf</b> will be
+ * modified. The resulting smartlist will consist of pointers to buf, so there
+ * is no need to free the contents of sl. <b>buf</b> must be a NUL-terminated
+ * string. <b>len</b> should be set to the length of the buffer excluding the
+ * NUL. Non-printable characters (including NUL) will be replaced with "." */
+int
+tor_split_lines(smartlist_t *sl, char *buf, int len)
+{
+ /* Index in buf of the start of the current line */
+ int start = 0;
+ /* Index in buf of the current character being processed */
+ int cur = 0;
+ /* Are we currently in a line */
+ char in_line = 0;
+
+ /* Loop over string */
+ while (cur < len) {
+ /* Loop until end of line or end of string */
+ for (; cur < len; cur++) {
+ if (in_line) {
+ if ('\r' == buf[cur] || '\n' == buf[cur]) {
+ /* End of line */
+ buf[cur] = '\0';
+ /* Point cur to the next line */
+ cur++;
+ /* Line starts at start and ends with a nul */
+ break;
+ } else {
+ if (!TOR_ISPRINT(buf[cur]))
+ buf[cur] = '.';
+ }
+ } else {
+ if ('\r' == buf[cur] || '\n' == buf[cur]) {
+ /* Skip leading vertical space */
+ ;
+ } else {
+ in_line = 1;
+ start = cur;
+ if (!TOR_ISPRINT(buf[cur]))
+ buf[cur] = '.';
+ }
+ }
+ }
+ /* We are at the end of the line or end of string. If in_line is true there
+ * is a line which starts at buf+start and ends at a NUL. cur points to
+ * the character after the NUL. */
+ if (in_line)
+ smartlist_add(sl, (void *)(buf+start));
+ in_line = 0;
+ }
+ return smartlist_len(sl);
+}
+
+#ifdef _WIN32
+
+/** Return a smartlist containing lines outputted from
+ * <b>handle</b>. Return NULL on error, and set
+ * <b>stream_status_out</b> appropriately. */
+MOCK_IMPL(smartlist_t *,
+tor_get_lines_from_handle, (HANDLE *handle,
+ enum stream_status *stream_status_out))
+{
+ int pos;
+ char stdout_buf[600] = {0};
+ smartlist_t *lines = NULL;
+
+ tor_assert(stream_status_out);
+
+ *stream_status_out = IO_STREAM_TERM;
+
+ pos = tor_read_all_handle(handle, stdout_buf, sizeof(stdout_buf) - 1, NULL);
+ if (pos < 0) {
+ *stream_status_out = IO_STREAM_TERM;
+ return NULL;
+ }
+ if (pos == 0) {
+ *stream_status_out = IO_STREAM_EAGAIN;
+ return NULL;
+ }
+
+ /* End with a null even if there isn't a \r\n at the end */
+ /* TODO: What if this is a partial line? */
+ stdout_buf[pos] = '\0';
+
+ /* Split up the buffer */
+ lines = smartlist_new();
+ tor_split_lines(lines, stdout_buf, pos);
+
+ /* Currently 'lines' is populated with strings residing on the
+ stack. Replace them with their exact copies on the heap: */
+ SMARTLIST_FOREACH(lines, char *, line,
+ SMARTLIST_REPLACE_CURRENT(lines, line, tor_strdup(line)));
+
+ *stream_status_out = IO_STREAM_OKAY;
+
+ return lines;
+}
+
+#else /* !(defined(_WIN32)) */
+
+/** Return a smartlist containing lines outputted from
+ * <b>fd</b>. Return NULL on error, and set
+ * <b>stream_status_out</b> appropriately. */
+MOCK_IMPL(smartlist_t *,
+tor_get_lines_from_handle, (int fd, enum stream_status *stream_status_out))
+{
+ enum stream_status stream_status;
+ char stdout_buf[400];
+ smartlist_t *lines = NULL;
+
+ while (1) {
+ memset(stdout_buf, 0, sizeof(stdout_buf));
+
+ stream_status = get_string_from_pipe(fd,
+ stdout_buf, sizeof(stdout_buf) - 1);
+ if (stream_status != IO_STREAM_OKAY)
+ goto done;
+
+ if (!lines) lines = smartlist_new();
+ smartlist_split_string(lines, stdout_buf, "\n", 0, 0);
+ }
+
+ done:
+ *stream_status_out = stream_status;
+ return lines;
+}
+
+#endif /* defined(_WIN32) */
+
+/** Reads from <b>fd</b> and stores input in <b>buf_out</b> making
+ * sure it's below <b>count</b> bytes.
+ * If the string has a trailing newline, we strip it off.
+ *
+ * This function is specifically created to handle input from managed
+ * proxies, according to the pluggable transports spec. Make sure it
+ * fits your needs before using it.
+ *
+ * Returns:
+ * IO_STREAM_CLOSED: If the stream is closed.
+ * IO_STREAM_EAGAIN: If there is nothing to read and we should check back
+ * later.
+ * IO_STREAM_TERM: If something is wrong with the stream.
+ * IO_STREAM_OKAY: If everything went okay and we got a string
+ * in <b>buf_out</b>. */
+enum stream_status
+get_string_from_pipe(int fd, char *buf_out, size_t count)
+{
+ ssize_t ret;
+
+ tor_assert(count <= INT_MAX);
+
+ ret = read(fd, buf_out, count);
+
+ if (ret == 0)
+ return IO_STREAM_CLOSED;
+ else if (ret < 0 && errno == EAGAIN)
+ return IO_STREAM_EAGAIN;
+ else if (ret < 0)
+ return IO_STREAM_TERM;
+
+ if (buf_out[ret - 1] == '\n') {
+ /* Remove the trailing newline */
+ buf_out[ret - 1] = '\0';
+ } else
+ buf_out[ret] = '\0';
+
+ return IO_STREAM_OKAY;
+}
diff --git a/src/lib/process/subprocess.h b/src/lib/process/subprocess.h
new file mode 100644
index 0000000000..a319b3505c
--- /dev/null
+++ b/src/lib/process/subprocess.h
@@ -0,0 +1,129 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_SUBPROCESS_H
+#define TOR_SUBPROCESS_H
+
+#include "lib/cc/torint.h"
+#include "lib/testsupport/testsupport.h"
+#include <stddef.h>
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+struct smartlist_t;
+
+void tor_disable_spawning_background_processes(void);
+
+typedef struct process_handle_t process_handle_t;
+struct process_environment_t;
+int tor_spawn_background(const char *const filename, const char **argv,
+ struct process_environment_t *env,
+ process_handle_t **process_handle_out);
+
+#define SPAWN_ERROR_MESSAGE "ERR: Failed to spawn background process - code "
+
+/** Status of an I/O stream. */
+enum stream_status {
+ IO_STREAM_OKAY,
+ IO_STREAM_EAGAIN,
+ IO_STREAM_TERM,
+ IO_STREAM_CLOSED
+};
+
+const char *stream_status_to_string(enum stream_status stream_status);
+
+enum stream_status get_string_from_pipe(int fd, char *buf, size_t count);
+
+/* Values of process_handle_t.status. */
+#define PROCESS_STATUS_NOTRUNNING 0
+#define PROCESS_STATUS_RUNNING 1
+#define PROCESS_STATUS_ERROR -1
+
+#ifdef SUBPROCESS_PRIVATE
+struct waitpid_callback_t;
+
+/** Structure to represent the state of a process with which Tor is
+ * communicating. The contents of this structure are private to util.c */
+struct process_handle_t {
+ /** One of the PROCESS_STATUS_* values */
+ int status;
+#ifdef _WIN32
+ HANDLE stdin_pipe;
+ HANDLE stdout_pipe;
+ HANDLE stderr_pipe;
+ PROCESS_INFORMATION pid;
+#else /* !(defined(_WIN32)) */
+ int stdin_pipe;
+ int stdout_pipe;
+ int stderr_pipe;
+ pid_t pid;
+ /** If the process has not given us a SIGCHLD yet, this has the
+ * waitpid_callback_t that gets invoked once it has. Otherwise this
+ * contains NULL. */
+ struct waitpid_callback_t *waitpid_cb;
+ /** The exit status reported by waitpid. */
+ int waitpid_exit_status;
+#endif /* defined(_WIN32) */
+};
+#endif /* defined(SUBPROCESS_PRIVATE) */
+
+/* Return values of tor_get_exit_code() */
+#define PROCESS_EXIT_RUNNING 1
+#define PROCESS_EXIT_EXITED 0
+#define PROCESS_EXIT_ERROR -1
+int tor_get_exit_code(process_handle_t *process_handle,
+ int block, int *exit_code);
+int tor_split_lines(struct smartlist_t *sl, char *buf, int len);
+#ifdef _WIN32
+ssize_t tor_read_all_handle(HANDLE h, char *buf, size_t count,
+ const process_handle_t *process);
+#else
+ssize_t tor_read_all_handle(int fd, char *buf, size_t count,
+ const process_handle_t *process,
+ int *eof);
+#endif /* defined(_WIN32) */
+ssize_t tor_read_all_from_process_stdout(
+ const process_handle_t *process_handle, char *buf, size_t count);
+ssize_t tor_read_all_from_process_stderr(
+ const process_handle_t *process_handle, char *buf, size_t count);
+char *tor_join_win_cmdline(const char *argv[]);
+
+int tor_process_get_pid(process_handle_t *process_handle);
+#ifdef _WIN32
+HANDLE tor_process_get_stdout_pipe(process_handle_t *process_handle);
+#else
+int tor_process_get_stdout_pipe(process_handle_t *process_handle);
+#endif
+
+#ifdef _WIN32
+MOCK_DECL(struct smartlist_t *, tor_get_lines_from_handle,(HANDLE *handle,
+ enum stream_status *stream_status));
+#else
+MOCK_DECL(struct smartlist_t *, tor_get_lines_from_handle,(int fd,
+ enum stream_status *stream_status));
+#endif /* defined(_WIN32) */
+
+int tor_terminate_process(process_handle_t *process_handle);
+
+MOCK_DECL(void, tor_process_handle_destroy,(process_handle_t *process_handle,
+ int also_terminate_process));
+
+#ifdef SUBPROCESS_PRIVATE
+/* Prototypes for private functions only used by util.c (and unit tests) */
+
+#ifndef _WIN32
+STATIC int format_helper_exit_status(unsigned char child_state,
+ int saved_errno, char *hex_errno);
+
+/* Space for hex values of child state, a slash, saved_errno (with
+ leading minus) and newline (no null) */
+#define HEX_ERRNO_SIZE (sizeof(char) * 2 + 1 + \
+ 1 + sizeof(int) * 2 + 1)
+#endif /* !defined(_WIN32) */
+
+#endif /* defined(SUBPROCESS_PRIVATE) */
+
+#endif
diff --git a/src/common/util_process.c b/src/lib/process/waitpid.c
index c2826152e9..66c77b05f3 100644
--- a/src/common/util_process.c
+++ b/src/lib/process/waitpid.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,18 +12,19 @@
#include "orconfig.h"
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
+#ifndef _WIN32
+
+#include "lib/process/waitpid.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/malloc/util_malloc.h"
+#include "ht.h"
+
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
-#include "compat.h"
-#include "util.h"
-#include "torlog.h"
-#include "util_process.h"
-#include "ht.h"
+#include <string.h>
/* ================================================== */
/* Convenience structures for handlers for waitpid().
@@ -32,8 +33,6 @@
* monitoring a non-child process.
*/
-#ifndef _WIN32
-
/** Mapping from a PID to a userfn/userdata pair. */
struct waitpid_callback_t {
HT_ENTRY(waitpid_callback_t) node;
@@ -155,4 +154,3 @@ notify_pending_waitpid_callbacks(void)
}
#endif /* !defined(_WIN32) */
-
diff --git a/src/common/util_process.h b/src/lib/process/waitpid.h
index c9aa771b77..85905da6bf 100644
--- a/src/common/util_process.h
+++ b/src/lib/process/waitpid.h
@@ -1,15 +1,19 @@
-/* Copyright (c) 2011-2017, The Tor Project, Inc. */
+/* Copyright (c) 2011-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file util_process.h
- * \brief Headers for util_process.c
+ * \file waitpid.h
+ * \brief Headers for waitpid.c
**/
-#ifndef TOR_UTIL_PROCESS_H
-#define TOR_UTIL_PROCESS_H
+#ifndef TOR_WAITPID_H
+#define TOR_WAITPID_H
#ifndef _WIN32
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
/** A callback structure waiting for us to get a SIGCHLD informing us that a
* PID has been closed. Created by set_waitpid_callback. Cancelled or cleaned-
* up from clear_waitpid_callback(). Do not access outside of the main thread;
@@ -22,5 +26,4 @@ void clear_waitpid_callback(waitpid_callback_t *ent);
void notify_pending_waitpid_callbacks(void);
#endif /* !defined(_WIN32) */
-#endif /* !defined(TOR_UTIL_PROCESS_H) */
-
+#endif /* !defined(TOR_WAITPID_H) */
diff --git a/src/lib/sandbox/.may_include b/src/lib/sandbox/.may_include
new file mode 100644
index 0000000000..84906dfb3d
--- /dev/null
+++ b/src/lib/sandbox/.may_include
@@ -0,0 +1,15 @@
+orconfig.h
+
+lib/cc/*.h
+lib/container/*.h
+lib/err/*.h
+lib/log/*.h
+lib/malloc/*.h
+lib/net/*.h
+lib/sandbox/*.h
+lib/sandbox/*.inc
+lib/string/*.h
+
+ht.h
+siphash.h
+tor_queue.h
diff --git a/src/lib/sandbox/include.am b/src/lib/sandbox/include.am
new file mode 100644
index 0000000000..adfda6bde5
--- /dev/null
+++ b/src/lib/sandbox/include.am
@@ -0,0 +1,18 @@
+
+noinst_LIBRARIES += src/lib/libtor-sandbox.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-sandbox-testing.a
+endif
+
+src_lib_libtor_sandbox_a_SOURCES = \
+ src/lib/sandbox/sandbox.c
+
+src_lib_libtor_sandbox_testing_a_SOURCES = \
+ $(src_lib_libtor_sandbox_a_SOURCES)
+src_lib_libtor_sandbox_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_sandbox_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/sandbox/linux_syscalls.inc \
+ src/lib/sandbox/sandbox.h
diff --git a/src/common/linux_syscalls.inc b/src/lib/sandbox/linux_syscalls.inc
index cf47c73809..cf47c73809 100644
--- a/src/common/linux_syscalls.inc
+++ b/src/lib/sandbox/linux_syscalls.inc
diff --git a/src/common/sandbox.c b/src/lib/sandbox/sandbox.c
index 440f8722f2..25dd6d1c26 100644
--- a/src/common/sandbox.c
+++ b/src/lib/sandbox/sandbox.c
@@ -1,7 +1,7 @@
- /* Copyright (c) 2001 Matej Pfajfar.
+/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -31,15 +31,20 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <errno.h>
-#include "sandbox.h"
-#include "container.h"
-#include "torlog.h"
-#include "torint.h"
-#include "util.h"
-#include "tor_queue.h"
+#include "lib/sandbox/sandbox.h"
+#include "lib/container/map.h"
+#include "lib/err/torerr.h"
+#include "lib/log/torlog.h"
+#include "lib/cc/torint.h"
+#include "lib/net/resolve.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/string/scanf.h"
+#include "tor_queue.h"
#include "ht.h"
+#include "siphash.h"
#define DEBUGGING_CLOSE
@@ -79,7 +84,7 @@
defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
#define USE_BACKTRACE
#define EXPOSE_CLEAN_BACKTRACE
-#include "backtrace.h"
+#include "lib/err/backtrace.h"
#endif /* defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && ... */
#ifdef USE_BACKTRACE
@@ -1455,183 +1460,6 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file)
return 0;
}
-/** Cache entry for getaddrinfo results; used when sandboxing is implemented
- * so that we can consult the cache when the sandbox prevents us from doing
- * getaddrinfo.
- *
- * We support only a limited range of getaddrinfo calls, where servname is null
- * and hints contains only socktype=SOCK_STREAM, family in INET,INET6,UNSPEC.
- */
-typedef struct cached_getaddrinfo_item_t {
- HT_ENTRY(cached_getaddrinfo_item_t) node;
- char *name;
- int family;
- /** set if no error; otherwise NULL */
- struct addrinfo *res;
- /** 0 for no error; otherwise an EAI_* value */
- int err;
-} cached_getaddrinfo_item_t;
-
-static unsigned
-cached_getaddrinfo_item_hash(const cached_getaddrinfo_item_t *item)
-{
- return (unsigned)siphash24g(item->name, strlen(item->name)) + item->family;
-}
-
-static unsigned
-cached_getaddrinfo_items_eq(const cached_getaddrinfo_item_t *a,
- const cached_getaddrinfo_item_t *b)
-{
- return (a->family == b->family) && 0 == strcmp(a->name, b->name);
-}
-
-#define cached_getaddrinfo_item_free(item) \
- FREE_AND_NULL(cached_getaddrinfo_item_t, \
- cached_getaddrinfo_item_free_, (item))
-
-static void
-cached_getaddrinfo_item_free_(cached_getaddrinfo_item_t *item)
-{
- if (item == NULL)
- return;
-
- tor_free(item->name);
- if (item->res)
- freeaddrinfo(item->res);
- tor_free(item);
-}
-
-static HT_HEAD(getaddrinfo_cache, cached_getaddrinfo_item_t)
- getaddrinfo_cache = HT_INITIALIZER();
-
-HT_PROTOTYPE(getaddrinfo_cache, cached_getaddrinfo_item_t, node,
- cached_getaddrinfo_item_hash,
- cached_getaddrinfo_items_eq)
-HT_GENERATE2(getaddrinfo_cache, cached_getaddrinfo_item_t, node,
- cached_getaddrinfo_item_hash,
- cached_getaddrinfo_items_eq,
- 0.6, tor_reallocarray_, tor_free_)
-
-/** If true, don't try to cache getaddrinfo results. */
-static int sandbox_getaddrinfo_cache_disabled = 0;
-
-/** Tell the sandbox layer not to try to cache getaddrinfo results. Used as in
- * tor-resolve, when we have no intention of initializing crypto or of
- * installing the sandbox.*/
-void
-sandbox_disable_getaddrinfo_cache(void)
-{
- sandbox_getaddrinfo_cache_disabled = 1;
-}
-
-void
-sandbox_freeaddrinfo(struct addrinfo *ai)
-{
- if (sandbox_getaddrinfo_cache_disabled)
- freeaddrinfo(ai);
-}
-
-int
-sandbox_getaddrinfo(const char *name, const char *servname,
- const struct addrinfo *hints,
- struct addrinfo **res)
-{
- int err;
- struct cached_getaddrinfo_item_t search, *item;
-
- if (sandbox_getaddrinfo_cache_disabled) {
- return getaddrinfo(name, NULL, hints, res);
- }
-
- if (servname != NULL) {
- log_warn(LD_BUG, "called with non-NULL servname");
- return EAI_NONAME;
- }
- if (name == NULL) {
- log_warn(LD_BUG, "called with NULL name");
- return EAI_NONAME;
- }
-
- *res = NULL;
-
- memset(&search, 0, sizeof(search));
- search.name = (char *) name;
- search.family = hints ? hints->ai_family : AF_UNSPEC;
- item = HT_FIND(getaddrinfo_cache, &getaddrinfo_cache, &search);
-
- if (! sandbox_is_active()) {
- /* If the sandbox is not turned on yet, then getaddrinfo and store the
- result. */
-
- err = getaddrinfo(name, NULL, hints, res);
- log_info(LD_NET,"(Sandbox) getaddrinfo %s.", err ? "failed" : "succeeded");
-
- if (! item) {
- item = tor_malloc_zero(sizeof(*item));
- item->name = tor_strdup(name);
- item->family = hints ? hints->ai_family : AF_UNSPEC;
- HT_INSERT(getaddrinfo_cache, &getaddrinfo_cache, item);
- }
-
- if (item->res) {
- freeaddrinfo(item->res);
- item->res = NULL;
- }
- item->res = *res;
- item->err = err;
- return err;
- }
-
- /* Otherwise, the sandbox is on. If we have an item, yield its cached
- result. */
- if (item) {
- *res = item->res;
- return item->err;
- }
-
- /* getting here means something went wrong */
- log_err(LD_BUG,"(Sandbox) failed to get address %s!", name);
- return EAI_NONAME;
-}
-
-int
-sandbox_add_addrinfo(const char *name)
-{
- struct addrinfo *res;
- struct addrinfo hints;
- int i;
- static const int families[] = { AF_INET, AF_INET6, AF_UNSPEC };
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_STREAM;
- for (i = 0; i < 3; ++i) {
- hints.ai_family = families[i];
-
- res = NULL;
- (void) sandbox_getaddrinfo(name, NULL, &hints, &res);
- if (res)
- sandbox_freeaddrinfo(res);
- }
-
- return 0;
-}
-
-void
-sandbox_free_getaddrinfo_cache(void)
-{
- cached_getaddrinfo_item_t **next, **item, *this;
-
- for (item = HT_START(getaddrinfo_cache, &getaddrinfo_cache);
- item;
- item = next) {
- this = *item;
- next = HT_NEXT_RMV(getaddrinfo_cache, &getaddrinfo_cache, item);
- cached_getaddrinfo_item_free(this);
- }
-
- HT_CLEAR(getaddrinfo_cache, &getaddrinfo_cache);
-}
-
/**
* Function responsible for going through the parameter syscall filters and
* call each function pointer in the list.
@@ -1724,13 +1552,15 @@ install_syscall_filter(sandbox_cfg_t* cfg)
// marking the sandbox as active
sandbox_active = 1;
+ tor_make_getaddrinfo_cache_active();
end:
seccomp_release(ctx);
return (rc < 0 ? -rc : rc);
}
-#include "linux_syscalls.inc"
+#include "lib/sandbox/linux_syscalls.inc"
+
static const char *
get_syscall_name(int syscall_num)
{
@@ -1974,4 +1804,3 @@ sandbox_disable_getaddrinfo_cache(void)
{
}
#endif /* !defined(USE_LIBSECCOMP) */
-
diff --git a/src/common/sandbox.h b/src/lib/sandbox/sandbox.h
index d0f85570f4..60d8e8816a 100644
--- a/src/common/sandbox.h
+++ b/src/lib/sandbox/sandbox.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,7 +13,7 @@
#define SANDBOX_H_
#include "orconfig.h"
-#include "torint.h"
+#include "lib/cc/torint.h"
#ifndef SYS_SECCOMP
@@ -104,27 +104,6 @@ typedef struct {
#endif /* defined(USE_LIBSECCOMP) */
#ifdef USE_LIBSECCOMP
-/** Pre-calls getaddrinfo in order to pre-record result. */
-int sandbox_add_addrinfo(const char *addr);
-
-struct addrinfo;
-/** Replacement for getaddrinfo(), using pre-recorded results. */
-int sandbox_getaddrinfo(const char *name, const char *servname,
- const struct addrinfo *hints,
- struct addrinfo **res);
-void sandbox_freeaddrinfo(struct addrinfo *addrinfo);
-void sandbox_free_getaddrinfo_cache(void);
-#else /* !(defined(USE_LIBSECCOMP)) */
-#define sandbox_getaddrinfo(name, servname, hints, res) \
- getaddrinfo((name),(servname), (hints),(res))
-#define sandbox_add_addrinfo(name) \
- ((void)(name))
-#define sandbox_freeaddrinfo(addrinfo) \
- freeaddrinfo((addrinfo))
-#define sandbox_free_getaddrinfo_cache()
-#endif /* defined(USE_LIBSECCOMP) */
-
-#ifdef USE_LIBSECCOMP
/** Returns a registered protected string used with the sandbox, given that
* it matches the parameter.
*/
@@ -168,7 +147,4 @@ int sandbox_init(sandbox_cfg_t* cfg);
/** Return true iff the sandbox is turned on. */
int sandbox_is_active(void);
-void sandbox_disable_getaddrinfo_cache(void);
-
#endif /* !defined(SANDBOX_H_) */
-
diff --git a/src/lib/smartlist_core/.may_include b/src/lib/smartlist_core/.may_include
new file mode 100644
index 0000000000..a8507761a4
--- /dev/null
+++ b/src/lib/smartlist_core/.may_include
@@ -0,0 +1,7 @@
+orconfig.h
+lib/cc/*.h
+lib/malloc/*.h
+lib/err/*.h
+lib/string/*.h
+lib/smartlist_core/*.h
+lib/testsupport/testsupport.h
diff --git a/src/lib/smartlist_core/include.am b/src/lib/smartlist_core/include.am
new file mode 100644
index 0000000000..99d65f0b23
--- /dev/null
+++ b/src/lib/smartlist_core/include.am
@@ -0,0 +1,21 @@
+
+noinst_LIBRARIES += src/lib/libtor-smartlist-core.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-smartlist-core-testing.a
+endif
+
+src_lib_libtor_smartlist_core_a_SOURCES = \
+ src/lib/smartlist_core/smartlist_core.c \
+ src/lib/smartlist_core/smartlist_split.c
+
+src_lib_libtor_smartlist_core_testing_a_SOURCES = \
+ $(src_lib_libtor_smartlist_core_a_SOURCES)
+src_lib_libtor_smartlist_core_testing_a_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_smartlist_core_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/smartlist_core/smartlist_core.h \
+ src/lib/smartlist_core/smartlist_foreach.h \
+ src/lib/smartlist_core/smartlist_split.h
diff --git a/src/lib/smartlist_core/smartlist_core.c b/src/lib/smartlist_core/smartlist_core.c
new file mode 100644
index 0000000000..b9c5f728ce
--- /dev/null
+++ b/src/lib/smartlist_core/smartlist_core.c
@@ -0,0 +1,234 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file smartlist_core.c
+ * \brief Implements the core functionality of a smartlist (a resizeable
+ * dynamic array). For more functionality and helper functions, see the
+ * container library.
+ **/
+
+#include "lib/err/torerr.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/smartlist_core/smartlist_core.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/** All newly allocated smartlists have this capacity. */
+#define SMARTLIST_DEFAULT_CAPACITY 16
+
+/** Allocate and return an empty smartlist.
+ */
+MOCK_IMPL(smartlist_t *,
+smartlist_new,(void))
+{
+ smartlist_t *sl = tor_malloc(sizeof(smartlist_t));
+ sl->num_used = 0;
+ sl->capacity = SMARTLIST_DEFAULT_CAPACITY;
+ sl->list = tor_calloc(sizeof(void *), sl->capacity);
+ return sl;
+}
+
+/** Deallocate a smartlist. Does not release storage associated with the
+ * list's elements.
+ */
+MOCK_IMPL(void,
+smartlist_free_,(smartlist_t *sl))
+{
+ if (!sl)
+ return;
+ tor_free(sl->list);
+ tor_free(sl);
+}
+
+/** Remove all elements from the list.
+ */
+void
+smartlist_clear(smartlist_t *sl)
+{
+ memset(sl->list, 0, sizeof(void *) * sl->num_used);
+ sl->num_used = 0;
+}
+
+#if SIZE_MAX < INT_MAX
+#error "We don't support systems where size_t is smaller than int."
+#endif
+
+/** Make sure that <b>sl</b> can hold at least <b>size</b> entries. */
+static inline void
+smartlist_ensure_capacity(smartlist_t *sl, size_t size)
+{
+ /* Set MAX_CAPACITY to MIN(INT_MAX, SIZE_MAX / sizeof(void*)) */
+#if (SIZE_MAX/SIZEOF_VOID_P) > INT_MAX
+#define MAX_CAPACITY (INT_MAX)
+#else
+#define MAX_CAPACITY (int)((SIZE_MAX / (sizeof(void*))))
+#endif
+
+ raw_assert(size <= MAX_CAPACITY);
+
+ if (size > (size_t) sl->capacity) {
+ size_t higher = (size_t) sl->capacity;
+ if (PREDICT_UNLIKELY(size > MAX_CAPACITY/2)) {
+ higher = MAX_CAPACITY;
+ } else {
+ while (size > higher)
+ higher *= 2;
+ }
+ sl->list = tor_reallocarray(sl->list, sizeof(void *),
+ ((size_t)higher));
+ memset(sl->list + sl->capacity, 0,
+ sizeof(void *) * (higher - sl->capacity));
+ sl->capacity = (int) higher;
+ }
+#undef ASSERT_CAPACITY
+#undef MAX_CAPACITY
+}
+
+/** Append element to the end of the list. */
+void
+smartlist_add(smartlist_t *sl, void *element)
+{
+ smartlist_ensure_capacity(sl, ((size_t) sl->num_used)+1);
+ sl->list[sl->num_used++] = element;
+}
+
+/** Append each element from S2 to the end of S1. */
+void
+smartlist_add_all(smartlist_t *s1, const smartlist_t *s2)
+{
+ size_t new_size = (size_t)s1->num_used + (size_t)s2->num_used;
+ raw_assert(new_size >= (size_t) s1->num_used); /* check for overflow. */
+ smartlist_ensure_capacity(s1, new_size);
+ memcpy(s1->list + s1->num_used, s2->list, s2->num_used*sizeof(void*));
+ raw_assert(new_size <= INT_MAX); /* redundant. */
+ s1->num_used = (int) new_size;
+}
+
+/** Append a copy of string to sl */
+void
+smartlist_add_strdup(struct smartlist_t *sl, const char *string)
+{
+ char *copy;
+
+ copy = tor_strdup(string);
+
+ smartlist_add(sl, copy);
+}
+
+/** 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)
+{
+ int i;
+ if (element == NULL)
+ return;
+ 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;
+ }
+}
+
+/** As <b>smartlist_remove</b>, but do not change the order of
+ * any elements not removed */
+void
+smartlist_remove_keeporder(smartlist_t *sl, const void *element)
+{
+ int i, j, num_used_orig = sl->num_used;
+ if (element == NULL)
+ return;
+
+ for (i=j=0; j < num_used_orig; ++j) {
+ if (sl->list[j] == element) {
+ --sl->num_used;
+ } else {
+ sl->list[i++] = sl->list[j];
+ }
+ }
+}
+
+/** If <b>sl</b> is nonempty, remove and return the final element. Otherwise,
+ * return NULL. */
+void *
+smartlist_pop_last(smartlist_t *sl)
+{
+ raw_assert(sl);
+ if (sl->num_used) {
+ void *tmp = sl->list[--sl->num_used];
+ sl->list[sl->num_used] = NULL;
+ return tmp;
+ } else
+ return NULL;
+}
+
+/** Return true iff some element E of sl has E==element.
+ */
+int
+smartlist_contains(const smartlist_t *sl, const void *element)
+{
+ int i;
+ for (i=0; i < sl->num_used; i++)
+ if (sl->list[i] == element)
+ return 1;
+ return 0;
+}
+
+/** Remove the <b>idx</b>th element of sl; if idx is not the last
+ * element, swap the last element of sl into the <b>idx</b>th space.
+ */
+void
+smartlist_del(smartlist_t *sl, int idx)
+{
+ raw_assert(sl);
+ raw_assert(idx>=0);
+ raw_assert(idx < sl->num_used);
+ sl->list[idx] = sl->list[--sl->num_used];
+ sl->list[sl->num_used] = NULL;
+}
+
+/** Remove the <b>idx</b>th element of sl; if idx is not the last element,
+ * moving all subsequent elements back one space. Return the old value
+ * of the <b>idx</b>th element.
+ */
+void
+smartlist_del_keeporder(smartlist_t *sl, int idx)
+{
+ raw_assert(sl);
+ raw_assert(idx>=0);
+ raw_assert(idx < sl->num_used);
+ --sl->num_used;
+ if (idx < sl->num_used)
+ memmove(sl->list+idx, sl->list+idx+1, sizeof(void*)*(sl->num_used-idx));
+ sl->list[sl->num_used] = NULL;
+}
+
+/** Insert the value <b>val</b> as the new <b>idx</b>th element of
+ * <b>sl</b>, moving all items previously at <b>idx</b> or later
+ * forward one space.
+ */
+void
+smartlist_insert(smartlist_t *sl, int idx, void *val)
+{
+ raw_assert(sl);
+ raw_assert(idx>=0);
+ raw_assert(idx <= sl->num_used);
+ if (idx == sl->num_used) {
+ smartlist_add(sl, val);
+ } else {
+ smartlist_ensure_capacity(sl, ((size_t) sl->num_used)+1);
+ /* Move other elements away */
+ if (idx < sl->num_used)
+ memmove(sl->list + idx + 1, sl->list + idx,
+ sizeof(void*)*(sl->num_used-idx));
+ sl->num_used++;
+ sl->list[idx] = val;
+ }
+}
diff --git a/src/lib/smartlist_core/smartlist_core.h b/src/lib/smartlist_core/smartlist_core.h
new file mode 100644
index 0000000000..b1adf2ebdb
--- /dev/null
+++ b/src/lib/smartlist_core/smartlist_core.h
@@ -0,0 +1,95 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_SMARTLIST_CORE_H
+#define TOR_SMARTLIST_CORE_H
+
+#include <stddef.h>
+
+#include "lib/cc/compat_compiler.h"
+#include "lib/cc/torint.h"
+#include "lib/testsupport/testsupport.h"
+
+/** A resizeable list of pointers, with associated helpful functionality.
+ *
+ * The members of this struct are exposed only so that macros and inlines can
+ * use them; all access to smartlist internals should go through the functions
+ * and macros defined here.
+ **/
+typedef struct smartlist_t {
+ /** @{ */
+ /** <b>list</b> has enough capacity to store exactly <b>capacity</b> elements
+ * before it needs to be resized. Only the first <b>num_used</b> (\<=
+ * capacity) elements point to valid data.
+ */
+ void **list;
+ int num_used;
+ int capacity;
+ /** @} */
+} smartlist_t;
+
+MOCK_DECL(smartlist_t *, smartlist_new, (void));
+MOCK_DECL(void, smartlist_free_, (smartlist_t *sl));
+#define smartlist_free(sl) FREE_AND_NULL(smartlist_t, smartlist_free_, (sl))
+
+void smartlist_clear(smartlist_t *sl);
+void smartlist_add(smartlist_t *sl, void *element);
+void smartlist_add_all(smartlist_t *sl, const smartlist_t *s2);
+void smartlist_add_strdup(struct smartlist_t *sl, const char *string);
+
+void smartlist_remove(smartlist_t *sl, const void *element);
+void smartlist_remove_keeporder(smartlist_t *sl, const void *element);
+void *smartlist_pop_last(smartlist_t *sl);
+
+int smartlist_contains(const smartlist_t *sl, const void *element);
+
+/* smartlist_choose() is defined in crypto.[ch] */
+#ifdef DEBUG_SMARTLIST
+#include "lib/err/torerr.h"
+#include <stdlib.h>
+/** Return the number of items in sl.
+ */
+static inline int smartlist_len(const smartlist_t *sl);
+static inline int smartlist_len(const smartlist_t *sl) {
+ raw_assert(sl);
+ return (sl)->num_used;
+}
+/** Return the <b>idx</b>th element of sl.
+ */
+static inline void *smartlist_get(const smartlist_t *sl, int idx);
+static inline void *smartlist_get(const smartlist_t *sl, int idx) {
+ raw_assert(sl);
+ raw_assert(idx>=0);
+ raw_assert(sl->num_used > idx);
+ return sl->list[idx];
+}
+static inline void smartlist_set(smartlist_t *sl, int idx, void *val) {
+ raw_assert(sl);
+ raw_assert(idx>=0);
+ raw_assert(sl->num_used > idx);
+ sl->list[idx] = val;
+}
+#else /* !(defined(DEBUG_SMARTLIST)) */
+#define smartlist_len(sl) ((sl)->num_used)
+#define smartlist_get(sl, idx) ((sl)->list[idx])
+#define smartlist_set(sl, idx, val) ((sl)->list[idx] = (val))
+#endif /* defined(DEBUG_SMARTLIST) */
+
+/** Exchange the elements at indices <b>idx1</b> and <b>idx2</b> of the
+ * smartlist <b>sl</b>. */
+static inline void smartlist_swap(smartlist_t *sl, int idx1, int idx2)
+{
+ if (idx1 != idx2) {
+ void *elt = smartlist_get(sl, idx1);
+ smartlist_set(sl, idx1, smartlist_get(sl, idx2));
+ smartlist_set(sl, idx2, elt);
+ }
+}
+
+void smartlist_del(smartlist_t *sl, int idx);
+void smartlist_del_keeporder(smartlist_t *sl, int idx);
+void smartlist_insert(smartlist_t *sl, int idx, void *val);
+
+#endif /* !defined(TOR_CONTAINER_H) */
diff --git a/src/lib/smartlist_core/smartlist_foreach.h b/src/lib/smartlist_core/smartlist_foreach.h
new file mode 100644
index 0000000000..4bef36d99c
--- /dev/null
+++ b/src/lib/smartlist_core/smartlist_foreach.h
@@ -0,0 +1,128 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_SMARTLIST_FOREACH_H
+#define TOR_SMARTLIST_FOREACH_H
+
+/** Iterate over the items in a smartlist <b>sl</b>, in order. For each item,
+ * assign it to a new local variable of type <b>type</b> named <b>var</b>, and
+ * execute the statements inside the loop body. Inside the loop, the loop
+ * index can be accessed as <b>var</b>_sl_idx and the length of the list can
+ * be accessed as <b>var</b>_sl_len.
+ *
+ * NOTE: Do not change the length of the list while the loop is in progress,
+ * unless you adjust the _sl_len variable correspondingly. See second example
+ * below.
+ *
+ * Example use:
+ * <pre>
+ * smartlist_t *list = smartlist_split("A:B:C", ":", 0, 0);
+ * SMARTLIST_FOREACH_BEGIN(list, char *, cp) {
+ * printf("%d: %s\n", cp_sl_idx, cp);
+ * tor_free(cp);
+ * } SMARTLIST_FOREACH_END(cp);
+ * smartlist_free(list);
+ * </pre>
+ *
+ * Example use (advanced):
+ * <pre>
+ * SMARTLIST_FOREACH_BEGIN(list, char *, cp) {
+ * if (!strcmp(cp, "junk")) {
+ * tor_free(cp);
+ * SMARTLIST_DEL_CURRENT(list, cp);
+ * }
+ * } SMARTLIST_FOREACH_END(cp);
+ * </pre>
+ */
+/* Note: these macros use token pasting, and reach into smartlist internals.
+ * This can make them a little daunting. Here's the approximate unpacking of
+ * the above examples, for entertainment value:
+ *
+ * <pre>
+ * smartlist_t *list = smartlist_split("A:B:C", ":", 0, 0);
+ * {
+ * int cp_sl_idx, cp_sl_len = smartlist_len(list);
+ * char *cp;
+ * for (cp_sl_idx = 0; cp_sl_idx < cp_sl_len; ++cp_sl_idx) {
+ * cp = smartlist_get(list, cp_sl_idx);
+ * printf("%d: %s\n", cp_sl_idx, cp);
+ * tor_free(cp);
+ * }
+ * }
+ * smartlist_free(list);
+ * </pre>
+ *
+ * <pre>
+ * {
+ * int cp_sl_idx, cp_sl_len = smartlist_len(list);
+ * char *cp;
+ * for (cp_sl_idx = 0; cp_sl_idx < cp_sl_len; ++cp_sl_idx) {
+ * cp = smartlist_get(list, cp_sl_idx);
+ * if (!strcmp(cp, "junk")) {
+ * tor_free(cp);
+ * smartlist_del(list, cp_sl_idx);
+ * --cp_sl_idx;
+ * --cp_sl_len;
+ * }
+ * }
+ * }
+ * </pre>
+ */
+#define SMARTLIST_FOREACH_BEGIN(sl, type, var) \
+ STMT_BEGIN \
+ int var ## _sl_idx, var ## _sl_len=(sl)->num_used; \
+ type var; \
+ for (var ## _sl_idx = 0; var ## _sl_idx < var ## _sl_len; \
+ ++var ## _sl_idx) { \
+ var = (sl)->list[var ## _sl_idx];
+
+#define SMARTLIST_FOREACH_END(var) \
+ var = NULL; \
+ (void) var ## _sl_idx; \
+ } STMT_END
+
+/**
+ * An alias for SMARTLIST_FOREACH_BEGIN and SMARTLIST_FOREACH_END, using
+ * <b>cmd</b> as the loop body. This wrapper is here for convenience with
+ * very short loops.
+ *
+ * By convention, we do not use this for loops which nest, or for loops over
+ * 10 lines or so. Use SMARTLIST_FOREACH_{BEGIN,END} for those.
+ */
+#define SMARTLIST_FOREACH(sl, type, var, cmd) \
+ SMARTLIST_FOREACH_BEGIN(sl,type,var) { \
+ cmd; \
+ } SMARTLIST_FOREACH_END(var)
+
+/** Helper: While in a SMARTLIST_FOREACH loop over the list <b>sl</b> indexed
+ * with the variable <b>var</b>, remove the current element in a way that
+ * won't confuse the loop. */
+#define SMARTLIST_DEL_CURRENT(sl, var) \
+ STMT_BEGIN \
+ smartlist_del(sl, var ## _sl_idx); \
+ --var ## _sl_idx; \
+ --var ## _sl_len; \
+ STMT_END
+
+/** Helper: While in a SMARTLIST_FOREACH loop over the list <b>sl</b> indexed
+ * with the variable <b>var</b>, remove the current element in a way that
+ * won't confuse the loop. */
+#define SMARTLIST_DEL_CURRENT_KEEPORDER(sl, var) \
+ STMT_BEGIN \
+ smartlist_del_keeporder(sl, var ## _sl_idx); \
+ --var ## _sl_idx; \
+ --var ## _sl_len; \
+ STMT_END
+
+/** Helper: While in a SMARTLIST_FOREACH loop over the list <b>sl</b> indexed
+ * with the variable <b>var</b>, replace the current element with <b>val</b>.
+ * Does not deallocate the current value of <b>var</b>.
+ */
+#define SMARTLIST_REPLACE_CURRENT(sl, var, val) \
+ STMT_BEGIN \
+ smartlist_set(sl, var ## _sl_idx, val); \
+ STMT_END
+
+#endif /* !defined(TOR_SMARTLIST_FOREACH_H) */
diff --git a/src/lib/smartlist_core/smartlist_split.c b/src/lib/smartlist_core/smartlist_split.c
new file mode 100644
index 0000000000..b9340e7924
--- /dev/null
+++ b/src/lib/smartlist_core/smartlist_split.c
@@ -0,0 +1,87 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "lib/smartlist_core/smartlist_core.h"
+#include "lib/smartlist_core/smartlist_split.h"
+
+#include "lib/err/torerr.h"
+#include "lib/string/util_string.h"
+#include "lib/string/compat_ctype.h"
+#include "lib/malloc/util_malloc.h"
+
+#include <string.h>
+
+/**
+ * Split a string <b>str</b> along all occurrences of <b>sep</b>,
+ * appending the (newly allocated) split strings, in order, to
+ * <b>sl</b>. Return the number of strings added to <b>sl</b>.
+ *
+ * If <b>flags</b>&amp;SPLIT_SKIP_SPACE is true, remove initial and
+ * trailing space from each entry.
+ * If <b>flags</b>&amp;SPLIT_IGNORE_BLANK is true, remove any entries
+ * of length 0.
+ * If <b>flags</b>&amp;SPLIT_STRIP_SPACE is true, strip spaces from each
+ * split string.
+ *
+ * If <b>max</b>\>0, divide the string into no more than <b>max</b> pieces. If
+ * <b>sep</b> is NULL, split on any sequence of horizontal space.
+ */
+int
+smartlist_split_string(smartlist_t *sl, const char *str, const char *sep,
+ int flags, int max)
+{
+ const char *cp, *end, *next;
+ int n = 0;
+
+ raw_assert(sl);
+ raw_assert(str);
+
+ cp = str;
+ while (1) {
+ if (flags&SPLIT_SKIP_SPACE) {
+ while (TOR_ISSPACE(*cp)) ++cp;
+ }
+
+ if (max>0 && n == max-1) {
+ end = strchr(cp,'\0');
+ } else if (sep) {
+ end = strstr(cp,sep);
+ if (!end)
+ end = strchr(cp,'\0');
+ } else {
+ for (end = cp; *end && *end != '\t' && *end != ' '; ++end)
+ ;
+ }
+
+ raw_assert(end);
+
+ if (!*end) {
+ next = NULL;
+ } else if (sep) {
+ next = end+strlen(sep);
+ } else {
+ next = end+1;
+ while (*next == '\t' || *next == ' ')
+ ++next;
+ }
+
+ if (flags&SPLIT_SKIP_SPACE) {
+ while (end > cp && TOR_ISSPACE(*(end-1)))
+ --end;
+ }
+ if (end != cp || !(flags&SPLIT_IGNORE_BLANK)) {
+ char *string = tor_strndup(cp, end-cp);
+ if (flags&SPLIT_STRIP_SPACE)
+ tor_strstrip(string, " ");
+ smartlist_add(sl, string);
+ ++n;
+ }
+ if (!next)
+ break;
+ cp = next;
+ }
+
+ return n;
+}
diff --git a/src/lib/smartlist_core/smartlist_split.h b/src/lib/smartlist_core/smartlist_split.h
new file mode 100644
index 0000000000..8ed2abafb8
--- /dev/null
+++ b/src/lib/smartlist_core/smartlist_split.h
@@ -0,0 +1,15 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_SMARTLIST_SPLIT_H
+#define TOR_SMARTLIST_SPLIT_H
+
+#define SPLIT_SKIP_SPACE 0x01
+#define SPLIT_IGNORE_BLANK 0x02
+#define SPLIT_STRIP_SPACE 0x04
+int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep,
+ int flags, int max);
+
+#endif
diff --git a/src/lib/string/.may_include b/src/lib/string/.may_include
new file mode 100644
index 0000000000..ec5c769831
--- /dev/null
+++ b/src/lib/string/.may_include
@@ -0,0 +1,10 @@
+orconfig.h
+lib/cc/*.h
+lib/defs/*.h
+lib/err/*.h
+lib/malloc/*.h
+lib/ctime/*.h
+lib/string/*.h
+
+strlcat.c
+strlcpy.c
diff --git a/src/lib/string/compat_ctype.c b/src/lib/string/compat_ctype.c
new file mode 100644
index 0000000000..d1d4ce0ffc
--- /dev/null
+++ b/src/lib/string/compat_ctype.c
@@ -0,0 +1,67 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "lib/string/compat_ctype.h"
+
+/**
+ * Tables to implement ctypes-replacement TOR_IS*() functions. Each table
+ * has 256 bits to look up whether a character is in some set or not. This
+ * fails on non-ASCII platforms, but it is hard to find a platform whose
+ * character set is not a superset of ASCII nowadays. */
+
+/**@{*/
+const uint32_t TOR_ISALPHA_TABLE[8] =
+ { 0, 0, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 };
+const uint32_t TOR_ISALNUM_TABLE[8] =
+ { 0, 0x3ff0000, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 };
+const uint32_t TOR_ISSPACE_TABLE[8] = { 0x3e00, 0x1, 0, 0, 0, 0, 0, 0 };
+const uint32_t TOR_ISXDIGIT_TABLE[8] =
+ { 0, 0x3ff0000, 0x7e, 0x7e, 0, 0, 0, 0 };
+const uint32_t TOR_ISDIGIT_TABLE[8] = { 0, 0x3ff0000, 0, 0, 0, 0, 0, 0 };
+const uint32_t TOR_ISPRINT_TABLE[8] =
+ { 0, 0xffffffff, 0xffffffff, 0x7fffffff, 0, 0, 0, 0x0 };
+const uint32_t TOR_ISUPPER_TABLE[8] = { 0, 0, 0x7fffffe, 0, 0, 0, 0, 0 };
+const uint32_t TOR_ISLOWER_TABLE[8] = { 0, 0, 0, 0x7fffffe, 0, 0, 0, 0 };
+
+/** Upper-casing and lowercasing tables to map characters to upper/lowercase
+ * equivalents. Used by tor_toupper() and tor_tolower(). */
+/**@{*/
+const uint8_t TOR_TOUPPER_TABLE[256] = {
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
+ 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
+ 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
+ 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
+ 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
+ 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
+ 96,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
+ 80,81,82,83,84,85,86,87,88,89,90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
+};
+const uint8_t TOR_TOLOWER_TABLE[256] = {
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
+ 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
+ 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
+ 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
+ 64,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,91,92,93,94,95,
+ 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
+};
+/**@}*/
diff --git a/src/lib/string/compat_ctype.h b/src/lib/string/compat_ctype.h
new file mode 100644
index 0000000000..530a10270f
--- /dev/null
+++ b/src/lib/string/compat_ctype.h
@@ -0,0 +1,62 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_COMPAT_CTYPE_H
+#define TOR_COMPAT_CTYPE_H
+
+#include "orconfig.h"
+#include "lib/cc/torint.h"
+
+/* Much of the time when we're checking ctypes, we're doing spec compliance,
+ * which all assumes we're doing ASCII. */
+#define DECLARE_CTYPE_FN(name) \
+ static int TOR_##name(char c); \
+ extern const uint32_t TOR_##name##_TABLE[]; \
+ static inline int TOR_##name(char c) { \
+ uint8_t u = c; \
+ return !!(TOR_##name##_TABLE[(u >> 5) & 7] & (1u << (u & 31))); \
+ }
+DECLARE_CTYPE_FN(ISALPHA)
+DECLARE_CTYPE_FN(ISALNUM)
+DECLARE_CTYPE_FN(ISSPACE)
+DECLARE_CTYPE_FN(ISDIGIT)
+DECLARE_CTYPE_FN(ISXDIGIT)
+DECLARE_CTYPE_FN(ISPRINT)
+DECLARE_CTYPE_FN(ISLOWER)
+DECLARE_CTYPE_FN(ISUPPER)
+extern const uint8_t TOR_TOUPPER_TABLE[];
+extern const uint8_t TOR_TOLOWER_TABLE[];
+#define TOR_TOLOWER(c) (TOR_TOLOWER_TABLE[(uint8_t)c])
+#define TOR_TOUPPER(c) (TOR_TOUPPER_TABLE[(uint8_t)c])
+
+static inline int hex_decode_digit(char c);
+
+/** Helper: given a hex digit, return its value, or -1 if it isn't hex. */
+static inline int
+hex_decode_digit(char c)
+{
+ switch (c) {
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ case 'A': case 'a': return 10;
+ case 'B': case 'b': return 11;
+ case 'C': case 'c': return 12;
+ case 'D': case 'd': return 13;
+ case 'E': case 'e': return 14;
+ case 'F': case 'f': return 15;
+ default:
+ return -1;
+ }
+}
+
+#endif /* !defined(TOR_COMPAT_CTYPE_H) */
diff --git a/src/lib/string/compat_string.c b/src/lib/string/compat_string.c
new file mode 100644
index 0000000000..8b063b7242
--- /dev/null
+++ b/src/lib/string/compat_string.c
@@ -0,0 +1,68 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "lib/string/compat_string.h"
+#include "lib/err/torerr.h"
+
+/* Inline the strl functions if the platform doesn't have them. */
+#ifndef HAVE_STRLCPY
+#include "strlcpy.c"
+#endif
+#ifndef HAVE_STRLCAT
+#include "strlcat.c"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+/** Helper for tor_strtok_r_impl: Advances cp past all characters in
+ * <b>sep</b>, and returns its new value. */
+static char *
+strtok_helper(char *cp, const char *sep)
+{
+ if (sep[1]) {
+ while (*cp && strchr(sep, *cp))
+ ++cp;
+ } else {
+ while (*cp && *cp == *sep)
+ ++cp;
+ }
+ return cp;
+}
+
+/** Implementation of strtok_r for platforms whose coders haven't figured out
+ * how to write one. Hey, retrograde libc developers! You can use this code
+ * here for free! */
+char *
+tor_strtok_r_impl(char *str, const char *sep, char **lasts)
+{
+ char *cp, *start;
+ raw_assert(*sep);
+ if (str) {
+ str = strtok_helper(str, sep);
+ if (!*str)
+ return NULL;
+ start = cp = *lasts = str;
+ } else if (!*lasts || !**lasts) {
+ return NULL;
+ } else {
+ start = cp = *lasts;
+ }
+
+ if (sep[1]) {
+ while (*cp && !strchr(sep, *cp))
+ ++cp;
+ } else {
+ cp = strchr(cp, *sep);
+ }
+
+ if (!cp || !*cp) {
+ *lasts = NULL;
+ } else {
+ *cp++ = '\0';
+ *lasts = strtok_helper(cp, sep);
+ }
+ return start;
+}
diff --git a/src/lib/string/compat_string.h b/src/lib/string/compat_string.h
new file mode 100644
index 0000000000..5879c28fc2
--- /dev/null
+++ b/src/lib/string/compat_string.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_COMPAT_STRING_H
+#define TOR_COMPAT_STRING_H
+
+#include "orconfig.h"
+#include "lib/cc/compat_compiler.h"
+
+#include <stddef.h>
+
+/* ===== String compatibility */
+#ifdef _WIN32
+/* Windows doesn't have str(n)casecmp, but mingw defines it: only define it
+ * ourselves if it's missing. */
+#ifndef HAVE_STRNCASECMP
+static inline int strncasecmp(const char *a, const char *b, size_t n);
+static inline int strncasecmp(const char *a, const char *b, size_t n) {
+ return _strnicmp(a,b,n);
+}
+#endif
+#ifndef HAVE_STRCASECMP
+static inline int strcasecmp(const char *a, const char *b, size_t n);
+static inline int strcasecmp(const char *a, const char *b, size_t n) {
+ return _stricmp(a,b);
+}
+#endif
+#endif
+
+#if defined __APPLE__
+/* On OSX 10.9 and later, the overlap-checking code for strlcat would
+ * appear to have a severe bug that can sometimes cause aborts in Tor.
+ * Instead, use the non-checking variants. This is sad.
+ *
+ * See https://trac.torproject.org/projects/tor/ticket/15205
+ */
+#undef strlcat
+#undef strlcpy
+#endif /* defined __APPLE__ */
+
+#ifndef HAVE_STRLCAT
+size_t strlcat(char *dst, const char *src, size_t siz);
+#endif
+#ifndef HAVE_STRLCPY
+size_t strlcpy(char *dst, const char *src, size_t siz);
+#endif
+
+char *tor_strtok_r_impl(char *str, const char *sep, char **lasts);
+#ifdef HAVE_STRTOK_R
+#define tor_strtok_r(str, sep, lasts) strtok_r(str, sep, lasts)
+#else
+#define tor_strtok_r(str, sep, lasts) tor_strtok_r_impl(str, sep, lasts)
+#endif
+
+#endif
diff --git a/src/lib/string/include.am b/src/lib/string/include.am
new file mode 100644
index 0000000000..edd74b8a3e
--- /dev/null
+++ b/src/lib/string/include.am
@@ -0,0 +1,27 @@
+
+noinst_LIBRARIES += src/lib/libtor-string.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-string-testing.a
+endif
+
+src_lib_libtor_string_a_SOURCES = \
+ src/lib/string/compat_ctype.c \
+ src/lib/string/compat_string.c \
+ src/lib/string/util_string.c \
+ src/lib/string/parse_int.c \
+ src/lib/string/printf.c \
+ src/lib/string/scanf.c
+
+src_lib_libtor_string_testing_a_SOURCES = \
+ $(src_lib_libtor_string_a_SOURCES)
+src_lib_libtor_string_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_string_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/string/compat_ctype.h \
+ src/lib/string/compat_string.h \
+ src/lib/string/util_string.h \
+ src/lib/string/parse_int.h \
+ src/lib/string/printf.h \
+ src/lib/string/scanf.h
diff --git a/src/lib/string/parse_int.c b/src/lib/string/parse_int.c
new file mode 100644
index 0000000000..e552730cc4
--- /dev/null
+++ b/src/lib/string/parse_int.c
@@ -0,0 +1,126 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "lib/string/parse_int.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Helper: common code to check whether the result of a strtol or strtoul or
+ * strtoll is correct. */
+#define CHECK_STRTOX_RESULT() \
+ /* Did an overflow occur? */ \
+ if (errno == ERANGE) \
+ goto err; \
+ /* Was at least one character converted? */ \
+ if (endptr == s) \
+ goto err; \
+ /* Were there unexpected unconverted characters? */ \
+ if (!next && *endptr) \
+ goto err; \
+ /* Illogical (max, min) inputs? */ \
+ if (max < min) \
+ goto err; \
+ /* Is r within limits? */ \
+ if (r < min || r > max) \
+ goto err; \
+ if (ok) *ok = 1; \
+ if (next) *next = endptr; \
+ return r; \
+ err: \
+ if (ok) *ok = 0; \
+ if (next) *next = endptr; \
+ return 0
+
+/** Extract a long from the start of <b>s</b>, in the given numeric
+ * <b>base</b>. If <b>base</b> is 0, <b>s</b> is parsed as a decimal,
+ * octal, or hex number in the syntax of a C integer literal. If
+ * there is unconverted data and <b>next</b> is provided, set
+ * *<b>next</b> to the first unconverted character. An error has
+ * occurred if no characters are converted; or if there are
+ * unconverted characters and <b>next</b> is NULL; or if the parsed
+ * value is not between <b>min</b> and <b>max</b>. When no error
+ * occurs, return the parsed value and set *<b>ok</b> (if provided) to
+ * 1. When an error occurs, return 0 and set *<b>ok</b> (if provided)
+ * to 0.
+ */
+long
+tor_parse_long(const char *s, int base, long min, long max,
+ int *ok, char **next)
+{
+ char *endptr;
+ long r;
+
+ if (base < 0) {
+ if (ok)
+ *ok = 0;
+ return 0;
+ }
+
+ errno = 0;
+ r = strtol(s, &endptr, base);
+ CHECK_STRTOX_RESULT();
+}
+
+/** As tor_parse_long(), but return an unsigned long. */
+unsigned long
+tor_parse_ulong(const char *s, int base, unsigned long min,
+ unsigned long max, int *ok, char **next)
+{
+ char *endptr;
+ unsigned long r;
+
+ if (base < 0) {
+ if (ok)
+ *ok = 0;
+ return 0;
+ }
+
+ errno = 0;
+ r = strtoul(s, &endptr, base);
+ CHECK_STRTOX_RESULT();
+}
+
+/** As tor_parse_long(), but return a double. */
+double
+tor_parse_double(const char *s, double min, double max, int *ok, char **next)
+{
+ char *endptr;
+ double r;
+
+ errno = 0;
+ r = strtod(s, &endptr);
+ CHECK_STRTOX_RESULT();
+}
+
+/** As tor_parse_long, but return a uint64_t. Only base 10 is guaranteed to
+ * work for now. */
+uint64_t
+tor_parse_uint64(const char *s, int base, uint64_t min,
+ uint64_t max, int *ok, char **next)
+{
+ char *endptr;
+ uint64_t r;
+
+ if (base < 0) {
+ if (ok)
+ *ok = 0;
+ return 0;
+ }
+
+ errno = 0;
+#ifdef HAVE_STRTOULL
+ r = (uint64_t)strtoull(s, &endptr, base);
+#elif defined(_WIN32)
+ r = (uint64_t)_strtoui64(s, &endptr, base);
+#elif SIZEOF_LONG == 8
+ r = (uint64_t)strtoul(s, &endptr, base);
+#else
+#error "I don't know how to parse 64-bit numbers."
+#endif /* defined(HAVE_STRTOULL) || ... */
+
+ CHECK_STRTOX_RESULT();
+}
diff --git a/src/lib/string/parse_int.h b/src/lib/string/parse_int.h
new file mode 100644
index 0000000000..6f56fc32a8
--- /dev/null
+++ b/src/lib/string/parse_int.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_PARSE_INT_H
+#define TOR_PARSE_INT_H
+
+#include "lib/cc/torint.h"
+
+long tor_parse_long(const char *s, int base, long min,
+ long max, int *ok, char **next);
+unsigned long tor_parse_ulong(const char *s, int base, unsigned long min,
+ unsigned long max, int *ok, char **next);
+double tor_parse_double(const char *s, double min, double max, int *ok,
+ char **next);
+uint64_t tor_parse_uint64(const char *s, int base, uint64_t min,
+ uint64_t max, int *ok, char **next);
+
+#endif
diff --git a/src/lib/string/printf.c b/src/lib/string/printf.c
new file mode 100644
index 0000000000..4443e25fb4
--- /dev/null
+++ b/src/lib/string/printf.c
@@ -0,0 +1,152 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "lib/string/printf.h"
+#include "lib/err/torerr.h"
+#include "lib/cc/torint.h"
+#include "lib/malloc/util_malloc.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/** Replacement for snprintf. Differs from platform snprintf in two
+ * ways: First, always NUL-terminates its output. Second, always
+ * returns -1 if the result is truncated. (Note that this return
+ * behavior does <i>not</i> conform to C99; it just happens to be
+ * easier to emulate "return -1" with conformant implementations than
+ * it is to emulate "return number that would be written" with
+ * non-conformant implementations.) */
+int
+tor_snprintf(char *str, size_t size, const char *format, ...)
+{
+ va_list ap;
+ int r;
+ va_start(ap,format);
+ r = tor_vsnprintf(str,size,format,ap);
+ va_end(ap);
+ return r;
+}
+
+/** Replacement for vsnprintf; behavior differs as tor_snprintf differs from
+ * snprintf.
+ */
+int
+tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
+{
+ int r;
+ if (size == 0)
+ return -1; /* no place for the NUL */
+ if (size > SIZE_T_CEILING)
+ return -1;
+#ifdef _WIN32
+ r = _vsnprintf(str, size, format, args);
+#else
+ r = vsnprintf(str, size, format, args);
+#endif
+ str[size-1] = '\0';
+ if (r < 0 || r >= (ssize_t)size)
+ return -1;
+ return r;
+}
+
+/**
+ * Portable asprintf implementation. Does a printf() into a newly malloc'd
+ * string. Sets *<b>strp</b> to this string, and returns its length (not
+ * including the terminating NUL character).
+ *
+ * You can treat this function as if its implementation were something like
+ <pre>
+ char buf[_INFINITY_];
+ tor_snprintf(buf, sizeof(buf), fmt, args);
+ *strp = tor_strdup(buf);
+ return strlen(*strp):
+ </pre>
+ * Where _INFINITY_ is an imaginary constant so big that any string can fit
+ * into it.
+ */
+int
+tor_asprintf(char **strp, const char *fmt, ...)
+{
+ int r;
+ va_list args;
+ va_start(args, fmt);
+ r = tor_vasprintf(strp, fmt, args);
+ va_end(args);
+ if (!*strp || r < 0) {
+ /* LCOV_EXCL_START */
+ raw_assert_unreached_msg("Internal error in asprintf");
+ /* LCOV_EXCL_STOP */
+ }
+ return r;
+}
+
+/**
+ * Portable vasprintf implementation. Does a printf() into a newly malloc'd
+ * string. Differs from regular vasprintf in the same ways that
+ * tor_asprintf() differs from regular asprintf.
+ */
+int
+tor_vasprintf(char **strp, const char *fmt, va_list args)
+{
+ /* use a temporary variable in case *strp is in args. */
+ char *strp_tmp=NULL;
+#ifdef HAVE_VASPRINTF
+ /* If the platform gives us one, use it. */
+ int r = vasprintf(&strp_tmp, fmt, args);
+ if (r < 0)
+ *strp = NULL;
+ else
+ *strp = strp_tmp;
+ return r;
+#elif defined(HAVE__VSCPRINTF)
+ /* On Windows, _vsnprintf won't tell us the length of the string if it
+ * overflows, so we need to use _vcsprintf to tell how much to allocate */
+ int len, r;
+ va_list tmp_args;
+ va_copy(tmp_args, args);
+ len = _vscprintf(fmt, tmp_args);
+ va_end(tmp_args);
+ if (len < 0) {
+ *strp = NULL;
+ return -1;
+ }
+ strp_tmp = tor_malloc(len + 1);
+ r = _vsnprintf(strp_tmp, len+1, fmt, args);
+ if (r != len) {
+ tor_free(strp_tmp);
+ *strp = NULL;
+ return -1;
+ }
+ *strp = strp_tmp;
+ return len;
+#else
+ /* Everywhere else, we have a decent vsnprintf that tells us how many
+ * characters we need. We give it a try on a short buffer first, since
+ * it might be nice to avoid the second vsnprintf call.
+ */
+ char buf[128];
+ int len, r;
+ va_list tmp_args;
+ va_copy(tmp_args, args);
+ /* vsnprintf() was properly checked but tor_vsnprintf() available so
+ * why not use it? */
+ len = tor_vsnprintf(buf, sizeof(buf), fmt, tmp_args);
+ va_end(tmp_args);
+ if (len < (int)sizeof(buf)) {
+ *strp = tor_strdup(buf);
+ return len;
+ }
+ strp_tmp = tor_malloc(len+1);
+ /* use of tor_vsnprintf() will ensure string is null terminated */
+ r = tor_vsnprintf(strp_tmp, len+1, fmt, args);
+ if (r != len) {
+ tor_free(strp_tmp);
+ *strp = NULL;
+ return -1;
+ }
+ *strp = strp_tmp;
+ return len;
+#endif /* defined(HAVE_VASPRINTF) || ... */
+}
diff --git a/src/lib/string/printf.h b/src/lib/string/printf.h
new file mode 100644
index 0000000000..69b724379a
--- /dev/null
+++ b/src/lib/string/printf.h
@@ -0,0 +1,25 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_UTIL_PRINTF_H
+#define TOR_UTIL_PRINTF_H
+
+#include "orconfig.h"
+#include "lib/cc/compat_compiler.h"
+
+#include <stdarg.h>
+#include <stddef.h>
+
+int tor_snprintf(char *str, size_t size, const char *format, ...)
+ CHECK_PRINTF(3,4);
+int tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
+ CHECK_PRINTF(3,0);
+
+int tor_asprintf(char **strp, const char *fmt, ...)
+ CHECK_PRINTF(2,3);
+int tor_vasprintf(char **strp, const char *fmt, va_list args)
+ CHECK_PRINTF(2,0);
+
+#endif /* !defined(TOR_UTIL_STRING_H) */
diff --git a/src/lib/string/scanf.c b/src/lib/string/scanf.c
new file mode 100644
index 0000000000..0c5082799c
--- /dev/null
+++ b/src/lib/string/scanf.c
@@ -0,0 +1,312 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "lib/string/scanf.h"
+#include "lib/string/compat_ctype.h"
+#include "lib/cc/torint.h"
+#include "lib/err/torerr.h"
+
+#include <stdlib.h>
+
+#define MAX_SCANF_WIDTH 9999
+
+/** Helper: given an ASCII-encoded decimal digit, return its numeric value.
+ * NOTE: requires that its input be in-bounds. */
+static int
+digit_to_num(char d)
+{
+ int num = ((int)d) - (int)'0';
+ raw_assert(num <= 9 && num >= 0);
+ return num;
+}
+
+/** Helper: Read an unsigned int from *<b>bufp</b> of up to <b>width</b>
+ * characters. (Handle arbitrary width if <b>width</b> is less than 0.) On
+ * success, store the result in <b>out</b>, advance bufp to the next
+ * character, and return 0. On failure, return -1. */
+static int
+scan_unsigned(const char **bufp, unsigned long *out, int width, unsigned base)
+{
+ unsigned long result = 0;
+ int scanned_so_far = 0;
+ const int hex = base==16;
+ raw_assert(base == 10 || base == 16);
+ if (!bufp || !*bufp || !out)
+ return -1;
+ if (width<0)
+ width=MAX_SCANF_WIDTH;
+
+ while (**bufp && (hex?TOR_ISXDIGIT(**bufp):TOR_ISDIGIT(**bufp))
+ && scanned_so_far < width) {
+ unsigned digit = hex?hex_decode_digit(*(*bufp)++):digit_to_num(*(*bufp)++);
+ // Check for overflow beforehand, without actually causing any overflow
+ // This preserves functionality on compilers that don't wrap overflow
+ // (i.e. that trap or optimise away overflow)
+ // result * base + digit > ULONG_MAX
+ // result * base > ULONG_MAX - digit
+ if (result > (ULONG_MAX - digit)/base)
+ return -1; /* Processing this digit would overflow */
+ result = result * base + digit;
+ ++scanned_so_far;
+ }
+
+ if (!scanned_so_far) /* No actual digits scanned */
+ return -1;
+
+ *out = result;
+ return 0;
+}
+
+/** Helper: Read an signed int from *<b>bufp</b> of up to <b>width</b>
+ * characters. (Handle arbitrary width if <b>width</b> is less than 0.) On
+ * success, store the result in <b>out</b>, advance bufp to the next
+ * character, and return 0. On failure, return -1. */
+static int
+scan_signed(const char **bufp, long *out, int width)
+{
+ int neg = 0;
+ unsigned long result = 0;
+
+ if (!bufp || !*bufp || !out)
+ return -1;
+ if (width<0)
+ width=MAX_SCANF_WIDTH;
+
+ if (**bufp == '-') {
+ neg = 1;
+ ++*bufp;
+ --width;
+ }
+
+ if (scan_unsigned(bufp, &result, width, 10) < 0)
+ return -1;
+
+ if (neg && result > 0) {
+ if (result > ((unsigned long)LONG_MAX) + 1)
+ return -1; /* Underflow */
+ else if (result == ((unsigned long)LONG_MAX) + 1)
+ *out = LONG_MIN;
+ else {
+ /* We once had a far more clever no-overflow conversion here, but
+ * some versions of GCC apparently ran it into the ground. Now
+ * we just check for LONG_MIN explicitly.
+ */
+ *out = -(long)result;
+ }
+ } else {
+ if (result > LONG_MAX)
+ return -1; /* Overflow */
+ *out = (long)result;
+ }
+
+ return 0;
+}
+
+/** Helper: Read a decimal-formatted double from *<b>bufp</b> of up to
+ * <b>width</b> characters. (Handle arbitrary width if <b>width</b> is less
+ * than 0.) On success, store the result in <b>out</b>, advance bufp to the
+ * next character, and return 0. On failure, return -1. */
+static int
+scan_double(const char **bufp, double *out, int width)
+{
+ int neg = 0;
+ double result = 0;
+ int scanned_so_far = 0;
+
+ if (!bufp || !*bufp || !out)
+ return -1;
+ if (width<0)
+ width=MAX_SCANF_WIDTH;
+
+ if (**bufp == '-') {
+ neg = 1;
+ ++*bufp;
+ }
+
+ while (**bufp && TOR_ISDIGIT(**bufp) && scanned_so_far < width) {
+ const int digit = digit_to_num(*(*bufp)++);
+ result = result * 10 + digit;
+ ++scanned_so_far;
+ }
+ if (**bufp == '.') {
+ double fracval = 0, denominator = 1;
+ ++*bufp;
+ ++scanned_so_far;
+ while (**bufp && TOR_ISDIGIT(**bufp) && scanned_so_far < width) {
+ const int digit = digit_to_num(*(*bufp)++);
+ fracval = fracval * 10 + digit;
+ denominator *= 10;
+ ++scanned_so_far;
+ }
+ result += fracval / denominator;
+ }
+
+ if (!scanned_so_far) /* No actual digits scanned */
+ return -1;
+
+ *out = neg ? -result : result;
+ return 0;
+}
+
+/** Helper: copy up to <b>width</b> non-space characters from <b>bufp</b> to
+ * <b>out</b>. Make sure <b>out</b> is nul-terminated. Advance <b>bufp</b>
+ * to the next non-space character or the EOS. */
+static int
+scan_string(const char **bufp, char *out, int width)
+{
+ int scanned_so_far = 0;
+ if (!bufp || !out || width < 0)
+ return -1;
+ while (**bufp && ! TOR_ISSPACE(**bufp) && scanned_so_far < width) {
+ *out++ = *(*bufp)++;
+ ++scanned_so_far;
+ }
+ *out = '\0';
+ return 0;
+}
+
+/** Locale-independent, minimal, no-surprises scanf variant, accepting only a
+ * restricted pattern format. For more info on what it supports, see
+ * tor_sscanf() documentation. */
+int
+tor_vsscanf(const char *buf, const char *pattern, va_list ap)
+{
+ int n_matched = 0;
+
+ while (*pattern) {
+ if (*pattern != '%') {
+ if (*buf == *pattern) {
+ ++buf;
+ ++pattern;
+ continue;
+ } else {
+ return n_matched;
+ }
+ } else {
+ int width = -1;
+ int longmod = 0;
+ ++pattern;
+ if (TOR_ISDIGIT(*pattern)) {
+ width = digit_to_num(*pattern++);
+ while (TOR_ISDIGIT(*pattern)) {
+ width *= 10;
+ width += digit_to_num(*pattern++);
+ if (width > MAX_SCANF_WIDTH)
+ return -1;
+ }
+ if (!width) /* No zero-width things. */
+ return -1;
+ }
+ if (*pattern == 'l') {
+ longmod = 1;
+ ++pattern;
+ }
+ if (*pattern == 'u' || *pattern == 'x') {
+ unsigned long u;
+ const int base = (*pattern == 'u') ? 10 : 16;
+ if (!*buf)
+ return n_matched;
+ if (scan_unsigned(&buf, &u, width, base)<0)
+ return n_matched;
+ if (longmod) {
+ unsigned long *out = va_arg(ap, unsigned long *);
+ *out = u;
+ } else {
+ unsigned *out = va_arg(ap, unsigned *);
+ if (u > UINT_MAX)
+ return n_matched;
+ *out = (unsigned) u;
+ }
+ ++pattern;
+ ++n_matched;
+ } else if (*pattern == 'f') {
+ double *d = va_arg(ap, double *);
+ if (!longmod)
+ return -1; /* float not supported */
+ if (!*buf)
+ return n_matched;
+ if (scan_double(&buf, d, width)<0)
+ return n_matched;
+ ++pattern;
+ ++n_matched;
+ } else if (*pattern == 'd') {
+ long lng=0;
+ if (scan_signed(&buf, &lng, width)<0)
+ return n_matched;
+ if (longmod) {
+ long *out = va_arg(ap, long *);
+ *out = lng;
+ } else {
+ int *out = va_arg(ap, int *);
+#if LONG_MAX > INT_MAX
+ if (lng < INT_MIN || lng > INT_MAX)
+ return n_matched;
+#endif
+ *out = (int)lng;
+ }
+ ++pattern;
+ ++n_matched;
+ } else if (*pattern == 's') {
+ char *s = va_arg(ap, char *);
+ if (longmod)
+ return -1;
+ if (width < 0)
+ return -1;
+ if (scan_string(&buf, s, width)<0)
+ return n_matched;
+ ++pattern;
+ ++n_matched;
+ } else if (*pattern == 'c') {
+ char *ch = va_arg(ap, char *);
+ if (longmod)
+ return -1;
+ if (width != -1)
+ return -1;
+ if (!*buf)
+ return n_matched;
+ *ch = *buf++;
+ ++pattern;
+ ++n_matched;
+ } else if (*pattern == '%') {
+ if (*buf != '%')
+ return n_matched;
+ if (longmod)
+ return -1;
+ ++buf;
+ ++pattern;
+ } else {
+ return -1; /* Unrecognized pattern component. */
+ }
+ }
+ }
+
+ return n_matched;
+}
+
+/** Minimal sscanf replacement: parse <b>buf</b> according to <b>pattern</b>
+ * and store the results in the corresponding argument fields. Differs from
+ * sscanf in that:
+ * <ul><li>It only handles %u, %lu, %x, %lx, %[NUM]s, %d, %ld, %lf, and %c.
+ * <li>It only handles decimal inputs for %lf. (12.3, not 1.23e1)
+ * <li>It does not handle arbitrarily long widths.
+ * <li>Numbers do not consume any space characters.
+ * <li>It is locale-independent.
+ * <li>%u and %x do not consume any space.
+ * <li>It returns -1 on malformed patterns.</ul>
+ *
+ * (As with other locale-independent functions, we need this to parse data that
+ * is in ASCII without worrying that the C library's locale-handling will make
+ * miscellaneous characters look like numbers, spaces, and so on.)
+ */
+int
+tor_sscanf(const char *buf, const char *pattern, ...)
+{
+ int r;
+ va_list ap;
+ va_start(ap, pattern);
+ r = tor_vsscanf(buf, pattern, ap);
+ va_end(ap);
+ return r;
+}
diff --git a/src/lib/string/scanf.h b/src/lib/string/scanf.h
new file mode 100644
index 0000000000..9cfa9cc6c1
--- /dev/null
+++ b/src/lib/string/scanf.h
@@ -0,0 +1,19 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_UTIL_SCANF_H
+#define TOR_UTIL_SCANF_H
+
+#include "orconfig.h"
+#include "lib/cc/compat_compiler.h"
+
+#include <stdarg.h>
+
+int tor_vsscanf(const char *buf, const char *pattern, va_list ap) \
+ CHECK_SCANF(2, 0);
+int tor_sscanf(const char *buf, const char *pattern, ...)
+ CHECK_SCANF(2, 3);
+
+#endif /* !defined(TOR_UTIL_STRING_H) */
diff --git a/src/lib/string/util_string.c b/src/lib/string/util_string.c
new file mode 100644
index 0000000000..e8ed3d4f54
--- /dev/null
+++ b/src/lib/string/util_string.c
@@ -0,0 +1,448 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "lib/string/util_string.h"
+#include "lib/string/compat_ctype.h"
+#include "lib/err/torerr.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/defs/digest_sizes.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+/** Given <b>hlen</b> bytes at <b>haystack</b> and <b>nlen</b> bytes at
+ * <b>needle</b>, return a pointer to the first occurrence of the needle
+ * within the haystack, or NULL if there is no such occurrence.
+ *
+ * This function is <em>not</em> timing-safe.
+ *
+ * Requires that <b>nlen</b> be greater than zero.
+ */
+const void *
+tor_memmem(const void *_haystack, size_t hlen,
+ const void *_needle, size_t nlen)
+{
+#if defined(HAVE_MEMMEM) && (!defined(__GNUC__) || __GNUC__ >= 2)
+ raw_assert(nlen);
+ return memmem(_haystack, hlen, _needle, nlen);
+#else
+ /* This isn't as fast as the GLIBC implementation, but it doesn't need to
+ * be. */
+ const char *p, *last_possible_start;
+ const char *haystack = (const char*)_haystack;
+ const char *needle = (const char*)_needle;
+ char first;
+ raw_assert(nlen);
+
+ if (nlen > hlen)
+ return NULL;
+
+ p = haystack;
+ /* Last position at which the needle could start. */
+ last_possible_start = haystack + hlen - nlen;
+ first = *(const char*)needle;
+ while ((p = memchr(p, first, last_possible_start + 1 - p))) {
+ if (fast_memeq(p, needle, nlen))
+ return p;
+ if (++p > last_possible_start) {
+ /* This comparison shouldn't be necessary, since if p was previously
+ * equal to last_possible_start, the next memchr call would be
+ * "memchr(p, first, 0)", which will return NULL. But it clarifies the
+ * logic. */
+ return NULL;
+ }
+ }
+ return NULL;
+#endif /* defined(HAVE_MEMMEM) && (!defined(__GNUC__) || __GNUC__ >= 2) */
+}
+
+const void *
+tor_memstr(const void *haystack, size_t hlen, const char *needle)
+{
+ return tor_memmem(haystack, hlen, needle, strlen(needle));
+}
+
+/** Return true iff the 'len' bytes at 'mem' are all zero. */
+int
+tor_mem_is_zero(const char *mem, size_t len)
+{
+ static const char ZERO[] = {
+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
+ };
+ while (len >= sizeof(ZERO)) {
+ /* It's safe to use fast_memcmp here, since the very worst thing an
+ * attacker could learn is how many initial bytes of a secret were zero */
+ if (fast_memcmp(mem, ZERO, sizeof(ZERO)))
+ return 0;
+ len -= sizeof(ZERO);
+ mem += sizeof(ZERO);
+ }
+ /* Deal with leftover bytes. */
+ if (len)
+ return fast_memeq(mem, ZERO, len);
+
+ return 1;
+}
+
+/** Return true iff the DIGEST_LEN bytes in digest are all zero. */
+int
+tor_digest_is_zero(const char *digest)
+{
+ static const uint8_t ZERO_DIGEST[] = {
+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
+ };
+ return tor_memeq(digest, ZERO_DIGEST, DIGEST_LEN);
+}
+
+/** Return true iff the DIGEST256_LEN bytes in digest are all zero. */
+int
+tor_digest256_is_zero(const char *digest)
+{
+ return tor_mem_is_zero(digest, DIGEST256_LEN);
+}
+
+/** Remove from the string <b>s</b> every character which appears in
+ * <b>strip</b>. */
+void
+tor_strstrip(char *s, const char *strip)
+{
+ char *readp = s;
+ while (*readp) {
+ if (strchr(strip, *readp)) {
+ ++readp;
+ } else {
+ *s++ = *readp++;
+ }
+ }
+ *s = '\0';
+}
+
+/** Convert all alphabetic characters in the nul-terminated string <b>s</b> to
+ * lowercase. */
+void
+tor_strlower(char *s)
+{
+ while (*s) {
+ *s = TOR_TOLOWER(*s);
+ ++s;
+ }
+}
+
+/** Convert all alphabetic characters in the nul-terminated string <b>s</b> to
+ * lowercase. */
+void
+tor_strupper(char *s)
+{
+ while (*s) {
+ *s = TOR_TOUPPER(*s);
+ ++s;
+ }
+}
+
+/** Return 1 if every character in <b>s</b> is printable, else return 0.
+ */
+int
+tor_strisprint(const char *s)
+{
+ while (*s) {
+ if (!TOR_ISPRINT(*s))
+ return 0;
+ s++;
+ }
+ return 1;
+}
+
+/** Return 1 if no character in <b>s</b> is uppercase, else return 0.
+ */
+int
+tor_strisnonupper(const char *s)
+{
+ while (*s) {
+ if (TOR_ISUPPER(*s))
+ return 0;
+ s++;
+ }
+ return 1;
+}
+
+/** Return true iff every character in <b>s</b> is whitespace space; else
+ * return false. */
+int
+tor_strisspace(const char *s)
+{
+ while (*s) {
+ if (!TOR_ISSPACE(*s))
+ return 0;
+ s++;
+ }
+ return 1;
+}
+
+/** As strcmp, except that either string may be NULL. The NULL string is
+ * considered to be before any non-NULL string. */
+int
+strcmp_opt(const char *s1, const char *s2)
+{
+ if (!s1) {
+ if (!s2)
+ return 0;
+ else
+ return -1;
+ } else if (!s2) {
+ return 1;
+ } else {
+ return strcmp(s1, s2);
+ }
+}
+
+/** Compares the first strlen(s2) characters of s1 with s2. Returns as for
+ * strcmp.
+ */
+int
+strcmpstart(const char *s1, const char *s2)
+{
+ size_t n = strlen(s2);
+ return strncmp(s1, s2, n);
+}
+
+/** Compare the s1_len-byte string <b>s1</b> with <b>s2</b>,
+ * without depending on a terminating nul in s1. Sorting order is first by
+ * length, then lexically; return values are as for strcmp.
+ */
+int
+strcmp_len(const char *s1, const char *s2, size_t s1_len)
+{
+ size_t s2_len = strlen(s2);
+ if (s1_len < s2_len)
+ return -1;
+ if (s1_len > s2_len)
+ return 1;
+ return fast_memcmp(s1, s2, s2_len);
+}
+
+/** Compares the first strlen(s2) characters of s1 with s2. Returns as for
+ * strcasecmp.
+ */
+int
+strcasecmpstart(const char *s1, const char *s2)
+{
+ size_t n = strlen(s2);
+ return strncasecmp(s1, s2, n);
+}
+
+/** Compare the value of the string <b>prefix</b> with the start of the
+ * <b>memlen</b>-byte memory chunk at <b>mem</b>. Return as for strcmp.
+ *
+ * [As fast_memcmp(mem, prefix, strlen(prefix)) but returns -1 if memlen is
+ * less than strlen(prefix).]
+ */
+int
+fast_memcmpstart(const void *mem, size_t memlen,
+ const char *prefix)
+{
+ size_t plen = strlen(prefix);
+ if (memlen < plen)
+ return -1;
+ return fast_memcmp(mem, prefix, plen);
+}
+
+/** Compares the last strlen(s2) characters of s1 with s2. Returns as for
+ * strcmp.
+ */
+int
+strcmpend(const char *s1, const char *s2)
+{
+ size_t n1 = strlen(s1), n2 = strlen(s2);
+ if (n2>n1)
+ return strcmp(s1,s2);
+ else
+ return strncmp(s1+(n1-n2), s2, n2);
+}
+
+/** Compares the last strlen(s2) characters of s1 with s2. Returns as for
+ * strcasecmp.
+ */
+int
+strcasecmpend(const char *s1, const char *s2)
+{
+ size_t n1 = strlen(s1), n2 = strlen(s2);
+ if (n2>n1) /* then they can't be the same; figure out which is bigger */
+ return strcasecmp(s1,s2);
+ else
+ return strncasecmp(s1+(n1-n2), s2, n2);
+}
+
+/** Return a pointer to the first char of s that is not whitespace and
+ * not a comment, or to the terminating NUL if no such character exists.
+ */
+const char *
+eat_whitespace(const char *s)
+{
+ raw_assert(s);
+
+ while (1) {
+ switch (*s) {
+ case '\0':
+ default:
+ return s;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ ++s;
+ break;
+ case '#':
+ ++s;
+ while (*s && *s != '\n')
+ ++s;
+ }
+ }
+}
+
+/** Return a pointer to the first char of s that is not whitespace and
+ * not a comment, or to the terminating NUL if no such character exists.
+ */
+const char *
+eat_whitespace_eos(const char *s, const char *eos)
+{
+ raw_assert(s);
+ raw_assert(eos && s <= eos);
+
+ while (s < eos) {
+ switch (*s) {
+ case '\0':
+ default:
+ return s;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ ++s;
+ break;
+ case '#':
+ ++s;
+ while (s < eos && *s && *s != '\n')
+ ++s;
+ }
+ }
+ return s;
+}
+
+/** Return a pointer to the first char of s that is not a space or a tab
+ * or a \\r, or to the terminating NUL if no such character exists. */
+const char *
+eat_whitespace_no_nl(const char *s)
+{
+ while (*s == ' ' || *s == '\t' || *s == '\r')
+ ++s;
+ return s;
+}
+
+/** As eat_whitespace_no_nl, but stop at <b>eos</b> whether we have
+ * found a non-whitespace character or not. */
+const char *
+eat_whitespace_eos_no_nl(const char *s, const char *eos)
+{
+ while (s < eos && (*s == ' ' || *s == '\t' || *s == '\r'))
+ ++s;
+ return s;
+}
+
+/** Return a pointer to the first char of s that is whitespace or <b>#</b>,
+ * or to the terminating NUL if no such character exists.
+ */
+const char *
+find_whitespace(const char *s)
+{
+ /* tor_assert(s); */
+ while (1) {
+ switch (*s)
+ {
+ case '\0':
+ case '#':
+ case ' ':
+ case '\r':
+ case '\n':
+ case '\t':
+ return s;
+ default:
+ ++s;
+ }
+ }
+}
+
+/** As find_whitespace, but stop at <b>eos</b> whether we have found a
+ * whitespace or not. */
+const char *
+find_whitespace_eos(const char *s, const char *eos)
+{
+ /* tor_assert(s); */
+ while (s < eos) {
+ switch (*s)
+ {
+ case '\0':
+ case '#':
+ case ' ':
+ case '\r':
+ case '\n':
+ case '\t':
+ return s;
+ default:
+ ++s;
+ }
+ }
+ return s;
+}
+
+/** Return the first occurrence of <b>needle</b> in <b>haystack</b> that
+ * occurs at the start of a line (that is, at the beginning of <b>haystack</b>
+ * or immediately after a newline). Return NULL if no such string is found.
+ */
+const char *
+find_str_at_start_of_line(const char *haystack, const char *needle)
+{
+ size_t needle_len = strlen(needle);
+
+ do {
+ if (!strncmp(haystack, needle, needle_len))
+ return haystack;
+
+ haystack = strchr(haystack, '\n');
+ if (!haystack)
+ return NULL;
+ else
+ ++haystack;
+ } while (*haystack);
+
+ return NULL;
+}
+
+/** Returns true if <b>string</b> could be a C identifier.
+ A C identifier must begin with a letter or an underscore and the
+ rest of its characters can be letters, numbers or underscores. No
+ length limit is imposed. */
+int
+string_is_C_identifier(const char *string)
+{
+ size_t iter;
+ size_t length = strlen(string);
+ if (!length)
+ return 0;
+
+ for (iter = 0; iter < length ; iter++) {
+ if (iter == 0) {
+ if (!(TOR_ISALPHA(string[iter]) ||
+ string[iter] == '_'))
+ return 0;
+ } else {
+ if (!(TOR_ISALPHA(string[iter]) ||
+ TOR_ISDIGIT(string[iter]) ||
+ string[iter] == '_'))
+ return 0;
+ }
+ }
+
+ return 1;
+}
diff --git a/src/lib/string/util_string.h b/src/lib/string/util_string.h
new file mode 100644
index 0000000000..75407d5ffa
--- /dev/null
+++ b/src/lib/string/util_string.h
@@ -0,0 +1,50 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_UTIL_STRING_H
+#define TOR_UTIL_STRING_H
+
+#include "orconfig.h"
+#include "lib/cc/compat_compiler.h"
+
+#include <stddef.h>
+
+const void *tor_memmem(const void *haystack, size_t hlen, const void *needle,
+ size_t nlen);
+const void *tor_memstr(const void *haystack, size_t hlen,
+ const char *needle);
+int tor_mem_is_zero(const char *mem, size_t len);
+int tor_digest_is_zero(const char *digest);
+int tor_digest256_is_zero(const char *digest);
+
+/** Allowable characters in a hexadecimal string. */
+#define HEX_CHARACTERS "0123456789ABCDEFabcdef"
+void tor_strlower(char *s);
+void tor_strupper(char *s);
+int tor_strisprint(const char *s);
+int tor_strisnonupper(const char *s);
+int tor_strisspace(const char *s);
+int strcmp_opt(const char *s1, const char *s2);
+int strcmpstart(const char *s1, const char *s2);
+int strcmp_len(const char *s1, const char *s2, size_t len);
+int strcasecmpstart(const char *s1, const char *s2);
+int strcmpend(const char *s1, const char *s2);
+int strcasecmpend(const char *s1, const char *s2);
+int fast_memcmpstart(const void *mem, size_t memlen, const char *prefix);
+
+void tor_strstrip(char *s, const char *strip);
+
+const char *eat_whitespace(const char *s);
+const char *eat_whitespace_eos(const char *s, const char *eos);
+const char *eat_whitespace_no_nl(const char *s);
+const char *eat_whitespace_eos_no_nl(const char *s, const char *eos);
+const char *find_whitespace(const char *s);
+const char *find_whitespace_eos(const char *s, const char *eos);
+const char *find_str_at_start_of_line(const char *haystack,
+ const char *needle);
+
+int string_is_C_identifier(const char *string);
+
+#endif /* !defined(TOR_UTIL_STRING_H) */
diff --git a/src/lib/term/.may_include b/src/lib/term/.may_include
new file mode 100644
index 0000000000..c93a06e59e
--- /dev/null
+++ b/src/lib/term/.may_include
@@ -0,0 +1,9 @@
+orconfig.h
+
+lib/cc/*.h
+lib/log/*.h
+lib/term/*.h
+lib/malloc/*.h
+
+# From src/ext
+tor_readpassphrase.h
diff --git a/src/lib/term/getpass.c b/src/lib/term/getpass.c
new file mode 100644
index 0000000000..10c99914f8
--- /dev/null
+++ b/src/lib/term/getpass.c
@@ -0,0 +1,115 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "lib/term/getpass.h"
+
+#include "lib/log/util_bug.h"
+#include "lib/malloc/util_malloc.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#include <conio.h>
+#include <wchar.h>
+/* Some mingw headers lack these. :p */
+#if defined(HAVE_DECL__GETWCH) && !HAVE_DECL__GETWCH
+wint_t _getwch(void);
+#endif
+#ifndef WEOF
+#define WEOF (wchar_t)(0xFFFF)
+#endif
+#if defined(HAVE_DECL_SECUREZEROMEMORY) && !HAVE_DECL_SECUREZEROMEMORY
+static inline void
+SecureZeroMemory(PVOID ptr, SIZE_T cnt)
+{
+ volatile char *vcptr = (volatile char*)ptr;
+ while (cnt--)
+ *vcptr++ = 0;
+}
+#endif /* defined(HAVE_DECL_SECUREZEROMEMORY) && !HAVE_DECL_SECUREZEROMEMORY */
+#elif defined(HAVE_READPASSPHRASE_H)
+#include <readpassphrase.h>
+#else
+#include "tor_readpassphrase.h"
+#endif /* defined(_WIN32) || ... */
+
+#include <stdlib.h>
+#include <string.h>
+
+/** Emit the password prompt <b>prompt</b>, then read up to <b>buflen</b>
+ * bytes of passphrase into <b>output</b>. Return the number of bytes in
+ * the passphrase, excluding terminating NUL.
+ */
+ssize_t
+tor_getpass(const char *prompt, char *output, size_t buflen)
+{
+ tor_assert(buflen <= SSIZE_MAX);
+ tor_assert(buflen >= 1);
+#if defined(HAVE_READPASSPHRASE)
+ char *pwd = readpassphrase(prompt, output, buflen, RPP_ECHO_OFF);
+ if (pwd == NULL)
+ return -1;
+ return strlen(pwd);
+#elif defined(_WIN32)
+ int r = -1;
+ while (*prompt) {
+ _putch(*prompt++);
+ }
+
+ tor_assert(buflen <= INT_MAX);
+ wchar_t *buf = tor_calloc(buflen, sizeof(wchar_t));
+
+ wchar_t *ptr = buf, *lastch = buf + buflen - 1;
+ while (ptr < lastch) {
+ wint_t ch = _getwch();
+ switch (ch) {
+ case '\r':
+ case '\n':
+ case WEOF:
+ goto done_reading;
+ case 3:
+ goto done; /* Can't actually read ctrl-c this way. */
+ case '\b':
+ if (ptr > buf)
+ --ptr;
+ continue;
+ case 0:
+ case 0xe0:
+ ch = _getwch(); /* Ignore; this is a function or arrow key */
+ break;
+ default:
+ *ptr++ = ch;
+ break;
+ }
+ }
+ done_reading:
+ ;
+
+#ifndef WC_ERR_INVALID_CHARS
+#define WC_ERR_INVALID_CHARS 0x80
+#endif
+
+ /* Now convert it to UTF-8 */
+ r = WideCharToMultiByte(CP_UTF8,
+ WC_NO_BEST_FIT_CHARS|WC_ERR_INVALID_CHARS,
+ buf, (int)(ptr-buf),
+ output, (int)(buflen-1),
+ NULL, NULL);
+ if (r <= 0) {
+ r = -1;
+ goto done;
+ }
+
+ tor_assert(r < (int)buflen);
+
+ output[r] = 0;
+
+ done:
+ SecureZeroMemory(buf, sizeof(wchar_t)*buflen);
+ tor_free(buf);
+ return r;
+#else
+#error "No implementation for tor_getpass found!"
+#endif /* defined(HAVE_READPASSPHRASE) || ... */
+}
diff --git a/src/lib/term/getpass.h b/src/lib/term/getpass.h
new file mode 100644
index 0000000000..9d03f7036c
--- /dev/null
+++ b/src/lib/term/getpass.h
@@ -0,0 +1,13 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_GETPASS_H
+#define TOR_GETPASS_H
+
+#include "lib/cc/torint.h"
+
+ssize_t tor_getpass(const char *prompt, char *output, size_t buflen);
+
+#endif
diff --git a/src/lib/term/include.am b/src/lib/term/include.am
new file mode 100644
index 0000000000..55fe548ebc
--- /dev/null
+++ b/src/lib/term/include.am
@@ -0,0 +1,24 @@
+
+noinst_LIBRARIES += src/lib/libtor-term.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-term-testing.a
+endif
+
+if BUILD_READPASSPHRASE_C
+readpassphrase_source=src/ext/readpassphrase.c
+else
+readpassphrase_source=
+endif
+
+src_lib_libtor_term_a_SOURCES = \
+ src/lib/term/getpass.c \
+ $(readpassphrase_source)
+
+src_lib_libtor_term_testing_a_SOURCES = \
+ $(src_lib_libtor_term_a_SOURCES)
+src_lib_libtor_term_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_term_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/term/getpass.h
diff --git a/src/lib/testsupport/.may_include b/src/lib/testsupport/.may_include
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/lib/testsupport/.may_include
diff --git a/src/lib/testsupport/include.am b/src/lib/testsupport/include.am
new file mode 100644
index 0000000000..b2aa620985
--- /dev/null
+++ b/src/lib/testsupport/include.am
@@ -0,0 +1,3 @@
+
+noinst_HEADERS += \
+ src/lib/testsupport/testsupport.h
diff --git a/src/common/testsupport.h b/src/lib/testsupport/testsupport.h
index a3f2ff91ed..9a55d306fc 100644
--- a/src/common/testsupport.h
+++ b/src/lib/testsupport/testsupport.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
+/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TESTSUPPORT_H
diff --git a/src/lib/thread/.may_include b/src/lib/thread/.may_include
new file mode 100644
index 0000000000..93ad0cd734
--- /dev/null
+++ b/src/lib/thread/.may_include
@@ -0,0 +1,6 @@
+orconfig.h
+lib/cc/*.h
+lib/lock/*.h
+lib/log/*.h
+lib/testsupport/*.h
+lib/thread/*.h
diff --git a/src/common/compat_pthreads.c b/src/lib/thread/compat_pthreads.c
index 002274c469..246c6254bb 100644
--- a/src/common/compat_pthreads.c
+++ b/src/lib/thread/compat_pthreads.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -11,13 +11,16 @@
*/
#include "orconfig.h"
+#include "lib/thread/threads.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+
+#include <sys/time.h>
#include <pthread.h>
#include <signal.h>
#include <time.h>
-
-#include "compat.h"
-#include "torlog.h"
-#include "util.h"
+#include <errno.h>
+#include <string.h>
/** Wraps a void (*)(void*) function and its argument so we can
* invoke them in a way pthreads would expect.
@@ -91,88 +94,6 @@ spawn_exit(void)
pthread_exit(NULL);
}
-/** A mutex attribute that we're going to use to tell pthreads that we want
- * "recursive" mutexes (i.e., once we can re-lock if we're already holding
- * them.) */
-static pthread_mutexattr_t attr_recursive;
-
-/** Initialize <b>mutex</b> so it can be locked. Every mutex must be set
- * up with tor_mutex_init() or tor_mutex_new(); not both. */
-void
-tor_mutex_init(tor_mutex_t *mutex)
-{
- if (PREDICT_UNLIKELY(!threads_initialized))
- tor_threads_init(); // LCOV_EXCL_LINE
- const int err = pthread_mutex_init(&mutex->mutex, &attr_recursive);
- if (PREDICT_UNLIKELY(err)) {
- // LCOV_EXCL_START
- log_err(LD_GENERAL, "Error %d creating a mutex.", err);
- tor_assert_unreached();
- // LCOV_EXCL_STOP
- }
-}
-
-/** As tor_mutex_init, but initialize a mutex suitable that may be
- * non-recursive, if the OS supports that. */
-void
-tor_mutex_init_nonrecursive(tor_mutex_t *mutex)
-{
- int err;
- if (!threads_initialized)
- tor_threads_init(); // LCOV_EXCL_LINE
- err = pthread_mutex_init(&mutex->mutex, NULL);
- if (PREDICT_UNLIKELY(err)) {
- // LCOV_EXCL_START
- log_err(LD_GENERAL, "Error %d creating a mutex.", err);
- tor_assert_unreached();
- // LCOV_EXCL_STOP
- }
-}
-
-/** Wait until <b>m</b> is free, then acquire it. */
-void
-tor_mutex_acquire(tor_mutex_t *m)
-{
- int err;
- tor_assert(m);
- err = pthread_mutex_lock(&m->mutex);
- if (PREDICT_UNLIKELY(err)) {
- // LCOV_EXCL_START
- log_err(LD_GENERAL, "Error %d locking a mutex.", err);
- tor_assert_unreached();
- // LCOV_EXCL_STOP
- }
-}
-/** Release the lock <b>m</b> so another thread can have it. */
-void
-tor_mutex_release(tor_mutex_t *m)
-{
- int err;
- tor_assert(m);
- err = pthread_mutex_unlock(&m->mutex);
- if (PREDICT_UNLIKELY(err)) {
- // LCOV_EXCL_START
- log_err(LD_GENERAL, "Error %d unlocking a mutex.", err);
- tor_assert_unreached();
- // LCOV_EXCL_STOP
- }
-}
-/** Clean up the mutex <b>m</b> so that it no longer uses any system
- * resources. Does not free <b>m</b>. This function must only be called on
- * mutexes from tor_mutex_init(). */
-void
-tor_mutex_uninit(tor_mutex_t *m)
-{
- int err;
- tor_assert(m);
- err = pthread_mutex_destroy(&m->mutex);
- if (PREDICT_UNLIKELY(err)) {
- // LCOV_EXCL_START
- log_err(LD_GENERAL, "Error %d destroying a mutex.", err);
- tor_assert_unreached();
- // LCOV_EXCL_STOP
- }
-}
/** Return an integer representing this thread. */
unsigned long
tor_get_thread_id(void)
@@ -333,8 +254,7 @@ void
tor_threads_init(void)
{
if (!threads_initialized) {
- pthread_mutexattr_init(&attr_recursive);
- pthread_mutexattr_settype(&attr_recursive, PTHREAD_MUTEX_RECURSIVE);
+ tor_locking_init();
const int ret1 = pthread_attr_init(&attr_detached);
tor_assert(ret1 == 0);
#ifndef PTHREAD_CREATE_DETACHED
@@ -347,4 +267,3 @@ tor_threads_init(void)
set_main_thread();
}
}
-
diff --git a/src/lib/thread/compat_threads.c b/src/lib/thread/compat_threads.c
new file mode 100644
index 0000000000..972960e242
--- /dev/null
+++ b/src/lib/thread/compat_threads.c
@@ -0,0 +1,111 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file compat_threads.c
+ *
+ * \brief Cross-platform threading and inter-thread communication logic.
+ * (Platform-specific parts are written in the other compat_*threads
+ * modules.)
+ */
+
+#include "orconfig.h"
+#include <stdlib.h>
+#include "lib/thread/threads.h"
+
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+
+#include <string.h>
+
+/** Allocate and return a new condition variable. */
+tor_cond_t *
+tor_cond_new(void)
+{
+ tor_cond_t *cond = tor_malloc(sizeof(tor_cond_t));
+ if (BUG(tor_cond_init(cond)<0))
+ tor_free(cond); // LCOV_EXCL_LINE
+ return cond;
+}
+
+/** Free all storage held in <b>c</b>. */
+void
+tor_cond_free_(tor_cond_t *c)
+{
+ if (!c)
+ return;
+ tor_cond_uninit(c);
+ tor_free(c);
+}
+
+/** Identity of the "main" thread */
+static unsigned long main_thread_id = -1;
+
+/** Start considering the current thread to be the 'main thread'. This has
+ * no effect on anything besides in_main_thread(). */
+void
+set_main_thread(void)
+{
+ main_thread_id = tor_get_thread_id();
+}
+/** Return true iff called from the main thread. */
+int
+in_main_thread(void)
+{
+ return main_thread_id == tor_get_thread_id();
+}
+
+#ifndef HAVE_STDATOMIC_H
+/** Initialize a new atomic counter with the value 0 */
+void
+atomic_counter_init(atomic_counter_t *counter)
+{
+ memset(counter, 0, sizeof(*counter));
+ tor_mutex_init_nonrecursive(&counter->mutex);
+}
+/** Clean up all resources held by an atomic counter. */
+void
+atomic_counter_destroy(atomic_counter_t *counter)
+{
+ tor_mutex_uninit(&counter->mutex);
+ memset(counter, 0, sizeof(*counter));
+}
+/** Add a value to an atomic counter. */
+void
+atomic_counter_add(atomic_counter_t *counter, size_t add)
+{
+ tor_mutex_acquire(&counter->mutex);
+ counter->val += add;
+ tor_mutex_release(&counter->mutex);
+}
+/** Subtract a value from an atomic counter. */
+void
+atomic_counter_sub(atomic_counter_t *counter, size_t sub)
+{
+ // this relies on unsigned overflow, but that's fine.
+ atomic_counter_add(counter, -sub);
+}
+/** Return the current value of an atomic counter */
+size_t
+atomic_counter_get(atomic_counter_t *counter)
+{
+ size_t val;
+ tor_mutex_acquire(&counter->mutex);
+ val = counter->val;
+ tor_mutex_release(&counter->mutex);
+ return val;
+}
+/** Replace the value of an atomic counter; return the old one. */
+size_t
+atomic_counter_exchange(atomic_counter_t *counter, size_t newval)
+{
+ size_t oldval;
+ tor_mutex_acquire(&counter->mutex);
+ oldval = counter->val;
+ counter->val = newval;
+ tor_mutex_release(&counter->mutex);
+ return oldval;
+}
+#endif /* !defined(HAVE_STDATOMIC_H) */
diff --git a/src/common/compat_winthreads.c b/src/lib/thread/compat_winthreads.c
index 7021344f6e..7f9877d21e 100644
--- a/src/common/compat_winthreads.c
+++ b/src/lib/thread/compat_winthreads.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,12 +12,12 @@
#ifdef _WIN32
-#include "compat.h"
#include <windows.h>
#include <process.h>
-#include "util.h"
-#include "container.h"
-#include "torlog.h"
+#include "lib/thread/threads.h"
+#include "lib/log/torlog.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
@@ -55,33 +55,6 @@ spawn_exit(void)
// LCOV_EXCL_STOP
}
-void
-tor_mutex_init(tor_mutex_t *m)
-{
- InitializeCriticalSection(&m->mutex);
-}
-void
-tor_mutex_init_nonrecursive(tor_mutex_t *m)
-{
- InitializeCriticalSection(&m->mutex);
-}
-
-void
-tor_mutex_uninit(tor_mutex_t *m)
-{
- DeleteCriticalSection(&m->mutex);
-}
-void
-tor_mutex_acquire(tor_mutex_t *m)
-{
- tor_assert(m);
- EnterCriticalSection(&m->mutex);
-}
-void
-tor_mutex_release(tor_mutex_t *m)
-{
- LeaveCriticalSection(&m->mutex);
-}
unsigned long
tor_get_thread_id(void)
{
@@ -248,4 +221,3 @@ tor_threads_init(void)
}
#endif /* defined(_WIN32) */
-
diff --git a/src/lib/thread/include.am b/src/lib/thread/include.am
new file mode 100644
index 0000000000..9ec23d166e
--- /dev/null
+++ b/src/lib/thread/include.am
@@ -0,0 +1,27 @@
+
+noinst_LIBRARIES += src/lib/libtor-thread.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-thread-testing.a
+endif
+
+if THREADS_PTHREADS
+threads_impl_source=src/lib/thread/compat_pthreads.c
+endif
+if THREADS_WIN32
+threads_impl_source=src/lib/thread/compat_winthreads.c
+endif
+
+src_lib_libtor_thread_a_SOURCES = \
+ src/lib/thread/compat_threads.c \
+ src/lib/thread/numcpus.c \
+ $(threads_impl_source)
+
+src_lib_libtor_thread_testing_a_SOURCES = \
+ $(src_lib_libtor_thread_a_SOURCES)
+src_lib_libtor_thread_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_thread_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/thread/threads.h \
+ src/lib/thread/numcpus.h
diff --git a/src/lib/thread/numcpus.c b/src/lib/thread/numcpus.c
new file mode 100644
index 0000000000..534b0570f8
--- /dev/null
+++ b/src/lib/thread/numcpus.c
@@ -0,0 +1,93 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "lib/thread/numcpus.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include <stdlib.h>
+
+/** Implementation logic for compute_num_cpus(). */
+static int
+compute_num_cpus_impl(void)
+{
+#ifdef _WIN32
+ SYSTEM_INFO info;
+ memset(&info, 0, sizeof(info));
+ GetSystemInfo(&info);
+ if (info.dwNumberOfProcessors >= 1 && info.dwNumberOfProcessors < INT_MAX)
+ return (int)info.dwNumberOfProcessors;
+ else
+ return -1;
+#elif defined(HAVE_SYSCONF)
+#ifdef _SC_NPROCESSORS_CONF
+ long cpus_conf = sysconf(_SC_NPROCESSORS_CONF);
+#else
+ long cpus_conf = -1;
+#endif
+#ifdef _SC_NPROCESSORS_ONLN
+ long cpus_onln = sysconf(_SC_NPROCESSORS_ONLN);
+#else
+ long cpus_onln = -1;
+#endif
+ long cpus = -1;
+
+ if (cpus_conf > 0 && cpus_onln < 0) {
+ cpus = cpus_conf;
+ } else if (cpus_onln > 0 && cpus_conf < 0) {
+ cpus = cpus_onln;
+ } else if (cpus_onln > 0 && cpus_conf > 0) {
+ if (cpus_onln < cpus_conf) {
+ log_notice(LD_GENERAL, "I think we have %ld CPUS, but only %ld of them "
+ "are available. Telling Tor to only use %ld. You can over"
+ "ride this with the NumCPUs option",
+ cpus_conf, cpus_onln, cpus_onln);
+ }
+ cpus = cpus_onln;
+ }
+
+ if (cpus >= 1 && cpus < INT_MAX)
+ return (int)cpus;
+ else
+ return -1;
+#else
+ return -1;
+#endif /* defined(_WIN32) || ... */
+}
+
+#define MAX_DETECTABLE_CPUS 16
+
+/** Return how many CPUs we are running with. We assume that nobody is
+ * using hot-swappable CPUs, so we don't recompute this after the first
+ * time. Return -1 if we don't know how to tell the number of CPUs on this
+ * system.
+ */
+int
+compute_num_cpus(void)
+{
+ static int num_cpus = -2;
+ if (num_cpus == -2) {
+ num_cpus = compute_num_cpus_impl();
+ tor_assert(num_cpus != -2);
+ if (num_cpus > MAX_DETECTABLE_CPUS) {
+ /* LCOV_EXCL_START */
+ log_notice(LD_GENERAL, "Wow! I detected that you have %d CPUs. I "
+ "will not autodetect any more than %d, though. If you "
+ "want to configure more, set NumCPUs in your torrc",
+ num_cpus, MAX_DETECTABLE_CPUS);
+ num_cpus = MAX_DETECTABLE_CPUS;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+ return num_cpus;
+}
diff --git a/src/lib/thread/numcpus.h b/src/lib/thread/numcpus.h
new file mode 100644
index 0000000000..2899a9ec8a
--- /dev/null
+++ b/src/lib/thread/numcpus.h
@@ -0,0 +1,11 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_NUMCPUS_H
+#define TOR_NUMCPUS_H
+
+int compute_num_cpus(void);
+
+#endif
diff --git a/src/common/compat_threads.h b/src/lib/thread/threads.h
index c93e601ec5..fcccc643d5 100644
--- a/src/common/compat_threads.h
+++ b/src/lib/thread/threads.h
@@ -1,62 +1,25 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_COMPAT_THREADS_H
#define TOR_COMPAT_THREADS_H
#include "orconfig.h"
-#include "torint.h"
-#include "testsupport.h"
-
-#if defined(HAVE_PTHREAD_H) && !defined(_WIN32)
-#include <pthread.h>
-#endif
+#include "lib/cc/torint.h"
+#include "lib/testsupport/testsupport.h"
+#include "lib/lock/compat_mutex.h"
#ifdef HAVE_STDATOMIC_H
#include <stdatomic.h>
#endif
-#if defined(_WIN32)
-#define USE_WIN32_THREADS
-#elif defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_CREATE)
-#define USE_PTHREADS
-#else
-#error "No threading system was found"
-#endif /* defined(_WIN32) || ... */
+struct timeval;
int spawn_func(void (*func)(void *), void *data);
void spawn_exit(void) ATTR_NORETURN;
-/* Because we use threads instead of processes on most platforms (Windows,
- * Linux, etc), we need locking for them. On platforms with poor thread
- * support or broken gethostbyname_r, these functions are no-ops. */
-
-/** A generic lock structure for multithreaded builds. */
-typedef struct tor_mutex_t {
-#if defined(USE_WIN32_THREADS)
- /** Windows-only: on windows, we implement locks with CRITICAL_SECTIONS. */
- CRITICAL_SECTION mutex;
-#elif defined(USE_PTHREADS)
- /** Pthreads-only: with pthreads, we implement locks with
- * pthread_mutex_t. */
- pthread_mutex_t mutex;
-#else
- /** No-threads only: Dummy variable so that tor_mutex_t takes up space. */
- int _unused;
-#endif /* defined(USE_WIN32_THREADS) || ... */
-} tor_mutex_t;
-
-tor_mutex_t *tor_mutex_new(void);
-tor_mutex_t *tor_mutex_new_nonrecursive(void);
-void tor_mutex_init(tor_mutex_t *m);
-void tor_mutex_init_nonrecursive(tor_mutex_t *m);
-void tor_mutex_acquire(tor_mutex_t *m);
-void tor_mutex_release(tor_mutex_t *m);
-void tor_mutex_free_(tor_mutex_t *m);
-#define tor_mutex_free(m) FREE_AND_NULL(tor_mutex_t, tor_mutex_free_, (m))
-void tor_mutex_uninit(tor_mutex_t *m);
unsigned long tor_get_thread_id(void);
void tor_threads_init(void);
@@ -91,32 +54,6 @@ int tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex,
void tor_cond_signal_one(tor_cond_t *cond);
void tor_cond_signal_all(tor_cond_t *cond);
-/** Helper type used to manage waking up the main thread while it's in
- * the libevent main loop. Used by the work queue code. */
-typedef struct alert_sockets_s {
- /* XXXX This structure needs a better name. */
- /** Socket that the main thread should listen for EV_READ events on.
- * Note that this socket may be a regular fd on a non-Windows platform.
- */
- tor_socket_t read_fd;
- /** Socket to use when alerting the main thread. */
- tor_socket_t write_fd;
- /** Function to alert the main thread */
- int (*alert_fn)(tor_socket_t write_fd);
- /** Function to make the main thread no longer alerted. */
- int (*drain_fn)(tor_socket_t read_fd);
-} alert_sockets_t;
-
-/* Flags to disable one or more alert_sockets backends. */
-#define ASOCKS_NOEVENTFD2 (1u<<0)
-#define ASOCKS_NOEVENTFD (1u<<1)
-#define ASOCKS_NOPIPE2 (1u<<2)
-#define ASOCKS_NOPIPE (1u<<3)
-#define ASOCKS_NOSOCKETPAIR (1u<<4)
-
-int alert_sockets_create(alert_sockets_t *socks_out, uint32_t flags);
-void alert_sockets_close(alert_sockets_t *socks);
-
typedef struct tor_threadlocal_s {
#ifdef _WIN32
DWORD index;
@@ -220,4 +157,3 @@ atomic_counter_exchange(atomic_counter_t *counter, size_t newval)
#endif /* defined(HAVE_STDATOMIC_H) */
#endif /* !defined(TOR_COMPAT_THREADS_H) */
-
diff --git a/src/lib/time/.may_include b/src/lib/time/.may_include
new file mode 100644
index 0000000000..2c7e37a836
--- /dev/null
+++ b/src/lib/time/.may_include
@@ -0,0 +1,11 @@
+orconfig.h
+
+lib/cc/*.h
+lib/err/*.h
+lib/intmath/*.h
+lib/log/*.h
+lib/time/*.h
+lib/wallclock/*.h
+
+# For load_windows_system_lib.
+lib/fs/winlib.h \ No newline at end of file
diff --git a/src/common/compat_time.c b/src/lib/time/compat_time.c
index 40847a8442..2ea6eca988 100644
--- a/src/common/compat_time.c
+++ b/src/lib/time/compat_time.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,7 +10,15 @@
**/
#define COMPAT_TIME_PRIVATE
-#include "compat.h"
+#include "lib/time/compat_time.h"
+
+#include "lib/err/torerr.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/intmath/muldiv.h"
+#include "lib/intmath/bits.h"
+#include "lib/fs/winlib.h"
+#include "lib/wallclock/timeval.h"
#ifdef _WIN32
#include <winsock2.h>
@@ -20,6 +28,9 @@
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -34,15 +45,9 @@
#include <mach/mach_time.h>
#endif
-#include "torlog.h"
-#include "util.h"
-#include "container.h"
-
-#ifndef HAVE_GETTIMEOFDAY
-#ifdef HAVE_FTIME
-#include <sys/timeb.h>
-#endif
-#endif
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
#ifdef _WIN32
#undef HAVE_CLOCK_GETTIME
@@ -68,54 +73,6 @@ tor_sleep_msec(int msec)
}
#endif /* defined(TOR_UNIT_TESTS) */
-/** Set *timeval to the current time of day. On error, log and terminate.
- * (Same as gettimeofday(timeval,NULL), but never returns -1.)
- */
-MOCK_IMPL(void,
-tor_gettimeofday, (struct timeval *timeval))
-{
-#ifdef _WIN32
- /* Epoch bias copied from perl: number of units between windows epoch and
- * Unix epoch. */
-#define EPOCH_BIAS U64_LITERAL(116444736000000000)
-#define UNITS_PER_SEC U64_LITERAL(10000000)
-#define USEC_PER_SEC U64_LITERAL(1000000)
-#define UNITS_PER_USEC U64_LITERAL(10)
- union {
- uint64_t ft_64;
- FILETIME ft_ft;
- } ft;
- /* number of 100-nsec units since Jan 1, 1601 */
- GetSystemTimeAsFileTime(&ft.ft_ft);
- if (ft.ft_64 < EPOCH_BIAS) {
- /* LCOV_EXCL_START */
- log_err(LD_GENERAL,"System time is before 1970; failing.");
- exit(1); // exit ok: system clock is broken.
- /* LCOV_EXCL_STOP */
- }
- ft.ft_64 -= EPOCH_BIAS;
- timeval->tv_sec = (unsigned) (ft.ft_64 / UNITS_PER_SEC);
- timeval->tv_usec = (unsigned) ((ft.ft_64 / UNITS_PER_USEC) % USEC_PER_SEC);
-#elif defined(HAVE_GETTIMEOFDAY)
- if (gettimeofday(timeval, NULL)) {
- /* LCOV_EXCL_START */
- log_err(LD_GENERAL,"gettimeofday failed.");
- /* If gettimeofday dies, we have either given a bad timezone (we didn't),
- or segfaulted.*/
- exit(1); // exit ok: gettimeofday failed.
- /* LCOV_EXCL_STOP */
- }
-#elif defined(HAVE_FTIME)
- struct timeb tb;
- ftime(&tb);
- timeval->tv_sec = tb.time;
- timeval->tv_usec = tb.millitm * 1000;
-#else
-#error "No way to get time."
-#endif /* defined(_WIN32) || ... */
- return;
-}
-
#define ONE_MILLION ((int64_t) (1000 * 1000))
#define ONE_BILLION ((int64_t) (1000 * 1000 * 1000))
@@ -900,4 +857,3 @@ monotime_msec_to_approx_coarse_stamp_units(uint64_t msec)
return (msec * STAMP_TICKS_PER_SECOND) / 1000;
}
#endif
-
diff --git a/src/common/compat_time.h b/src/lib/time/compat_time.h
index 57ab20ab11..4427ce8f92 100644
--- a/src/common/compat_time.h
+++ b/src/lib/time/compat_time.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,6 +19,10 @@
#define TOR_COMPAT_TIME_H
#include "orconfig.h"
+#include "lib/cc/torint.h"
+
+#include "lib/wallclock/tor_gettimeofday.h"
+
#ifdef _WIN32
#undef HAVE_CLOCK_GETTIME
#endif
@@ -200,8 +204,6 @@ monotime_coarse_diff_msec32(const monotime_coarse_t *start,
#endif
}
-MOCK_DECL(void, tor_gettimeofday, (struct timeval *timeval));
-
#ifdef TOR_UNIT_TESTS
void tor_sleep_msec(int msec);
@@ -230,4 +232,3 @@ void monotime_reset_ratchets_for_testing(void);
#endif /* defined(COMPAT_TIME_PRIVATE) */
#endif /* !defined(TOR_COMPAT_TIME_H) */
-
diff --git a/src/lib/time/include.am b/src/lib/time/include.am
new file mode 100644
index 0000000000..a3f93a3744
--- /dev/null
+++ b/src/lib/time/include.am
@@ -0,0 +1,19 @@
+
+noinst_LIBRARIES += src/lib/libtor-time.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-time-testing.a
+endif
+
+src_lib_libtor_time_a_SOURCES = \
+ src/lib/time/compat_time.c \
+ src/lib/time/tvdiff.c
+
+src_lib_libtor_time_testing_a_SOURCES = \
+ $(src_lib_libtor_time_a_SOURCES)
+src_lib_libtor_time_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_time_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/time/compat_time.h \
+ src/lib/time/tvdiff.h
diff --git a/src/lib/time/tvdiff.c b/src/lib/time/tvdiff.c
new file mode 100644
index 0000000000..cfd1ace771
--- /dev/null
+++ b/src/lib/time/tvdiff.c
@@ -0,0 +1,162 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "lib/time/tvdiff.h"
+
+#include "lib/cc/compat_compiler.h"
+#include "lib/log/torlog.h"
+
+#ifdef _WIN32
+#include <winsock2.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#define TOR_USEC_PER_SEC 1000000
+
+/** Return the difference between start->tv_sec and end->tv_sec.
+ * Returns INT64_MAX on overflow and underflow.
+ */
+static int64_t
+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,
+ * but it's easy to see that it's correct and doesn't overflow */
+
+ if (s > 0 && e < INT64_MIN + s) {
+ /* s is positive: equivalent to e - s < INT64_MIN, but without any
+ * overflow */
+ return INT64_MAX;
+ } else if (s < 0 && e > INT64_MAX + s) {
+ /* s is negative: equivalent to e - s > INT64_MAX, but without any
+ * overflow */
+ return INT64_MAX;
+ }
+
+ return e - s;
+}
+
+/** Return the number of microseconds elapsed between *start and *end.
+ * Returns LONG_MAX on overflow and underflow.
+ */
+long
+tv_udiff(const struct timeval *start, const struct timeval *end)
+{
+ /* Sanity check tv_usec */
+ if (start->tv_usec > TOR_USEC_PER_SEC || start->tv_usec < 0) {
+ log_warn(LD_GENERAL, "comparing times on microsecond detail with bad "
+ "start tv_usec: %"PRId64 " microseconds",
+ (int64_t)start->tv_usec);
+ return LONG_MAX;
+ }
+
+ if (end->tv_usec > TOR_USEC_PER_SEC || end->tv_usec < 0) {
+ log_warn(LD_GENERAL, "comparing times on microsecond detail with bad "
+ "end tv_usec: %"PRId64 " microseconds",
+ (int64_t)end->tv_usec);
+ return LONG_MAX;
+ }
+
+ /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
+ */
+ int64_t udiff;
+ const int64_t secdiff = tv_secdiff_impl(start, end);
+
+ /* end->tv_usec - start->tv_usec can be up to 1 second either way */
+ if (secdiff > (int64_t)(LONG_MAX/1000000 - 1) ||
+ secdiff < (int64_t)(LONG_MIN/1000000 + 1)) {
+ log_warn(LD_GENERAL, "comparing times on microsecond detail too far "
+ "apart: %"PRId64 " seconds", (secdiff));
+ return LONG_MAX;
+ }
+
+ /* we'll never get an overflow here, because we check that both usecs are
+ * between 0 and TV_USEC_PER_SEC. */
+ udiff = secdiff*1000000 + ((int64_t)end->tv_usec - (int64_t)start->tv_usec);
+
+ /* Some compilers are smart enough to work out this is a no-op on L64 */
+#if SIZEOF_LONG < 8
+ if (udiff > (int64_t)LONG_MAX || udiff < (int64_t)LONG_MIN) {
+ return LONG_MAX;
+ }
+#endif
+
+ return (long)udiff;
+}
+
+/** Return the number of milliseconds elapsed between *start and *end.
+ * If the tv_usec difference is 500, rounds away from zero.
+ * Returns LONG_MAX on overflow and underflow.
+ */
+long
+tv_mdiff(const struct timeval *start, const struct timeval *end)
+{
+ /* Sanity check tv_usec */
+ if (start->tv_usec > TOR_USEC_PER_SEC || start->tv_usec < 0) {
+ log_warn(LD_GENERAL, "comparing times on millisecond detail with bad "
+ "start tv_usec: %"PRId64 " microseconds",
+ (int64_t)start->tv_usec);
+ return LONG_MAX;
+ }
+
+ if (end->tv_usec > TOR_USEC_PER_SEC || end->tv_usec < 0) {
+ log_warn(LD_GENERAL, "comparing times on millisecond detail with bad "
+ "end tv_usec: %"PRId64 " microseconds",
+ (int64_t)end->tv_usec);
+ return LONG_MAX;
+ }
+
+ /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
+ */
+ int64_t mdiff;
+ const int64_t secdiff = tv_secdiff_impl(start, end);
+
+ /* end->tv_usec - start->tv_usec can be up to 1 second either way, but the
+ * mdiff calculation may add another temporary second for rounding.
+ * Whether this actually causes overflow depends on the compiler's constant
+ * folding and order of operations. */
+ if (secdiff > (int64_t)(LONG_MAX/1000 - 2) ||
+ secdiff < (int64_t)(LONG_MIN/1000 + 1)) {
+ log_warn(LD_GENERAL, "comparing times on millisecond detail too far "
+ "apart: %"PRId64 " seconds", (int64_t)secdiff);
+ return LONG_MAX;
+ }
+
+ /* Subtract and round */
+ mdiff = secdiff*1000 +
+ /* We add a million usec here to ensure that the result is positive,
+ * so that the round-towards-zero behavior of the division will give
+ * the right result for rounding to the nearest msec. Later we subtract
+ * 1000 in order to get the correct result.
+ * We'll never get an overflow here, because we check that both usecs are
+ * between 0 and TV_USEC_PER_SEC. */
+ ((int64_t)end->tv_usec - (int64_t)start->tv_usec + 500 + 1000000) / 1000
+ - 1000;
+
+ /* Some compilers are smart enough to work out this is a no-op on L64 */
+#if SIZEOF_LONG < 8
+ if (mdiff > (int64_t)LONG_MAX || mdiff < (int64_t)LONG_MIN) {
+ return LONG_MAX;
+ }
+#endif
+
+ return (long)mdiff;
+}
+
+/**
+ * Converts timeval to milliseconds.
+ */
+int64_t
+tv_to_msec(const struct timeval *tv)
+{
+ int64_t conv = ((int64_t)tv->tv_sec)*1000L;
+ /* Round ghetto-style */
+ conv += ((int64_t)tv->tv_usec+500)/1000L;
+ return conv;
+}
diff --git a/src/lib/time/tvdiff.h b/src/lib/time/tvdiff.h
new file mode 100644
index 0000000000..215de9cf37
--- /dev/null
+++ b/src/lib/time/tvdiff.h
@@ -0,0 +1,16 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_TVDIFF_H
+#define TOR_TVDIFF_H
+
+#include "lib/cc/torint.h"
+struct timeval;
+
+long tv_udiff(const struct timeval *start, const struct timeval *end);
+long tv_mdiff(const struct timeval *start, const struct timeval *end);
+int64_t tv_to_msec(const struct timeval *tv);
+
+#endif
diff --git a/src/lib/tls/.may_include b/src/lib/tls/.may_include
new file mode 100644
index 0000000000..ca7cb455e4
--- /dev/null
+++ b/src/lib/tls/.may_include
@@ -0,0 +1,16 @@
+orconfig.h
+
+lib/arch/*.h
+lib/cc/*.h
+lib/container/*.h
+lib/crypt_ops/*.h
+lib/ctime/*.h
+lib/encoding/*.h
+lib/intmath/*.h
+lib/log/*.h
+lib/net/*.h
+lib/string/*.h
+lib/testsupport/testsupport.h
+lib/tls/*.h
+
+ciphers.inc
diff --git a/src/common/buffers_tls.c b/src/lib/tls/buffers_tls.c
index 041f78b818..243e0eb0bc 100644
--- a/src/common/buffers_tls.c
+++ b/src/lib/tls/buffers_tls.c
@@ -1,20 +1,19 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define BUFFERS_PRIVATE
#include "orconfig.h"
#include <stddef.h>
-#include "buffers.h"
-#include "buffers_tls.h"
-#include "compat.h"
-#include "compress.h"
-#include "util.h"
-#include "torint.h"
-#include "torlog.h"
-#include "tortls.h"
+#include "lib/container/buffers.h"
+#include "lib/tls/buffers_tls.h"
+#include "lib/cc/torint.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/tls/tortls.h"
+
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -176,4 +175,3 @@ buf_flush_to_tls(buf_t *buf, tor_tls_t *tls, size_t flushlen,
tor_assert(flushed < INT_MAX);
return (int)flushed;
}
-
diff --git a/src/common/buffers_tls.h b/src/lib/tls/buffers_tls.h
index 2f9fda45a0..d9d26c82bd 100644
--- a/src/common/buffers_tls.h
+++ b/src/lib/tls/buffers_tls.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_BUFFERS_TLS_H
diff --git a/src/common/ciphers.inc b/src/lib/tls/ciphers.inc
index 0084b3e325..0084b3e325 100644
--- a/src/common/ciphers.inc
+++ b/src/lib/tls/ciphers.inc
diff --git a/src/lib/tls/include.am b/src/lib/tls/include.am
new file mode 100644
index 0000000000..b3b013f4dd
--- /dev/null
+++ b/src/lib/tls/include.am
@@ -0,0 +1,20 @@
+
+noinst_LIBRARIES += src/lib/libtor-tls.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-tls-testing.a
+endif
+
+src_lib_libtor_tls_a_SOURCES = \
+ src/lib/tls/buffers_tls.c \
+ src/lib/tls/tortls.c
+
+src_lib_libtor_tls_testing_a_SOURCES = \
+ $(src_lib_libtor_tls_a_SOURCES)
+src_lib_libtor_tls_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_tls_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/tls/ciphers.inc \
+ src/lib/tls/buffers_tls.h \
+ src/lib/tls/tortls.h
diff --git a/src/common/tortls.c b/src/lib/tls/tortls.c
index 669742c9dd..1cd22a7eba 100644
--- a/src/common/tortls.c
+++ b/src/lib/tls/tortls.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,16 +19,15 @@
#define TORTLS_PRIVATE
#define TORTLS_OPENSSL_PRIVATE
-#include <assert.h>
#ifdef _WIN32 /*wrkard for dtls1.h >= 0.9.8m of "#include <winsock.h>"*/
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
-#include "crypto.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "compat.h"
+#include "lib/crypt_ops/crypto.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "lib/crypt_ops/crypto_util.h"
/* Some versions of OpenSSL declare SSL_get_selected_srtp_profile twice in
* srtp.h. Suppress the GCC warning so we can build with -Wredundant-decl. */
@@ -52,12 +51,22 @@ DISABLE_GCC_WARNING(redundant-decls)
ENABLE_GCC_WARNING(redundant-decls)
#define TORTLS_PRIVATE
-#include "tortls.h"
-#include "util.h"
-#include "torlog.h"
-#include "container.h"
+#include "lib/tls/tortls.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/container/smartlist.h"
+#include "lib/string/compat_string.h"
+#include "lib/string/printf.h"
+#include "lib/net/socket.h"
+#include "lib/intmath/cmp.h"
+#include "lib/ctime/di_ops.h"
+#include "lib/encoding/time_fmt.h"
+
+#include <stdlib.h>
#include <string.h>
+#include "lib/arch/bytes.h"
+
#ifdef OPENSSL_1_1_API
#define X509_get_notBefore_const(cert) \
X509_get0_notBefore(cert)
@@ -1392,7 +1401,7 @@ find_cipher_by_id(const SSL *ssl, const SSL_METHOD *m, uint16_t cipher)
{
unsigned char cipherid[3];
tor_assert(ssl);
- set_uint16(cipherid, htons(cipher));
+ set_uint16(cipherid, tor_htons(cipher));
cipherid[2] = 0; /* If ssl23_get_cipher_by_char finds no cipher starting
* with a two-byte 'cipherid', it may look for a v2
* cipher with the appropriate 3 bytes. */
@@ -1406,7 +1415,7 @@ find_cipher_by_id(const SSL *ssl, const SSL_METHOD *m, uint16_t cipher)
# if defined(HAVE_STRUCT_SSL_METHOD_ST_GET_CIPHER_BY_CHAR)
if (m && m->get_cipher_by_char) {
unsigned char cipherid[3];
- set_uint16(cipherid, htons(cipher));
+ set_uint16(cipherid, tor_htons(cipher));
cipherid[2] = 0; /* If ssl23_get_cipher_by_char finds no cipher starting
* with a two-byte 'cipherid', it may look for a v2
* cipher with the appropriate 3 bytes. */
@@ -2433,8 +2442,8 @@ tls_get_write_overhead_ratio,(void))
if (total_bytes_written_over_tls == 0)
return 1.0;
- return U64_TO_DBL(total_bytes_written_by_tls) /
- U64_TO_DBL(total_bytes_written_over_tls);
+ return ((double)total_bytes_written_by_tls) /
+ ((double)total_bytes_written_over_tls);
}
/** Implement check_no_tls_errors: If there are any pending OpenSSL
@@ -2660,4 +2669,3 @@ evaluate_ecgroup_for_tls(const char *ecgroup)
return ret;
}
-
diff --git a/src/common/tortls.h b/src/lib/tls/tortls.h
index 7c867bfff2..fe192b2abc 100644
--- a/src/common/tortls.h
+++ b/src/lib/tls/tortls.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TORTLS_H
@@ -11,10 +11,9 @@
* \brief Headers for tortls.c
**/
-#include "crypto_rsa.h"
-#include "compat_openssl.h"
-#include "compat.h"
-#include "testsupport.h"
+#include "lib/crypt_ops/crypto_rsa.h"
+#include "lib/crypt_ops/compat_openssl.h"
+#include "lib/testsupport/testsupport.h"
/* Opaque structure to hold a TLS connection. */
typedef struct tor_tls_t tor_tls_t;
@@ -292,4 +291,3 @@ const char *tor_tls_get_ciphersuite_name(tor_tls_t *tls);
int evaluate_ecgroup_for_tls(const char *ecgroup);
#endif /* !defined(TOR_TORTLS_H) */
-
diff --git a/src/lib/trace/.may_include b/src/lib/trace/.may_include
new file mode 100644
index 0000000000..45cd13676b
--- /dev/null
+++ b/src/lib/trace/.may_include
@@ -0,0 +1,3 @@
+orconfig.h
+lib/log/*.h
+lib/trace/*.h
diff --git a/src/trace/debug.h b/src/lib/trace/debug.h
index 3a1652543a..9b5d9d05c8 100644
--- a/src/trace/debug.h
+++ b/src/lib/trace/debug.h
@@ -1,10 +1,10 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TRACE_LOG_DEBUG_H
#define TOR_TRACE_LOG_DEBUG_H
-#include "torlog.h"
+#include "lib/log/torlog.h"
/* Stringify pre-processor trick. */
#define XSTR(d) STR(d)
diff --git a/src/trace/events.h b/src/lib/trace/events.h
index 1be1fd596e..6d4269aaed 100644
--- a/src/trace/events.h
+++ b/src/lib/trace/events.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -31,7 +31,7 @@
/* Enable event tracing for the debug framework where all trace events are
* mapped to a log_debug(). */
#ifdef USE_EVENT_TRACING_DEBUG
-#include "trace/debug.h"
+#include "lib/trace/debug.h"
#endif
#else /* TOR_EVENT_TRACING_ENABLED */
diff --git a/src/lib/trace/include.am b/src/lib/trace/include.am
new file mode 100644
index 0000000000..6f10c98744
--- /dev/null
+++ b/src/lib/trace/include.am
@@ -0,0 +1,18 @@
+
+noinst_LIBRARIES += \
+ src/lib/libtor-trace.a
+
+TRACEHEADERS = \
+ src/lib/trace/trace.h \
+ src/lib/trace/events.h
+
+if USE_EVENT_TRACING_DEBUG
+TRACEHEADERS += \
+ src/lib/trace/debug.h
+endif
+
+# Library source files.
+src_lib_libtor_trace_a_SOURCES = \
+ src/lib/trace/trace.c
+
+noinst_HEADERS+= $(TRACEHEADERS)
diff --git a/src/trace/trace.c b/src/lib/trace/trace.c
index fcdb80091f..c0bbbb0cc6 100644
--- a/src/trace/trace.c
+++ b/src/lib/trace/trace.c
@@ -1,7 +1,7 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "trace.h"
+#include "lib/trace/trace.h"
/** Initialize the tracing library. */
void
diff --git a/src/trace/trace.h b/src/lib/trace/trace.h
index 28fcd8eea8..2dd51aace1 100644
--- a/src/trace/trace.h
+++ b/src/lib/trace/trace.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TRACE_TRACE_H
diff --git a/src/lib/wallclock/.may_include b/src/lib/wallclock/.may_include
new file mode 100644
index 0000000000..dc010da063
--- /dev/null
+++ b/src/lib/wallclock/.may_include
@@ -0,0 +1,6 @@
+orconfig.h
+lib/cc/*.h
+lib/err/*.h
+lib/wallclock/*.h
+lib/string/*.h
+lib/testsupport/*.h
diff --git a/src/lib/wallclock/approx_time.c b/src/lib/wallclock/approx_time.c
new file mode 100644
index 0000000000..2528954f13
--- /dev/null
+++ b/src/lib/wallclock/approx_time.c
@@ -0,0 +1,38 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "lib/wallclock/approx_time.h"
+
+/* =====
+ * Cached time
+ * ===== */
+
+#ifndef TIME_IS_FAST
+/** Cached estimate of the current time. Updated around once per second;
+ * may be a few seconds off if we are really busy. This is a hack to avoid
+ * calling time(NULL) (which not everybody has optimized) on critical paths.
+ */
+static time_t cached_approx_time = 0;
+
+/** Return a cached estimate of the current time from when
+ * update_approx_time() was last called. This is a hack to avoid calling
+ * time(NULL) on critical paths: please do not even think of calling it
+ * anywhere else. */
+time_t
+approx_time(void)
+{
+ return cached_approx_time;
+}
+
+/** Update the cached estimate of the current time. This function SHOULD be
+ * called once per second, and MUST be called before the first call to
+ * get_approx_time. */
+void
+update_approx_time(time_t now)
+{
+ cached_approx_time = now;
+}
+#endif /* !defined(TIME_IS_FAST) */
diff --git a/src/lib/wallclock/approx_time.h b/src/lib/wallclock/approx_time.h
new file mode 100644
index 0000000000..c57ff5bcd3
--- /dev/null
+++ b/src/lib/wallclock/approx_time.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_APPROX_TIME_H
+#define TOR_APPROX_TIME_H
+
+#include <time.h>
+
+/* Cached time */
+#ifdef TIME_IS_FAST
+#define approx_time() time(NULL)
+#define update_approx_time(t) STMT_NIL
+#else
+time_t approx_time(void);
+void update_approx_time(time_t now);
+#endif /* defined(TIME_IS_FAST) */
+
+#endif
diff --git a/src/lib/wallclock/include.am b/src/lib/wallclock/include.am
new file mode 100644
index 0000000000..7864c21e16
--- /dev/null
+++ b/src/lib/wallclock/include.am
@@ -0,0 +1,22 @@
+
+noinst_LIBRARIES += src/lib/libtor-wallclock.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-wallclock-testing.a
+endif
+
+src_lib_libtor_wallclock_a_SOURCES = \
+ src/lib/wallclock/approx_time.c \
+ src/lib/wallclock/tm_cvt.c \
+ src/lib/wallclock/tor_gettimeofday.c
+
+src_lib_libtor_wallclock_testing_a_SOURCES = \
+ $(src_lib_libtor_wallclock_a_SOURCES)
+src_lib_libtor_wallclock_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_wallclock_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/wallclock/approx_time.h \
+ src/lib/wallclock/timeval.h \
+ src/lib/wallclock/tm_cvt.h \
+ src/lib/wallclock/tor_gettimeofday.h
diff --git a/src/lib/wallclock/timeval.c b/src/lib/wallclock/timeval.c
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/lib/wallclock/timeval.c
diff --git a/src/lib/wallclock/timeval.h b/src/lib/wallclock/timeval.h
new file mode 100644
index 0000000000..6a9b36a022
--- /dev/null
+++ b/src/lib/wallclock/timeval.h
@@ -0,0 +1,58 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_TIMEVAL_H
+#define TOR_TIMEVAL_H
+
+#include "orconfig.h"
+#include "lib/cc/torint.h"
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifndef timeradd
+/** Replacement for timeradd on platforms that do not have it: sets tvout to
+ * the sum of tv1 and tv2. */
+#define timeradd(tv1,tv2,tvout) \
+ do { \
+ (tvout)->tv_sec = (tv1)->tv_sec + (tv2)->tv_sec; \
+ (tvout)->tv_usec = (tv1)->tv_usec + (tv2)->tv_usec; \
+ if ((tvout)->tv_usec >= 1000000) { \
+ (tvout)->tv_usec -= 1000000; \
+ (tvout)->tv_sec++; \
+ } \
+ } while (0)
+#endif /* !defined(timeradd) */
+
+#ifndef timersub
+/** Replacement for timersub on platforms that do not have it: sets tvout to
+ * tv1 minus tv2. */
+#define timersub(tv1,tv2,tvout) \
+ do { \
+ (tvout)->tv_sec = (tv1)->tv_sec - (tv2)->tv_sec; \
+ (tvout)->tv_usec = (tv1)->tv_usec - (tv2)->tv_usec; \
+ if ((tvout)->tv_usec < 0) { \
+ (tvout)->tv_usec += 1000000; \
+ (tvout)->tv_sec--; \
+ } \
+ } while (0)
+#endif /* !defined(timersub) */
+
+#ifndef timercmp
+/** Replacement for timercmp on platforms that do not have it: returns true
+ * iff the relational operator "op" makes the expression tv1 op tv2 true.
+ *
+ * Note that while this definition should work for all boolean operators, some
+ * platforms' native timercmp definitions do not support >=, <=, or ==. So
+ * don't use those.
+ */
+#define timercmp(tv1,tv2,op) \
+ (((tv1)->tv_sec == (tv2)->tv_sec) ? \
+ ((tv1)->tv_usec op (tv2)->tv_usec) : \
+ ((tv1)->tv_sec op (tv2)->tv_sec))
+#endif /* !defined(timercmp) */
+
+#endif
diff --git a/src/lib/wallclock/tm_cvt.c b/src/lib/wallclock/tm_cvt.c
new file mode 100644
index 0000000000..31d929e635
--- /dev/null
+++ b/src/lib/wallclock/tm_cvt.c
@@ -0,0 +1,195 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "lib/cc/torint.h"
+#include "lib/cc/compat_compiler.h"
+#include "lib/wallclock/tm_cvt.h"
+#include "lib/string/printf.h"
+#include "lib/err/torerr.h"
+
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+#include <stdlib.h>
+
+#if !defined(_WIN32)
+/** Defined iff we need to add locks when defining fake versions of reentrant
+ * versions of time-related functions. */
+#define TIME_FNS_NEED_LOCKS
+#endif
+
+/** Helper: Deal with confused or out-of-bounds values from localtime_r and
+ * friends. (On some platforms, they can give out-of-bounds values or can
+ * return NULL.) If <b>islocal</b>, this is a localtime result; otherwise
+ * it's from gmtime. The function returns <b>r</b>, when given <b>timep</b>
+ * as its input. If we need to store new results, store them in
+ * <b>resultbuf</b>. */
+static struct tm *
+correct_tm(int islocal, const time_t *timep, struct tm *resultbuf,
+ struct tm *r, char **err_out)
+{
+ const char *outcome;
+
+ if (PREDICT_LIKELY(r)) {
+ /* We can't strftime dates after 9999 CE, and we want to avoid dates
+ * before 1 CE (avoiding the year 0 issue and negative years). */
+ if (r->tm_year > 8099) {
+ r->tm_year = 8099;
+ r->tm_mon = 11;
+ r->tm_mday = 31;
+ r->tm_yday = 364;
+ r->tm_wday = 6;
+ r->tm_hour = 23;
+ r->tm_min = 59;
+ r->tm_sec = 59;
+ } else if (r->tm_year < (1-1900)) {
+ r->tm_year = (1-1900);
+ r->tm_mon = 0;
+ r->tm_mday = 1;
+ r->tm_yday = 0;
+ r->tm_wday = 0;
+ r->tm_hour = 0;
+ r->tm_min = 0;
+ r->tm_sec = 0;
+ }
+ return r;
+ }
+
+ /* If we get here, gmtime or localtime returned NULL. It might have done
+ * this because of overrun or underrun, or it might have done it because of
+ * some other weird issue. */
+ if (timep) {
+ if (*timep < 0) {
+ r = resultbuf;
+ r->tm_year = 70; /* 1970 CE */
+ r->tm_mon = 0;
+ r->tm_mday = 1;
+ r->tm_yday = 0;
+ r->tm_wday = 0;
+ r->tm_hour = 0;
+ r->tm_min = 0 ;
+ r->tm_sec = 0;
+ outcome = "Rounding up to 1970";
+ goto done;
+ } else if (*timep >= INT32_MAX) {
+ /* Rounding down to INT32_MAX isn't so great, but keep in mind that we
+ * only do it if gmtime/localtime tells us NULL. */
+ r = resultbuf;
+ r->tm_year = 137; /* 2037 CE */
+ r->tm_mon = 11;
+ r->tm_mday = 31;
+ r->tm_yday = 364;
+ r->tm_wday = 6;
+ r->tm_hour = 23;
+ r->tm_min = 59;
+ r->tm_sec = 59;
+ outcome = "Rounding down to 2037";
+ goto done;
+ }
+ }
+
+ /* If we get here, then gmtime/localtime failed without getting an extreme
+ * value for *timep */
+ /* LCOV_EXCL_START */
+ r = resultbuf;
+ memset(resultbuf, 0, sizeof(struct tm));
+ outcome="can't recover";
+ /* LCOV_EXCL_STOP */
+ done:
+ if (err_out) {
+ tor_asprintf(err_out, "%s(%"PRId64") failed with error %s: %s",
+ islocal?"localtime":"gmtime",
+ timep?((int64_t)*timep):0,
+ strerror(errno),
+ outcome);
+ }
+ return r;
+}
+
+/** @{ */
+/** As localtime_r, but defined for platforms that don't have it:
+ *
+ * Convert *<b>timep</b> to a struct tm in local time, and store the value in
+ * *<b>result</b>. Return the result on success, or NULL on failure.
+ */
+#ifdef HAVE_LOCALTIME_R
+struct tm *
+tor_localtime_r_msg(const time_t *timep, struct tm *result, char **err_out)
+{
+ struct tm *r;
+ r = localtime_r(timep, result);
+ return correct_tm(1, timep, result, r, err_out);
+}
+#elif defined(TIME_FNS_NEED_LOCKS)
+struct tm *
+tor_localtime_r_msg(const time_t *timep, struct tm *result, char **err_out)
+{
+ struct tm *r;
+ static tor_mutex_t *m=NULL;
+ if (!m) { m=tor_mutex_new(); }
+ raw_assert(result);
+ tor_mutex_acquire(m);
+ r = localtime(timep);
+ if (r)
+ memcpy(result, r, sizeof(struct tm));
+ tor_mutex_release(m);
+ return correct_tm(1, timep, result, r, err_out);
+}
+#else
+struct tm *
+tor_localtime_r_msg(const time_t *timep, struct tm *result, char **err_out)
+{
+ struct tm *r;
+ raw_assert(result);
+ r = localtime(timep);
+ if (r)
+ memcpy(result, r, sizeof(struct tm));
+ return correct_tm(1, timep, result, r, err_out);
+}
+#endif /* defined(HAVE_LOCALTIME_R) || ... */
+/** @} */
+
+/** @{ */
+/** As gmtime_r, but defined for platforms that don't have it:
+ *
+ * Convert *<b>timep</b> to a struct tm in UTC, and store the value in
+ * *<b>result</b>. Return the result on success, or NULL on failure.
+ */
+#ifdef HAVE_GMTIME_R
+struct tm *
+tor_gmtime_r_msg(const time_t *timep, struct tm *result, char **err_out)
+{
+ struct tm *r;
+ r = gmtime_r(timep, result);
+ return correct_tm(0, timep, result, r, err_out);
+}
+#elif defined(TIME_FNS_NEED_LOCKS)
+struct tm *
+tor_gmtime_r_msg(const time_t *timep, struct tm *result, char **err_out)
+{
+ struct tm *r;
+ static tor_mutex_t *m=NULL;
+ if (!m) { m=tor_mutex_new(); }
+ raw_assert(result);
+ tor_mutex_acquire(m);
+ r = gmtime(timep);
+ if (r)
+ memcpy(result, r, sizeof(struct tm));
+ tor_mutex_release(m);
+ return correct_tm(0, timep, result, r, err_out);
+}
+#else
+struct tm *
+tor_gmtime_r_msg(const time_t *timep, struct tm *result, char **err_out)
+{
+ struct tm *r;
+ raw_assert(result);
+ r = gmtime(timep);
+ if (r)
+ memcpy(result, r, sizeof(struct tm));
+ return correct_tm(0, timep, result, r, err_out);
+}
+#endif /* defined(HAVE_GMTIME_R) || ... */
diff --git a/src/lib/wallclock/tm_cvt.h b/src/lib/wallclock/tm_cvt.h
new file mode 100644
index 0000000000..4d87acd4fa
--- /dev/null
+++ b/src/lib/wallclock/tm_cvt.h
@@ -0,0 +1,17 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_WALLCLOCK_TM_CVT_H
+#define TOR_WALLCLOCK_TM_CVT_H
+
+#include <sys/types.h>
+
+struct tm;
+struct tm *tor_localtime_r_msg(const time_t *timep, struct tm *result,
+ char **err_out);
+struct tm *tor_gmtime_r_msg(const time_t *timep, struct tm *result,
+ char **err_out);
+
+#endif
diff --git a/src/lib/wallclock/tor_gettimeofday.c b/src/lib/wallclock/tor_gettimeofday.c
new file mode 100644
index 0000000000..eb902e681d
--- /dev/null
+++ b/src/lib/wallclock/tor_gettimeofday.c
@@ -0,0 +1,82 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file compat_time.c
+ * \brief Portable wrappers for finding out the current time, running
+ * timers, etc.
+ **/
+
+#include "orconfig.h"
+#include "lib/err/torerr.h"
+#include "lib/wallclock/tor_gettimeofday.h"
+#include "lib/cc/torint.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifndef HAVE_GETTIMEOFDAY
+#ifdef HAVE_FTIME
+#include <sys/timeb.h>
+#endif
+#endif
+
+/** Set *timeval to the current time of day. On error, log and terminate.
+ * (Same as gettimeofday(timeval,NULL), but never returns -1.)
+ */
+MOCK_IMPL(void,
+tor_gettimeofday, (struct timeval *timeval))
+{
+#ifdef _WIN32
+ /* Epoch bias copied from perl: number of units between windows epoch and
+ * Unix epoch. */
+#define EPOCH_BIAS UINT64_C(116444736000000000)
+#define UNITS_PER_SEC UINT64_C(10000000)
+#define USEC_PER_SEC UINT64_C(1000000)
+#define UNITS_PER_USEC UINT64_C(10)
+ union {
+ uint64_t ft_64;
+ FILETIME ft_ft;
+ } ft;
+ /* number of 100-nsec units since Jan 1, 1601 */
+ GetSystemTimeAsFileTime(&ft.ft_ft);
+ if (ft.ft_64 < EPOCH_BIAS) {
+ /* LCOV_EXCL_START */
+ raw_assert_unreached_msg("System time is before 1970; failing.");
+ /* LCOV_EXCL_STOP */
+ }
+ ft.ft_64 -= EPOCH_BIAS;
+ timeval->tv_sec = (unsigned) (ft.ft_64 / UNITS_PER_SEC);
+ timeval->tv_usec = (unsigned) ((ft.ft_64 / UNITS_PER_USEC) % USEC_PER_SEC);
+#elif defined(HAVE_GETTIMEOFDAY)
+ if (gettimeofday(timeval, NULL)) {
+ /* LCOV_EXCL_START */
+ /* If gettimeofday dies, we have either given a bad timezone (we didn't),
+ or segfaulted.*/
+ raw_assert_unreached_msg("gettimeofday failed");
+ /* LCOV_EXCL_STOP */
+ }
+#elif defined(HAVE_FTIME)
+ struct timeb tb;
+ ftime(&tb);
+ timeval->tv_sec = tb.time;
+ timeval->tv_usec = tb.millitm * 1000;
+#else
+#error "No way to get time."
+#endif /* defined(_WIN32) || ... */
+ return;
+}
diff --git a/src/lib/wallclock/tor_gettimeofday.h b/src/lib/wallclock/tor_gettimeofday.h
new file mode 100644
index 0000000000..728ad9565d
--- /dev/null
+++ b/src/lib/wallclock/tor_gettimeofday.h
@@ -0,0 +1,15 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_GETTIMEOFDAY_H
+#define TOR_GETTIMEOFDAY_H
+
+#include "lib/testsupport/testsupport.h"
+
+struct timeval;
+
+MOCK_DECL(void, tor_gettimeofday, (struct timeval *timeval));
+
+#endif
diff --git a/src/or/Makefile.nmake b/src/or/Makefile.nmake
deleted file mode 100644
index 429ae67858..0000000000
--- a/src/or/Makefile.nmake
+++ /dev/null
@@ -1,79 +0,0 @@
-all: tor.exe
-
-CFLAGS = /O2 /MT /I ..\win32 /I ..\..\..\build-alpha\include /I ..\common \
- /I ..\ext
-
-LIBS = ..\..\..\build-alpha\lib\libevent.lib \
- ..\..\..\build-alpha\lib\libcrypto.lib \
- ..\..\..\build-alpha\lib\libssl.lib \
- ..\..\..\build-alpha\lib\libz.lib \
- ws2_32.lib advapi32.lib shell32.lib \
- crypt32.lib gdi32.lib user32.lib
-
-LIBTOR_OBJECTS = \
- addressmap.obj \
- buffers.obj \
- channel.obj \
- channelpadding.obj \
- channeltls.obj \
- circpathbias.obj \
- circuitbuild.obj \
- circuitlist.obj \
- circuitmux.obj \
- circuitmux_ewma.obj \
- circuitstats.obj \
- circuituse.obj \
- command.obj \
- config.obj \
- config_codedigest.obj \
- confparse.obj \
- connection.obj \
- connection_edge.obj \
- connection_or.obj \
- control.obj \
- cpuworker.obj \
- directory.obj \
- dirserv.obj \
- dirvote.obj \
- dns.obj \
- dnsserv.obj \
- ext_orport.obj \
- fp_pair.obj \
- entrynodes.obj \
- geoip.obj \
- hibernate.obj \
- main.obj \
- microdesc.obj \
- networkstatus.obj \
- nodelist.obj \
- ntmain.obj \
- onion.obj \
- onion_fast.obj \
- onion_ntor.obj \
- onion_tap.obj \
- policies.obj \
- reasons.obj \
- relay.obj \
- rendclient.obj \
- rendcommon.obj \
- rendmid.obj \
- rendservice.obj \
- rephist.obj \
- replaycache.obj \
- router.obj \
- routerlist.obj \
- routerparse.obj \
- routerset.obj \
- scheduler.obj \
- statefile.obj \
- status.obj \
- transports.obj
-
-libtor.lib: $(LIBTOR_OBJECTS)
- lib $(LIBTOR_OBJECTS) /out:$@
-
-tor.exe: libtor.lib tor_main.obj
- $(CC) $(CFLAGS) $(LIBS) libtor.lib ..\common\*.lib ..\ext\*.lib tor_main.obj /Fe$@
-
-clean:
- del $(LIBTOR_OBJECTS) tor_main.obj *.lib tor.exe
diff --git a/src/or/circuitlist.h b/src/or/circuitlist.h
deleted file mode 100644
index 246f0c8815..0000000000
--- a/src/or/circuitlist.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* Copyright (c) 2001 Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file circuitlist.h
- * \brief Header file for circuitlist.c.
- **/
-
-#ifndef TOR_CIRCUITLIST_H
-#define TOR_CIRCUITLIST_H
-
-#include "testsupport.h"
-#include "hs_ident.h"
-
-MOCK_DECL(smartlist_t *, circuit_get_global_list, (void));
-smartlist_t *circuit_get_global_origin_circuit_list(void);
-int circuit_any_opened_circuits(void);
-int circuit_any_opened_circuits_cached(void);
-void circuit_cache_opened_circuit_state(int circuits_are_opened);
-
-const char *circuit_state_to_string(int state);
-const char *circuit_purpose_to_controller_string(uint8_t purpose);
-const char *circuit_purpose_to_controller_hs_state_string(uint8_t purpose);
-const char *circuit_purpose_to_string(uint8_t purpose);
-void circuit_dump_by_conn(connection_t *conn, int severity);
-void circuit_set_p_circid_chan(or_circuit_t *circ, circid_t id,
- channel_t *chan);
-void circuit_set_n_circid_chan(circuit_t *circ, circid_t id,
- channel_t *chan);
-void channel_mark_circid_unusable(channel_t *chan, circid_t id);
-void channel_mark_circid_usable(channel_t *chan, circid_t id);
-time_t circuit_id_when_marked_unusable_on_channel(circid_t circ_id,
- channel_t *chan);
-void circuit_set_state(circuit_t *circ, uint8_t state);
-void circuit_close_all_marked(void);
-int32_t circuit_initial_package_window(void);
-origin_circuit_t *origin_circuit_new(void);
-or_circuit_t *or_circuit_new(circid_t p_circ_id, channel_t *p_chan);
-circuit_t *circuit_get_by_circid_channel(circid_t circ_id,
- channel_t *chan);
-circuit_t *
-circuit_get_by_circid_channel_even_if_marked(circid_t circ_id,
- channel_t *chan);
-int circuit_id_in_use_on_channel(circid_t circ_id, channel_t *chan);
-circuit_t *circuit_get_by_edge_conn(edge_connection_t *conn);
-void circuit_unlink_all_from_channel(channel_t *chan, int reason);
-origin_circuit_t *circuit_get_by_global_id(uint32_t id);
-origin_circuit_t *circuit_get_ready_rend_circ_by_rend_data(
- const rend_data_t *rend_data);
-origin_circuit_t *circuit_get_next_by_pk_and_purpose(origin_circuit_t *start,
- const uint8_t *digest, uint8_t purpose);
-origin_circuit_t *circuit_get_next_service_intro_circ(origin_circuit_t *start);
-origin_circuit_t *circuit_get_next_service_rp_circ(origin_circuit_t *start);
-origin_circuit_t *circuit_get_next_service_hsdir_circ(origin_circuit_t *start);
-origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose,
- extend_info_t *info, int flags);
-void circuit_mark_all_unused_circs(void);
-void circuit_mark_all_dirty_circs_as_unusable(void);
-MOCK_DECL(void, circuit_mark_for_close_, (circuit_t *circ, int reason,
- int line, const char *file));
-int circuit_get_cpath_len(origin_circuit_t *circ);
-int circuit_get_cpath_opened_len(const origin_circuit_t *);
-void circuit_clear_cpath(origin_circuit_t *circ);
-crypt_path_t *circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum);
-void circuit_get_all_pending_on_channel(smartlist_t *out,
- channel_t *chan);
-int circuit_count_pending_on_channel(channel_t *chan);
-
-#define circuit_mark_for_close(c, reason) \
- circuit_mark_for_close_((c), (reason), __LINE__, SHORT_FILE__)
-
-void assert_cpath_layer_ok(const crypt_path_t *cp);
-MOCK_DECL(void, assert_circuit_ok,(const circuit_t *c));
-void circuit_free_all(void);
-void circuits_handle_oom(size_t current_allocation);
-
-void circuit_clear_testing_cell_stats(circuit_t *circ);
-
-void channel_note_destroy_pending(channel_t *chan, circid_t id);
-MOCK_DECL(void, channel_note_destroy_not_pending,
- (channel_t *chan, circid_t id));
-
-smartlist_t *circuit_find_circuits_to_upgrade_from_guard_wait(void);
-
-#ifdef CIRCUITLIST_PRIVATE
-STATIC void circuit_free_(circuit_t *circ);
-#define circuit_free(circ) FREE_AND_NULL(circuit_t, circuit_free_, (circ))
-STATIC size_t n_cells_in_circ_queues(const circuit_t *c);
-STATIC uint32_t circuit_max_queued_data_age(const circuit_t *c, uint32_t now);
-STATIC uint32_t circuit_max_queued_cell_age(const circuit_t *c, uint32_t now);
-STATIC uint32_t circuit_max_queued_item_age(const circuit_t *c, uint32_t now);
-#endif /* defined(CIRCUITLIST_PRIVATE) */
-
-#endif /* !defined(TOR_CIRCUITLIST_H) */
-
diff --git a/src/or/hs_ntor.h b/src/or/hs_ntor.h
deleted file mode 100644
index 77e544a130..0000000000
--- a/src/or/hs_ntor.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_HS_NTOR_H
-#define TOR_HS_NTOR_H
-
-#include "or.h"
-
-/* Output length of KDF for key expansion */
-#define HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN \
- (DIGEST256_LEN*2 + CIPHER256_KEY_LEN*2)
-
-/* Key material needed to encode/decode INTRODUCE1 cells */
-typedef struct {
- /* Key used for encryption of encrypted INTRODUCE1 blob */
- uint8_t enc_key[CIPHER256_KEY_LEN];
- /* MAC key used to protect encrypted INTRODUCE1 blob */
- uint8_t mac_key[DIGEST256_LEN];
-} hs_ntor_intro_cell_keys_t;
-
-/* Key material needed to encode/decode RENDEZVOUS1 cells */
-typedef struct {
- /* This is the MAC of the HANDSHAKE_INFO field */
- uint8_t rend_cell_auth_mac[DIGEST256_LEN];
- /* This is the key seed used to derive further rendezvous crypto keys as
- * detailed in section 4.2.1 of rend-spec-ng.txt. */
- uint8_t ntor_key_seed[DIGEST256_LEN];
-} hs_ntor_rend_cell_keys_t;
-
-int hs_ntor_client_get_introduce1_keys(
- const ed25519_public_key_t *intro_auth_pubkey,
- const curve25519_public_key_t *intro_enc_pubkey,
- const curve25519_keypair_t *client_ephemeral_enc_keypair,
- const uint8_t *subcredential,
- hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out);
-
-int hs_ntor_client_get_rendezvous1_keys(
- const ed25519_public_key_t *intro_auth_pubkey,
- const curve25519_keypair_t *client_ephemeral_enc_keypair,
- const curve25519_public_key_t *intro_enc_pubkey,
- const curve25519_public_key_t *service_ephemeral_rend_pubkey,
- hs_ntor_rend_cell_keys_t *hs_ntor_rend_cell_keys_out);
-
-int hs_ntor_service_get_introduce1_keys(
- const ed25519_public_key_t *intro_auth_pubkey,
- const curve25519_keypair_t *intro_enc_keypair,
- const curve25519_public_key_t *client_ephemeral_enc_pubkey,
- const uint8_t *subcredential,
- hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out);
-
-int hs_ntor_service_get_rendezvous1_keys(
- const ed25519_public_key_t *intro_auth_pubkey,
- const curve25519_keypair_t *intro_enc_keypair,
- const curve25519_keypair_t *service_ephemeral_rend_keypair,
- const curve25519_public_key_t *client_ephemeral_enc_pubkey,
- hs_ntor_rend_cell_keys_t *hs_ntor_rend_cell_keys_out);
-
-int hs_ntor_circuit_key_expansion(const uint8_t *ntor_key_seed,
- size_t seed_len,
- uint8_t *keys_out, size_t keys_out_len);
-
-int hs_ntor_client_rendezvous2_mac_is_good(
- const hs_ntor_rend_cell_keys_t *hs_ntor_rend_cell_keys,
- const uint8_t *rcvd_mac);
-
-#endif /* !defined(TOR_HS_NTOR_H) */
-
diff --git a/src/or/include.am b/src/or/include.am
deleted file mode 100644
index 59d593a5e9..0000000000
--- a/src/or/include.am
+++ /dev/null
@@ -1,320 +0,0 @@
-bin_PROGRAMS+= src/or/tor
-noinst_LIBRARIES += \
- src/or/libtor.a
-if UNITTESTS_ENABLED
-noinst_LIBRARIES += \
- src/or/libtor-testing.a
-endif
-if COVERAGE_ENABLED
-noinst_PROGRAMS+= src/or/tor-cov
-endif
-
-if BUILD_NT_SERVICES
-tor_platform_source=src/or/ntmain.c
-else
-tor_platform_source=
-endif
-
-EXTRA_DIST+= src/or/ntmain.c src/or/Makefile.nmake
-
-LIBTOR_A_SOURCES = \
- src/or/addressmap.c \
- src/or/bridges.c \
- src/or/channel.c \
- src/or/channelpadding.c \
- src/or/channeltls.c \
- src/or/circpathbias.c \
- src/or/circuitbuild.c \
- src/or/circuitlist.c \
- src/or/circuitmux.c \
- src/or/circuitmux_ewma.c \
- src/or/circuitstats.c \
- src/or/circuituse.c \
- src/or/command.c \
- src/or/config.c \
- src/or/confparse.c \
- src/or/connection.c \
- src/or/connection_edge.c \
- src/or/connection_or.c \
- src/or/conscache.c \
- src/or/consdiff.c \
- src/or/consdiffmgr.c \
- src/or/control.c \
- src/or/cpuworker.c \
- src/or/directory.c \
- src/or/dirserv.c \
- src/or/dns.c \
- src/or/dnsserv.c \
- src/or/dos.c \
- src/or/fp_pair.c \
- src/or/geoip.c \
- src/or/entrynodes.c \
- src/or/ext_orport.c \
- src/or/git_revision.c \
- src/or/hibernate.c \
- src/or/hs_cache.c \
- src/or/hs_cell.c \
- src/or/hs_circuit.c \
- src/or/hs_circuitmap.c \
- src/or/hs_client.c \
- src/or/hs_common.c \
- src/or/hs_config.c \
- src/or/hs_control.c \
- src/or/hs_descriptor.c \
- src/or/hs_ident.c \
- src/or/hs_intropoint.c \
- src/or/hs_ntor.c \
- src/or/hs_service.c \
- src/or/hs_stats.c \
- src/or/keypin.c \
- src/or/main.c \
- src/or/microdesc.c \
- src/or/networkstatus.c \
- src/or/nodelist.c \
- src/or/onion.c \
- src/or/onion_fast.c \
- src/or/onion_tap.c \
- src/or/transports.c \
- src/or/parsecommon.c \
- src/or/periodic.c \
- src/or/protover.c \
- src/or/protover_rust.c \
- src/or/proto_cell.c \
- src/or/proto_control0.c \
- src/or/proto_ext_or.c \
- src/or/proto_http.c \
- src/or/proto_socks.c \
- src/or/policies.c \
- src/or/reasons.c \
- src/or/relay.c \
- src/or/relay_crypto.c \
- src/or/rendcache.c \
- src/or/rendclient.c \
- src/or/rendcommon.c \
- src/or/rendmid.c \
- src/or/rendservice.c \
- src/or/rephist.c \
- src/or/replaycache.c \
- src/or/router.c \
- src/or/routerkeys.c \
- src/or/routerlist.c \
- src/or/routerparse.c \
- src/or/routerset.c \
- src/or/scheduler.c \
- src/or/scheduler_kist.c \
- src/or/scheduler_vanilla.c \
- src/or/shared_random_client.c \
- src/or/statefile.c \
- src/or/status.c \
- src/or/torcert.c \
- src/or/tor_api.c \
- src/or/voting_schedule.c \
- src/or/onion_ntor.c \
- $(tor_platform_source)
-
-#
-# Modules are conditionnally compiled in tor starting here. We add the C files
-# only if the modules has been enabled at configure time. We always add the
-# source files of every module to libtor-testing.a so we can build the unit
-# tests for everything. See the UNITTESTS_ENABLED branch below.
-#
-LIBTOR_TESTING_A_SOURCES = $(LIBTOR_A_SOURCES)
-
-# The Directory Authority module.
-MODULE_DIRAUTH_SOURCES = \
- src/or/dirauth/dircollate.c \
- src/or/dirauth/dirvote.c \
- src/or/dirauth/shared_random.c \
- src/or/dirauth/shared_random_state.c
-if BUILD_MODULE_DIRAUTH
-LIBTOR_A_SOURCES += $(MODULE_DIRAUTH_SOURCES)
-endif
-
-src_or_libtor_a_SOURCES = $(LIBTOR_A_SOURCES)
-if UNITTESTS_ENABLED
-
-# Add the sources of the modules that are needed for tests to work here.
-LIBTOR_TESTING_A_SOURCES += $(MODULE_DIRAUTH_SOURCES)
-
-src_or_libtor_testing_a_SOURCES = $(LIBTOR_TESTING_A_SOURCES)
-else
-src_or_libtor_testing_a_SOURCES =
-endif
-
-src_or_tor_SOURCES = src/or/tor_main.c
-AM_CPPFLAGS += -I$(srcdir)/src/or -Isrc/or
-
-src/or/tor_main.$(OBJEXT) \
- src/or/src_or_tor_cov-tor_main.$(OBJEXT): micro-revision.i
-
-AM_CPPFLAGS += -DSHARE_DATADIR="\"$(datadir)\"" \
- -DLOCALSTATEDIR="\"$(localstatedir)\"" \
- -DBINDIR="\"$(bindir)\""
-
-src_or_libtor_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
-src_or_libtor_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
-
-# -L flags need to go in LDFLAGS. -l flags need to go in LDADD.
-# 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_or_tor_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@
-src_or_tor_LDADD = src/or/libtor.a src/common/libor.a src/common/libor-ctime.a \
- src/common/libor-crypto.a $(LIBKECCAK_TINY) $(LIBDONNA) \
- src/common/libor-event.a src/trunnel/libor-trunnel.a \
- src/trace/libor-trace.a \
- $(rust_ldadd) \
- @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
- @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
- @CURVE25519_LIBS@ @TOR_SYSTEMD_LIBS@ \
- @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
-
-if COVERAGE_ENABLED
-src_or_tor_cov_SOURCES = src/or/tor_main.c
-src_or_tor_cov_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
-src_or_tor_cov_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
-src_or_tor_cov_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@
-src_or_tor_cov_LDADD = src/or/libtor-testing.a src/common/libor-testing.a \
- src/common/libor-ctime-testing.a \
- src/common/libor-crypto-testing.a $(LIBKECCAK_TINY) $(LIBDONNA) \
- src/common/libor-event-testing.a src/trunnel/libor-trunnel-testing.a \
- @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
- @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ @TOR_SYSTEMD_LIBS@ \
- @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
-endif
-
-ORHEADERS = \
- src/or/addressmap.h \
- src/or/auth_dirs.inc \
- src/or/bridges.h \
- src/or/channel.h \
- src/or/channelpadding.h \
- src/or/channeltls.h \
- src/or/circpathbias.h \
- src/or/circuitbuild.h \
- src/or/circuitlist.h \
- src/or/circuitmux.h \
- src/or/circuitmux_ewma.h \
- src/or/circuitstats.h \
- src/or/circuituse.h \
- src/or/command.h \
- src/or/config.h \
- src/or/confparse.h \
- src/or/connection.h \
- src/or/connection_edge.h \
- src/or/connection_or.h \
- src/or/conscache.h \
- src/or/consdiff.h \
- src/or/consdiffmgr.h \
- src/or/control.h \
- src/or/cpuworker.h \
- src/or/directory.h \
- src/or/dirserv.h \
- src/or/dns.h \
- src/or/dns_structs.h \
- src/or/dnsserv.h \
- src/or/dos.h \
- src/or/ext_orport.h \
- src/or/fallback_dirs.inc \
- src/or/fp_pair.h \
- src/or/geoip.h \
- src/or/entrynodes.h \
- src/or/git_revision.h \
- src/or/hibernate.h \
- src/or/hs_cache.h \
- src/or/hs_cell.h \
- src/or/hs_circuit.h \
- src/or/hs_circuitmap.h \
- src/or/hs_client.h \
- src/or/hs_common.h \
- src/or/hs_config.h \
- src/or/hs_control.h \
- src/or/hs_descriptor.h \
- src/or/hs_ident.h \
- src/or/hs_intropoint.h \
- src/or/hs_ntor.h \
- src/or/hs_stats.h \
- src/or/hs_service.h \
- src/or/keypin.h \
- src/or/main.h \
- src/or/microdesc.h \
- src/or/networkstatus.h \
- src/or/nodelist.h \
- src/or/ntmain.h \
- src/or/onion.h \
- src/or/onion_fast.h \
- src/or/onion_ntor.h \
- src/or/onion_tap.h \
- src/or/or.h \
- src/or/transports.h \
- src/or/parsecommon.h \
- src/or/periodic.h \
- src/or/policies.h \
- src/or/protover.h \
- src/or/proto_cell.h \
- src/or/proto_control0.h \
- src/or/proto_ext_or.h \
- src/or/proto_http.h \
- src/or/proto_socks.h \
- src/or/reasons.h \
- src/or/relay.h \
- src/or/relay_crypto.h \
- src/or/rendcache.h \
- src/or/rendclient.h \
- src/or/rendcommon.h \
- src/or/rendmid.h \
- src/or/rendservice.h \
- src/or/rephist.h \
- src/or/replaycache.h \
- src/or/router.h \
- src/or/routerkeys.h \
- src/or/routerlist.h \
- src/or/routerkeys.h \
- src/or/routerset.h \
- src/or/routerparse.h \
- src/or/scheduler.h \
- src/or/shared_random_client.h \
- src/or/statefile.h \
- src/or/status.h \
- src/or/torcert.h \
- src/or/tor_api_internal.h \
- src/or/voting_schedule.h
-
-# We add the headers of the modules even though they are disabled so we can
-# properly compiled the entry points stub.
-
-# The Directory Authority module headers.
-ORHEADERS += \
- src/or/dirauth/dircollate.h \
- src/or/dirauth/dirvote.h \
- src/or/dirauth/mode.h \
- src/or/dirauth/shared_random.h \
- src/or/dirauth/shared_random_state.h
-
-# This may someday want to be an installed file?
-noinst_HEADERS += src/or/tor_api.h
-
-noinst_HEADERS += $(ORHEADERS) micro-revision.i
-
-micro-revision.i: FORCE
- $(AM_V_at)rm -f micro-revision.tmp; \
- if test -r "$(top_srcdir)/.git" && \
- test -x "`which git 2>&1;true`"; then \
- HASH="`cd "$(top_srcdir)" && git rev-parse --short=16 HEAD`"; \
- echo \"$$HASH\" > micro-revision.tmp; \
- fi; \
- if test ! -f micro-revision.tmp; then \
- if test ! -f micro-revision.i; then \
- echo '""' > micro-revision.i; \
- fi; \
- elif test ! -f micro-revision.i || \
- test x"`cat micro-revision.tmp`" != x"`cat micro-revision.i`"; then \
- mv micro-revision.tmp micro-revision.i; \
- fi; \
- rm -f micro-revision.tmp; \
- true
-
-CLEANFILES+= micro-revision.i src/or/micro-revision.i micro-revision.tmp
-
-FORCE:
diff --git a/src/or/or.h b/src/or/or.h
deleted file mode 100644
index db8f9544fe..0000000000
--- a/src/or/or.h
+++ /dev/null
@@ -1,5534 +0,0 @@
-/* Copyright (c) 2001 Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file or.h
- * \brief Master header file for Tor-specific functionality.
- **/
-
-#ifndef TOR_OR_H
-#define TOR_OR_H
-
-#include "orconfig.h"
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h> /* FreeBSD needs this to know what version it is */
-#endif
-#include "torint.h"
-#ifdef HAVE_SYS_FCNTL_H
-#include <sys/fcntl.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_UN_H
-#include <sys/un.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_ASSERT_H
-#include <assert.h>
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-
-#ifdef _WIN32
-#include <winsock2.h>
-#include <io.h>
-#include <process.h>
-#include <direct.h>
-#include <windows.h>
-#endif /* defined(_WIN32) */
-
-#include "crypto.h"
-#include "crypto_format.h"
-#include "tortls.h"
-#include "torlog.h"
-#include "container.h"
-#include "compress.h"
-#include "address.h"
-#include "compat_libevent.h"
-#include "ht.h"
-#include "confline.h"
-#include "replaycache.h"
-#include "crypto_curve25519.h"
-#include "crypto_ed25519.h"
-#include "tor_queue.h"
-#include "token_bucket.h"
-#include "util_format.h"
-#include "hs_circuitmap.h"
-
-/* These signals are defined to help handle_control_signal work.
- */
-#ifndef SIGHUP
-#define SIGHUP 1
-#endif
-#ifndef SIGINT
-#define SIGINT 2
-#endif
-#ifndef SIGUSR1
-#define SIGUSR1 10
-#endif
-#ifndef SIGUSR2
-#define SIGUSR2 12
-#endif
-#ifndef SIGTERM
-#define SIGTERM 15
-#endif
-/* Controller signals start at a high number so we don't
- * conflict with system-defined signals. */
-#define SIGNEWNYM 129
-#define SIGCLEARDNSCACHE 130
-#define SIGHEARTBEAT 131
-
-#if (SIZEOF_CELL_T != 0)
-/* On Irix, stdlib.h defines a cell_t type, so we need to make sure
- * that our stuff always calls cell_t something different. */
-#define cell_t tor_cell_t
-#endif
-
-#ifdef ENABLE_TOR2WEB_MODE
-#define NON_ANONYMOUS_MODE_ENABLED 1
-#endif
-
-/** Helper macro: Given a pointer to to.base_, of type from*, return &to. */
-#define DOWNCAST(to, ptr) ((to*)SUBTYPE_P(ptr, to, base_))
-
-/** Length of longest allowable configured nickname. */
-#define MAX_NICKNAME_LEN 19
-/** Length of a router identity encoded as a hexadecimal digest, plus
- * possible dollar sign. */
-#define MAX_HEX_NICKNAME_LEN (HEX_DIGEST_LEN+1)
-/** Maximum length of verbose router identifier: dollar sign, hex ID digest,
- * equal sign or tilde, nickname. */
-#define MAX_VERBOSE_NICKNAME_LEN (1+HEX_DIGEST_LEN+1+MAX_NICKNAME_LEN)
-
-/** Maximum size, in bytes, for resized buffers. */
-#define MAX_BUF_SIZE ((1<<24)-1) /* 16MB-1 */
-/** Maximum size, in bytes, for any directory object that we've downloaded. */
-#define MAX_DIR_DL_SIZE MAX_BUF_SIZE
-
-/** For HTTP parsing: Maximum number of bytes we'll accept in the headers
- * of an HTTP request or response. */
-#define MAX_HEADERS_SIZE 50000
-/** Maximum size, in bytes, for any directory object that we're accepting
- * as an upload. */
-#define MAX_DIR_UL_SIZE MAX_BUF_SIZE
-
-/** Maximum size, in bytes, of a single router descriptor uploaded to us
- * as a directory authority. Caches and clients fetch whatever descriptors
- * the authorities tell them to fetch, and don't care about size. */
-#define MAX_DESCRIPTOR_UPLOAD_SIZE 20000
-
-/** Maximum size of a single extrainfo document, as above. */
-#define MAX_EXTRAINFO_UPLOAD_SIZE 50000
-
-/** Minimum lifetime for an onion key in days. */
-#define MIN_ONION_KEY_LIFETIME_DAYS (1)
-
-/** Maximum lifetime for an onion key in days. */
-#define MAX_ONION_KEY_LIFETIME_DAYS (90)
-
-/** Default lifetime for an onion key in days. */
-#define DEFAULT_ONION_KEY_LIFETIME_DAYS (28)
-
-/** Minimum grace period for acceptance of an onion key in days.
- * The maximum value is defined in proposal #274 as being the current network
- * consensus parameter for "onion-key-rotation-days". */
-#define MIN_ONION_KEY_GRACE_PERIOD_DAYS (1)
-
-/** Default grace period for acceptance of an onion key in days. */
-#define DEFAULT_ONION_KEY_GRACE_PERIOD_DAYS (7)
-
-/** How often we should check the network consensus if it is time to rotate or
- * expire onion keys. */
-#define ONION_KEY_CONSENSUS_CHECK_INTERVAL (60*60)
-
-/** How often do we rotate TLS contexts? */
-#define MAX_SSL_KEY_LIFETIME_INTERNAL (2*60*60)
-
-/** How old do we allow a router to get before removing it
- * from the router list? In seconds. */
-#define ROUTER_MAX_AGE (60*60*48)
-/** How old can a router get before we (as a server) will no longer
- * consider it live? In seconds. */
-#define ROUTER_MAX_AGE_TO_PUBLISH (60*60*24)
-/** How old do we let a saved descriptor get before force-removing it? */
-#define OLD_ROUTER_DESC_MAX_AGE (60*60*24*5)
-
-/** Possible rules for generating circuit IDs on an OR connection. */
-typedef enum {
- CIRC_ID_TYPE_LOWER=0, /**< Pick from 0..1<<15-1. */
- CIRC_ID_TYPE_HIGHER=1, /**< Pick from 1<<15..1<<16-1. */
- /** The other side of a connection is an OP: never create circuits to it,
- * and let it use any circuit ID it wants. */
- CIRC_ID_TYPE_NEITHER=2
-} circ_id_type_t;
-#define circ_id_type_bitfield_t ENUM_BF(circ_id_type_t)
-
-#define CONN_TYPE_MIN_ 3
-/** Type for sockets listening for OR connections. */
-#define CONN_TYPE_OR_LISTENER 3
-/** A bidirectional TLS connection transmitting a sequence of cells.
- * May be from an OR to an OR, or from an OP to an OR. */
-#define CONN_TYPE_OR 4
-/** A TCP connection from an onion router to a stream's destination. */
-#define CONN_TYPE_EXIT 5
-/** Type for sockets listening for SOCKS connections. */
-#define CONN_TYPE_AP_LISTENER 6
-/** A SOCKS proxy connection from the user application to the onion
- * proxy. */
-#define CONN_TYPE_AP 7
-/** Type for sockets listening for HTTP connections to the directory server. */
-#define CONN_TYPE_DIR_LISTENER 8
-/** Type for HTTP connections to the directory server. */
-#define CONN_TYPE_DIR 9
-/* Type 10 is unused. */
-/** Type for listening for connections from user interface process. */
-#define CONN_TYPE_CONTROL_LISTENER 11
-/** Type for connections from user interface process. */
-#define CONN_TYPE_CONTROL 12
-/** Type for sockets listening for transparent connections redirected by pf or
- * netfilter. */
-#define CONN_TYPE_AP_TRANS_LISTENER 13
-/** Type for sockets listening for transparent connections redirected by
- * natd. */
-#define CONN_TYPE_AP_NATD_LISTENER 14
-/** Type for sockets listening for DNS requests. */
-#define CONN_TYPE_AP_DNS_LISTENER 15
-
-/** Type for connections from the Extended ORPort. */
-#define CONN_TYPE_EXT_OR 16
-/** Type for sockets listening for Extended ORPort connections. */
-#define CONN_TYPE_EXT_OR_LISTENER 17
-/** Type for sockets listening for HTTP CONNECT tunnel connections. */
-#define CONN_TYPE_AP_HTTP_CONNECT_LISTENER 18
-
-#define CONN_TYPE_MAX_ 19
-/* !!!! If _CONN_TYPE_MAX is ever over 31, we must grow the type field in
- * connection_t. */
-
-/* Proxy client types */
-#define PROXY_NONE 0
-#define PROXY_CONNECT 1
-#define PROXY_SOCKS4 2
-#define PROXY_SOCKS5 3
-/* !!!! If there is ever a PROXY_* type over 3, we must grow the proxy_type
- * field in or_connection_t */
-
-/* Pluggable transport proxy type. Don't use this in or_connection_t,
- * instead use the actual underlying proxy type (see above). */
-#define PROXY_PLUGGABLE 4
-
-/* Proxy client handshake states */
-/* We use a proxy but we haven't even connected to it yet. */
-#define PROXY_INFANT 1
-/* We use an HTTP proxy and we've sent the CONNECT command. */
-#define PROXY_HTTPS_WANT_CONNECT_OK 2
-/* We use a SOCKS4 proxy and we've sent the CONNECT command. */
-#define PROXY_SOCKS4_WANT_CONNECT_OK 3
-/* We use a SOCKS5 proxy and we try to negotiate without
- any authentication . */
-#define PROXY_SOCKS5_WANT_AUTH_METHOD_NONE 4
-/* We use a SOCKS5 proxy and we try to negotiate with
- Username/Password authentication . */
-#define PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929 5
-/* We use a SOCKS5 proxy and we just sent our credentials. */
-#define PROXY_SOCKS5_WANT_AUTH_RFC1929_OK 6
-/* We use a SOCKS5 proxy and we just sent our CONNECT command. */
-#define PROXY_SOCKS5_WANT_CONNECT_OK 7
-/* We use a proxy and we CONNECTed successfully!. */
-#define PROXY_CONNECTED 8
-
-/** True iff <b>x</b> is an edge connection. */
-#define CONN_IS_EDGE(x) \
- ((x)->type == CONN_TYPE_EXIT || (x)->type == CONN_TYPE_AP)
-
-/** State for any listener connection. */
-#define LISTENER_STATE_READY 0
-
-#define OR_CONN_STATE_MIN_ 1
-/** State for a connection to an OR: waiting for connect() to finish. */
-#define OR_CONN_STATE_CONNECTING 1
-/** State for a connection to an OR: waiting for proxy handshake to complete */
-#define OR_CONN_STATE_PROXY_HANDSHAKING 2
-/** State for an OR connection client: SSL is handshaking, not done
- * yet. */
-#define OR_CONN_STATE_TLS_HANDSHAKING 3
-/** State for a connection to an OR: We're doing a second SSL handshake for
- * renegotiation purposes. (V2 handshake only.) */
-#define OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING 4
-/** State for a connection at an OR: We're waiting for the client to
- * renegotiate (to indicate a v2 handshake) or send a versions cell (to
- * indicate a v3 handshake) */
-#define OR_CONN_STATE_TLS_SERVER_RENEGOTIATING 5
-/** State for an OR connection: We're done with our SSL handshake, we've done
- * renegotiation, but we haven't yet negotiated link protocol versions and
- * sent a netinfo cell. */
-#define OR_CONN_STATE_OR_HANDSHAKING_V2 6
-/** State for an OR connection: We're done with our SSL handshake, but we
- * haven't yet negotiated link protocol versions, done a V3 handshake, and
- * sent a netinfo cell. */
-#define OR_CONN_STATE_OR_HANDSHAKING_V3 7
-/** State for an OR connection: Ready to send/receive cells. */
-#define OR_CONN_STATE_OPEN 8
-#define OR_CONN_STATE_MAX_ 8
-
-/** States of the Extended ORPort protocol. Be careful before changing
- * the numbers: they matter. */
-#define EXT_OR_CONN_STATE_MIN_ 1
-/** Extended ORPort authentication is waiting for the authentication
- * type selected by the client. */
-#define EXT_OR_CONN_STATE_AUTH_WAIT_AUTH_TYPE 1
-/** Extended ORPort authentication is waiting for the client nonce. */
-#define EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE 2
-/** Extended ORPort authentication is waiting for the client hash. */
-#define EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_HASH 3
-#define EXT_OR_CONN_STATE_AUTH_MAX 3
-/** Authentication finished and the Extended ORPort is now accepting
- * traffic. */
-#define EXT_OR_CONN_STATE_OPEN 4
-/** Extended ORPort is flushing its last messages and preparing to
- * start accepting OR connections. */
-#define EXT_OR_CONN_STATE_FLUSHING 5
-#define EXT_OR_CONN_STATE_MAX_ 5
-
-#define EXIT_CONN_STATE_MIN_ 1
-/** State for an exit connection: waiting for response from DNS farm. */
-#define EXIT_CONN_STATE_RESOLVING 1
-/** State for an exit connection: waiting for connect() to finish. */
-#define EXIT_CONN_STATE_CONNECTING 2
-/** State for an exit connection: open and ready to transmit data. */
-#define EXIT_CONN_STATE_OPEN 3
-/** State for an exit connection: waiting to be removed. */
-#define EXIT_CONN_STATE_RESOLVEFAILED 4
-#define EXIT_CONN_STATE_MAX_ 4
-
-/* The AP state values must be disjoint from the EXIT state values. */
-#define AP_CONN_STATE_MIN_ 5
-/** State for a SOCKS connection: waiting for SOCKS request. */
-#define AP_CONN_STATE_SOCKS_WAIT 5
-/** State for a SOCKS connection: got a y.onion URL; waiting to receive
- * rendezvous descriptor. */
-#define AP_CONN_STATE_RENDDESC_WAIT 6
-/** The controller will attach this connection to a circuit; it isn't our
- * job to do so. */
-#define AP_CONN_STATE_CONTROLLER_WAIT 7
-/** State for a SOCKS connection: waiting for a completed circuit. */
-#define AP_CONN_STATE_CIRCUIT_WAIT 8
-/** State for a SOCKS connection: sent BEGIN, waiting for CONNECTED. */
-#define AP_CONN_STATE_CONNECT_WAIT 9
-/** State for a SOCKS connection: sent RESOLVE, waiting for RESOLVED. */
-#define AP_CONN_STATE_RESOLVE_WAIT 10
-/** State for a SOCKS connection: ready to send and receive. */
-#define AP_CONN_STATE_OPEN 11
-/** State for a transparent natd connection: waiting for original
- * destination. */
-#define AP_CONN_STATE_NATD_WAIT 12
-/** State for an HTTP tunnel: waiting for an HTTP CONNECT command. */
-#define AP_CONN_STATE_HTTP_CONNECT_WAIT 13
-#define AP_CONN_STATE_MAX_ 13
-
-/** True iff the AP_CONN_STATE_* value <b>s</b> means that the corresponding
- * edge connection is not attached to any circuit. */
-#define AP_CONN_STATE_IS_UNATTACHED(s) \
- ((s) <= AP_CONN_STATE_CIRCUIT_WAIT || (s) == AP_CONN_STATE_NATD_WAIT)
-
-#define DIR_CONN_STATE_MIN_ 1
-/** State for connection to directory server: waiting for connect(). */
-#define DIR_CONN_STATE_CONNECTING 1
-/** State for connection to directory server: sending HTTP request. */
-#define DIR_CONN_STATE_CLIENT_SENDING 2
-/** State for connection to directory server: reading HTTP response. */
-#define DIR_CONN_STATE_CLIENT_READING 3
-/** State for connection to directory server: happy and finished. */
-#define DIR_CONN_STATE_CLIENT_FINISHED 4
-/** State for connection at directory server: waiting for HTTP request. */
-#define DIR_CONN_STATE_SERVER_COMMAND_WAIT 5
-/** State for connection at directory server: sending HTTP response. */
-#define DIR_CONN_STATE_SERVER_WRITING 6
-#define DIR_CONN_STATE_MAX_ 6
-
-/** True iff the purpose of <b>conn</b> means that it's a server-side
- * directory connection. */
-#define DIR_CONN_IS_SERVER(conn) ((conn)->purpose == DIR_PURPOSE_SERVER)
-
-#define CONTROL_CONN_STATE_MIN_ 1
-/** State for a control connection: Authenticated and accepting v1 commands. */
-#define CONTROL_CONN_STATE_OPEN 1
-/** State for a control connection: Waiting for authentication; speaking
- * protocol v1. */
-#define CONTROL_CONN_STATE_NEEDAUTH 2
-#define CONTROL_CONN_STATE_MAX_ 2
-
-#define DIR_PURPOSE_MIN_ 4
-/** A connection to a directory server: set after a v2 rendezvous
- * descriptor is downloaded. */
-#define DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2 4
-/** A connection to a directory server: download one or more server
- * descriptors. */
-#define DIR_PURPOSE_FETCH_SERVERDESC 6
-/** A connection to a directory server: download one or more extra-info
- * documents. */
-#define DIR_PURPOSE_FETCH_EXTRAINFO 7
-/** A connection to a directory server: upload a server descriptor. */
-#define DIR_PURPOSE_UPLOAD_DIR 8
-/** A connection to a directory server: upload a v3 networkstatus vote. */
-#define DIR_PURPOSE_UPLOAD_VOTE 10
-/** A connection to a directory server: upload a v3 consensus signature */
-#define DIR_PURPOSE_UPLOAD_SIGNATURES 11
-/** A connection to a directory server: download one or more v3 networkstatus
- * votes. */
-#define DIR_PURPOSE_FETCH_STATUS_VOTE 12
-/** A connection to a directory server: download a v3 detached signatures
- * object for a consensus. */
-#define DIR_PURPOSE_FETCH_DETACHED_SIGNATURES 13
-/** A connection to a directory server: download a v3 networkstatus
- * consensus. */
-#define DIR_PURPOSE_FETCH_CONSENSUS 14
-/** A connection to a directory server: download one or more directory
- * authority certificates. */
-#define DIR_PURPOSE_FETCH_CERTIFICATE 15
-
-/** Purpose for connection at a directory server. */
-#define DIR_PURPOSE_SERVER 16
-/** A connection to a hidden service directory server: upload a v2 rendezvous
- * descriptor. */
-#define DIR_PURPOSE_UPLOAD_RENDDESC_V2 17
-/** A connection to a hidden service directory server: download a v2 rendezvous
- * descriptor. */
-#define DIR_PURPOSE_FETCH_RENDDESC_V2 18
-/** A connection to a directory server: download a microdescriptor. */
-#define DIR_PURPOSE_FETCH_MICRODESC 19
-/** A connection to a hidden service directory: upload a v3 descriptor. */
-#define DIR_PURPOSE_UPLOAD_HSDESC 20
-/** A connection to a hidden service directory: fetch a v3 descriptor. */
-#define DIR_PURPOSE_FETCH_HSDESC 21
-/** A connection to a directory server: set after a hidden service descriptor
- * is downloaded. */
-#define DIR_PURPOSE_HAS_FETCHED_HSDESC 22
-#define DIR_PURPOSE_MAX_ 22
-
-/** True iff <b>p</b> is a purpose corresponding to uploading
- * data to a directory server. */
-#define DIR_PURPOSE_IS_UPLOAD(p) \
- ((p)==DIR_PURPOSE_UPLOAD_DIR || \
- (p)==DIR_PURPOSE_UPLOAD_VOTE || \
- (p)==DIR_PURPOSE_UPLOAD_SIGNATURES || \
- (p)==DIR_PURPOSE_UPLOAD_RENDDESC_V2 || \
- (p)==DIR_PURPOSE_UPLOAD_HSDESC)
-
-#define EXIT_PURPOSE_MIN_ 1
-/** This exit stream wants to do an ordinary connect. */
-#define EXIT_PURPOSE_CONNECT 1
-/** This exit stream wants to do a resolve (either normal or reverse). */
-#define EXIT_PURPOSE_RESOLVE 2
-#define EXIT_PURPOSE_MAX_ 2
-
-/* !!!! If any connection purpose is ever over 31, we must grow the type
- * field in connection_t. */
-
-/** Circuit state: I'm the origin, still haven't done all my handshakes. */
-#define CIRCUIT_STATE_BUILDING 0
-/** Circuit state: Waiting to process the onionskin. */
-#define CIRCUIT_STATE_ONIONSKIN_PENDING 1
-/** Circuit state: I'd like to deliver a create, but my n_chan is still
- * connecting. */
-#define CIRCUIT_STATE_CHAN_WAIT 2
-/** Circuit state: the circuit is open but we don't want to actually use it
- * until we find out if a better guard will be available.
- */
-#define CIRCUIT_STATE_GUARD_WAIT 3
-/** Circuit state: onionskin(s) processed, ready to send/receive cells. */
-#define CIRCUIT_STATE_OPEN 4
-
-#define CIRCUIT_PURPOSE_MIN_ 1
-
-/* these circuits were initiated elsewhere */
-#define CIRCUIT_PURPOSE_OR_MIN_ 1
-/** OR-side circuit purpose: normal circuit, at OR. */
-#define CIRCUIT_PURPOSE_OR 1
-/** OR-side circuit purpose: At OR, from the service, waiting for intro from
- * clients. */
-#define CIRCUIT_PURPOSE_INTRO_POINT 2
-/** OR-side circuit purpose: At OR, from the client, waiting for the service.
- */
-#define CIRCUIT_PURPOSE_REND_POINT_WAITING 3
-/** OR-side circuit purpose: At OR, both circuits have this purpose. */
-#define CIRCUIT_PURPOSE_REND_ESTABLISHED 4
-#define CIRCUIT_PURPOSE_OR_MAX_ 4
-
-/* these circuits originate at this node */
-
-/* here's how circ client-side purposes work:
- * normal circuits are C_GENERAL.
- * circuits that are c_introducing are either on their way to
- * becoming open, or they are open and waiting for a
- * suitable rendcirc before they send the intro.
- * circuits that are c_introduce_ack_wait have sent the intro,
- * but haven't gotten a response yet.
- * circuits that are c_establish_rend are either on their way
- * to becoming open, or they are open and have sent the
- * establish_rendezvous cell but haven't received an ack.
- * circuits that are c_rend_ready are open and have received a
- * rend ack, but haven't heard from the service yet. if they have a
- * buildstate->pending_final_cpath then they're expecting a
- * cell from the service, else they're not.
- * circuits that are c_rend_ready_intro_acked are open, and
- * some intro circ has sent its intro and received an ack.
- * circuits that are c_rend_joined are open, have heard from
- * the service, and are talking to it.
- */
-/** Client-side circuit purpose: Normal circuit, with cpath. */
-#define CIRCUIT_PURPOSE_C_GENERAL 5
-#define CIRCUIT_PURPOSE_C_HS_MIN_ 6
-/** Client-side circuit purpose: at the client, connecting to intro point. */
-#define CIRCUIT_PURPOSE_C_INTRODUCING 6
-/** Client-side circuit purpose: at the client, sent INTRODUCE1 to intro point,
- * waiting for ACK/NAK. */
-#define CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT 7
-/** Client-side circuit purpose: at the client, introduced and acked, closing.
- */
-#define CIRCUIT_PURPOSE_C_INTRODUCE_ACKED 8
-/** Client-side circuit purpose: at the client, waiting for ack. */
-#define CIRCUIT_PURPOSE_C_ESTABLISH_REND 9
-/** Client-side circuit purpose: at the client, waiting for the service. */
-#define CIRCUIT_PURPOSE_C_REND_READY 10
-/** Client-side circuit purpose: at the client, waiting for the service,
- * INTRODUCE has been acknowledged. */
-#define CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED 11
-/** Client-side circuit purpose: at the client, rendezvous established. */
-#define CIRCUIT_PURPOSE_C_REND_JOINED 12
-/** This circuit is used for getting hsdirs */
-#define CIRCUIT_PURPOSE_C_HSDIR_GET 13
-#define CIRCUIT_PURPOSE_C_HS_MAX_ 13
-/** This circuit is used for build time measurement only */
-#define CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT 14
-#define CIRCUIT_PURPOSE_C_MAX_ 14
-
-#define CIRCUIT_PURPOSE_S_HS_MIN_ 15
-/** Hidden-service-side circuit purpose: at the service, waiting for
- * introductions. */
-#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO 15
-/** Hidden-service-side circuit purpose: at the service, successfully
- * established intro. */
-#define CIRCUIT_PURPOSE_S_INTRO 16
-/** Hidden-service-side circuit purpose: at the service, connecting to rend
- * point. */
-#define CIRCUIT_PURPOSE_S_CONNECT_REND 17
-/** Hidden-service-side circuit purpose: at the service, rendezvous
- * established. */
-#define CIRCUIT_PURPOSE_S_REND_JOINED 18
-/** This circuit is used for uploading hsdirs */
-#define CIRCUIT_PURPOSE_S_HSDIR_POST 19
-#define CIRCUIT_PURPOSE_S_HS_MAX_ 19
-
-/** A testing circuit; not meant to be used for actual traffic. */
-#define CIRCUIT_PURPOSE_TESTING 20
-/** A controller made this circuit and Tor should not use it. */
-#define CIRCUIT_PURPOSE_CONTROLLER 21
-/** This circuit is used for path bias probing only */
-#define CIRCUIT_PURPOSE_PATH_BIAS_TESTING 22
-
-/** This circuit is used for vanguards/restricted paths.
- *
- * This type of circuit is *only* created preemptively and never
- * on-demand. When an HS operation needs to take place (e.g. connect to an
- * intro point), these circuits are then cannibalized and repurposed to the
- * actual needed HS purpose. */
-#define CIRCUIT_PURPOSE_HS_VANGUARDS 23
-
-#define CIRCUIT_PURPOSE_MAX_ 23
-/** A catch-all for unrecognized purposes. Currently we don't expect
- * to make or see any circuits with this purpose. */
-#define CIRCUIT_PURPOSE_UNKNOWN 255
-
-/** True iff the circuit purpose <b>p</b> is for a circuit that
- * originated at this node. */
-#define CIRCUIT_PURPOSE_IS_ORIGIN(p) ((p)>CIRCUIT_PURPOSE_OR_MAX_)
-/** True iff the circuit purpose <b>p</b> is for a circuit that originated
- * here to serve as a client. (Hidden services don't count here.) */
-#define CIRCUIT_PURPOSE_IS_CLIENT(p) \
- ((p)> CIRCUIT_PURPOSE_OR_MAX_ && \
- (p)<=CIRCUIT_PURPOSE_C_MAX_)
-/** True iff the circuit_t <b>c</b> is actually an origin_circuit_t. */
-#define CIRCUIT_IS_ORIGIN(c) (CIRCUIT_PURPOSE_IS_ORIGIN((c)->purpose))
-/** True iff the circuit purpose <b>p</b> is for an established rendezvous
- * circuit. */
-#define CIRCUIT_PURPOSE_IS_ESTABLISHED_REND(p) \
- ((p) == CIRCUIT_PURPOSE_C_REND_JOINED || \
- (p) == CIRCUIT_PURPOSE_S_REND_JOINED)
-/** True iff the circuit_t c is actually an or_circuit_t */
-#define CIRCUIT_IS_ORCIRC(c) (((circuit_t *)(c))->magic == OR_CIRCUIT_MAGIC)
-
-/** True iff this circuit purpose should count towards the global
- * pending rate limit (set by MaxClientCircuitsPending). We count all
- * general purpose circuits, as well as the first step of client onion
- * service connections (HSDir gets). */
-#define CIRCUIT_PURPOSE_COUNTS_TOWARDS_MAXPENDING(p) \
- ((p) == CIRCUIT_PURPOSE_C_GENERAL || \
- (p) == CIRCUIT_PURPOSE_C_HSDIR_GET)
-
-/** How many circuits do we want simultaneously in-progress to handle
- * a given stream? */
-#define MIN_CIRCUITS_HANDLING_STREAM 2
-
-/* These RELAY_COMMAND constants define values for relay cell commands, and
-* must match those defined in tor-spec.txt. */
-#define RELAY_COMMAND_BEGIN 1
-#define RELAY_COMMAND_DATA 2
-#define RELAY_COMMAND_END 3
-#define RELAY_COMMAND_CONNECTED 4
-#define RELAY_COMMAND_SENDME 5
-#define RELAY_COMMAND_EXTEND 6
-#define RELAY_COMMAND_EXTENDED 7
-#define RELAY_COMMAND_TRUNCATE 8
-#define RELAY_COMMAND_TRUNCATED 9
-#define RELAY_COMMAND_DROP 10
-#define RELAY_COMMAND_RESOLVE 11
-#define RELAY_COMMAND_RESOLVED 12
-#define RELAY_COMMAND_BEGIN_DIR 13
-#define RELAY_COMMAND_EXTEND2 14
-#define RELAY_COMMAND_EXTENDED2 15
-
-#define RELAY_COMMAND_ESTABLISH_INTRO 32
-#define RELAY_COMMAND_ESTABLISH_RENDEZVOUS 33
-#define RELAY_COMMAND_INTRODUCE1 34
-#define RELAY_COMMAND_INTRODUCE2 35
-#define RELAY_COMMAND_RENDEZVOUS1 36
-#define RELAY_COMMAND_RENDEZVOUS2 37
-#define RELAY_COMMAND_INTRO_ESTABLISHED 38
-#define RELAY_COMMAND_RENDEZVOUS_ESTABLISHED 39
-#define RELAY_COMMAND_INTRODUCE_ACK 40
-
-/* Reasons why an OR connection is closed. */
-#define END_OR_CONN_REASON_DONE 1
-#define END_OR_CONN_REASON_REFUSED 2 /* connection refused */
-#define END_OR_CONN_REASON_OR_IDENTITY 3
-#define END_OR_CONN_REASON_CONNRESET 4 /* connection reset by peer */
-#define END_OR_CONN_REASON_TIMEOUT 5
-#define END_OR_CONN_REASON_NO_ROUTE 6 /* no route to host/net */
-#define END_OR_CONN_REASON_IO_ERROR 7 /* read/write error */
-#define END_OR_CONN_REASON_RESOURCE_LIMIT 8 /* sockets, buffers, etc */
-#define END_OR_CONN_REASON_PT_MISSING 9 /* PT failed or not available */
-#define END_OR_CONN_REASON_MISC 10
-
-/* Reasons why we (or a remote OR) might close a stream. See tor-spec.txt for
- * documentation of these. The values must match. */
-#define END_STREAM_REASON_MISC 1
-#define END_STREAM_REASON_RESOLVEFAILED 2
-#define END_STREAM_REASON_CONNECTREFUSED 3
-#define END_STREAM_REASON_EXITPOLICY 4
-#define END_STREAM_REASON_DESTROY 5
-#define END_STREAM_REASON_DONE 6
-#define END_STREAM_REASON_TIMEOUT 7
-#define END_STREAM_REASON_NOROUTE 8
-#define END_STREAM_REASON_HIBERNATING 9
-#define END_STREAM_REASON_INTERNAL 10
-#define END_STREAM_REASON_RESOURCELIMIT 11
-#define END_STREAM_REASON_CONNRESET 12
-#define END_STREAM_REASON_TORPROTOCOL 13
-#define END_STREAM_REASON_NOTDIRECTORY 14
-#define END_STREAM_REASON_ENTRYPOLICY 15
-
-/* These high-numbered end reasons are not part of the official spec,
- * and are not intended to be put in relay end cells. They are here
- * to be more informative when sending back socks replies to the
- * application. */
-/* XXXX 256 is no longer used; feel free to reuse it. */
-/** We were unable to attach the connection to any circuit at all. */
-/* XXXX the ways we use this one don't make a lot of sense. */
-#define END_STREAM_REASON_CANT_ATTACH 257
-/** We can't connect to any directories at all, so we killed our streams
- * before they can time out. */
-#define END_STREAM_REASON_NET_UNREACHABLE 258
-/** This is a SOCKS connection, and the client used (or misused) the SOCKS
- * protocol in a way we couldn't handle. */
-#define END_STREAM_REASON_SOCKSPROTOCOL 259
-/** This is a transparent proxy connection, but we can't extract the original
- * target address:port. */
-#define END_STREAM_REASON_CANT_FETCH_ORIG_DEST 260
-/** This is a connection on the NATD port, and the destination IP:Port was
- * either ill-formed or out-of-range. */
-#define END_STREAM_REASON_INVALID_NATD_DEST 261
-/** The target address is in a private network (like 127.0.0.1 or 10.0.0.1);
- * you don't want to do that over a randomly chosen exit */
-#define END_STREAM_REASON_PRIVATE_ADDR 262
-/** This is an HTTP tunnel connection and the client used or misused HTTP in a
- * way we can't handle.
- */
-#define END_STREAM_REASON_HTTPPROTOCOL 263
-
-/** Bitwise-and this value with endreason to mask out all flags. */
-#define END_STREAM_REASON_MASK 511
-
-/** Bitwise-or this with the argument to control_event_stream_status
- * to indicate that the reason came from an END cell. */
-#define END_STREAM_REASON_FLAG_REMOTE 512
-/** Bitwise-or this with the argument to control_event_stream_status
- * to indicate that we already sent a CLOSED stream event. */
-#define END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED 1024
-/** Bitwise-or this with endreason to indicate that we already sent
- * a socks reply, and no further reply needs to be sent from
- * connection_mark_unattached_ap(). */
-#define END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED 2048
-
-/** Reason for remapping an AP connection's address: we have a cached
- * answer. */
-#define REMAP_STREAM_SOURCE_CACHE 1
-/** Reason for remapping an AP connection's address: the exit node told us an
- * answer. */
-#define REMAP_STREAM_SOURCE_EXIT 2
-
-/* 'type' values to use in RESOLVED cells. Specified in tor-spec.txt. */
-#define RESOLVED_TYPE_HOSTNAME 0
-#define RESOLVED_TYPE_IPV4 4
-#define RESOLVED_TYPE_IPV6 6
-#define RESOLVED_TYPE_ERROR_TRANSIENT 0xF0
-#define RESOLVED_TYPE_ERROR 0xF1
-
-/* Negative reasons are internal: we never send them in a DESTROY or TRUNCATE
- * call; they only go to the controller for tracking */
-
-/* Closing introduction point that were opened in parallel. */
-#define END_CIRC_REASON_IP_NOW_REDUNDANT -4
-
-/** Our post-timeout circuit time measurement period expired.
- * We must give up now */
-#define END_CIRC_REASON_MEASUREMENT_EXPIRED -3
-
-/** We couldn't build a path for this circuit. */
-#define END_CIRC_REASON_NOPATH -2
-/** Catch-all "other" reason for closing origin circuits. */
-#define END_CIRC_AT_ORIGIN -1
-
-/* Reasons why we (or a remote OR) might close a circuit. See tor-spec.txt
- * section 5.4 for documentation of these. */
-#define END_CIRC_REASON_MIN_ 0
-#define END_CIRC_REASON_NONE 0
-#define END_CIRC_REASON_TORPROTOCOL 1
-#define END_CIRC_REASON_INTERNAL 2
-#define END_CIRC_REASON_REQUESTED 3
-#define END_CIRC_REASON_HIBERNATING 4
-#define END_CIRC_REASON_RESOURCELIMIT 5
-#define END_CIRC_REASON_CONNECTFAILED 6
-#define END_CIRC_REASON_OR_IDENTITY 7
-#define END_CIRC_REASON_CHANNEL_CLOSED 8
-#define END_CIRC_REASON_FINISHED 9
-#define END_CIRC_REASON_TIMEOUT 10
-#define END_CIRC_REASON_DESTROYED 11
-#define END_CIRC_REASON_NOSUCHSERVICE 12
-#define END_CIRC_REASON_MAX_ 12
-
-/** Bitwise-OR this with the argument to circuit_mark_for_close() or
- * control_event_circuit_status() to indicate that the reason was
- * passed through from a destroy or truncate cell. */
-#define END_CIRC_REASON_FLAG_REMOTE 512
-
-/** Length of 'y' portion of 'y.onion' URL. */
-#define REND_SERVICE_ID_LEN_BASE32 16
-
-/** Length of 'y.onion' including '.onion' URL. */
-#define REND_SERVICE_ADDRESS_LEN (16+1+5)
-
-/** Length of a binary-encoded rendezvous service ID. */
-#define REND_SERVICE_ID_LEN 10
-
-/** Time period for which a v2 descriptor will be valid. */
-#define REND_TIME_PERIOD_V2_DESC_VALIDITY (24*60*60)
-
-/** Time period within which two sets of v2 descriptors will be uploaded in
- * parallel. */
-#define REND_TIME_PERIOD_OVERLAPPING_V2_DESCS (60*60)
-
-/** Number of non-consecutive replicas (i.e. distributed somewhere
- * in the ring) for a descriptor. */
-#define REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS 2
-
-/** Number of consecutive replicas for a descriptor. */
-#define REND_NUMBER_OF_CONSECUTIVE_REPLICAS 3
-
-/** Length of v2 descriptor ID (32 base32 chars = 160 bits). */
-#define REND_DESC_ID_V2_LEN_BASE32 BASE32_DIGEST_LEN
-
-/** Length of the base32-encoded secret ID part of versioned hidden service
- * descriptors. */
-#define REND_SECRET_ID_PART_LEN_BASE32 BASE32_DIGEST_LEN
-
-/** Length of the base32-encoded hash of an introduction point's
- * identity key. */
-#define REND_INTRO_POINT_ID_LEN_BASE32 BASE32_DIGEST_LEN
-
-/** Length of the descriptor cookie that is used for client authorization
- * to hidden services. */
-#define REND_DESC_COOKIE_LEN 16
-
-/** Length of the base64-encoded descriptor cookie that is used for
- * exchanging client authorization between hidden service and client. */
-#define REND_DESC_COOKIE_LEN_BASE64 22
-
-/** Length of client identifier in encrypted introduction points for hidden
- * service authorization type 'basic'. */
-#define REND_BASIC_AUTH_CLIENT_ID_LEN 4
-
-/** Multiple of the number of clients to which the real number of clients
- * is padded with fake clients for hidden service authorization type
- * 'basic'. */
-#define REND_BASIC_AUTH_CLIENT_MULTIPLE 16
-
-/** Length of client entry consisting of client identifier and encrypted
- * session key for hidden service authorization type 'basic'. */
-#define REND_BASIC_AUTH_CLIENT_ENTRY_LEN (REND_BASIC_AUTH_CLIENT_ID_LEN \
- + CIPHER_KEY_LEN)
-
-/** Maximum size of v2 hidden service descriptors. */
-#define REND_DESC_MAX_SIZE (20 * 1024)
-
-/** Legal characters for use in authorized client names for a hidden
- * service. */
-#define REND_LEGAL_CLIENTNAME_CHARACTERS \
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-_"
-
-/** Maximum length of authorized client names for a hidden service. */
-#define REND_CLIENTNAME_MAX_LEN 16
-
-/** Length of the rendezvous cookie that is used to connect circuits at the
- * rendezvous point. */
-#define REND_COOKIE_LEN DIGEST_LEN
-
-/** Client authorization type that a hidden service performs. */
-typedef enum rend_auth_type_t {
- REND_NO_AUTH = 0,
- REND_BASIC_AUTH = 1,
- REND_STEALTH_AUTH = 2,
-} rend_auth_type_t;
-
-/** Client-side configuration of authorization for a hidden service. */
-typedef struct rend_service_authorization_t {
- uint8_t descriptor_cookie[REND_DESC_COOKIE_LEN];
- char onion_address[REND_SERVICE_ADDRESS_LEN+1];
- rend_auth_type_t auth_type;
-} rend_service_authorization_t;
-
-/** Client- and server-side data that is used for hidden service connection
- * establishment. Not all fields contain data depending on where this struct
- * is used. */
-typedef struct rend_data_t {
- /* Hidden service protocol version of this base object. */
- uint32_t version;
-
- /** List of HSDir fingerprints on which this request has been sent to. This
- * contains binary identity digest of the directory of size DIGEST_LEN. */
- smartlist_t *hsdirs_fp;
-
- /** Rendezvous cookie used by both, client and service. */
- char rend_cookie[REND_COOKIE_LEN];
-
- /** Number of streams associated with this rendezvous circuit. */
- int nr_streams;
-} rend_data_t;
-
-typedef struct rend_data_v2_t {
- /* Rendezvous base data. */
- rend_data_t base_;
-
- /** Onion address (without the .onion part) that a client requests. */
- char onion_address[REND_SERVICE_ID_LEN_BASE32+1];
-
- /** Descriptor ID for each replicas computed from the onion address. If
- * the onion address is empty, this array MUST be empty. We keep them so
- * we know when to purge our entry in the last hsdir request table. */
- char descriptor_id[REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS][DIGEST_LEN];
-
- /** (Optional) descriptor cookie that is used by a client. */
- char descriptor_cookie[REND_DESC_COOKIE_LEN];
-
- /** Authorization type for accessing a service used by a client. */
- rend_auth_type_t auth_type;
-
- /** Descriptor ID for a client request. The control port command HSFETCH
- * uses this. It's set if the descriptor query should only use this
- * descriptor ID. */
- char desc_id_fetch[DIGEST_LEN];
-
- /** Hash of the hidden service's PK used by a service. */
- char rend_pk_digest[DIGEST_LEN];
-} rend_data_v2_t;
-
-/* From a base rend_data_t object <b>d</d>, return the v2 object. */
-static inline
-rend_data_v2_t *TO_REND_DATA_V2(const rend_data_t *d)
-{
- tor_assert(d);
- tor_assert(d->version == 2);
- return DOWNCAST(rend_data_v2_t, d);
-}
-
-/* Stub because we can't include hs_ident.h. */
-struct hs_ident_edge_conn_t;
-struct hs_ident_dir_conn_t;
-struct hs_ident_circuit_t;
-
-/* Hidden service directory index used in a node_t which is set once we set
- * the consensus. */
-typedef struct hsdir_index_t {
- /* HSDir index to use when fetching a descriptor. */
- uint8_t fetch[DIGEST256_LEN];
-
- /* HSDir index used by services to store their first and second
- * descriptor. The first descriptor is chronologically older than the second
- * one and uses older TP and SRV values. */
- uint8_t store_first[DIGEST256_LEN];
- uint8_t store_second[DIGEST256_LEN];
-} hsdir_index_t;
-
-/** Time interval for tracking replays of DH public keys received in
- * INTRODUCE2 cells. Used only to avoid launching multiple
- * simultaneous attempts to connect to the same rendezvous point. */
-#define REND_REPLAY_TIME_INTERVAL (5 * 60)
-
-/** Used to indicate which way a cell is going on a circuit. */
-typedef enum {
- CELL_DIRECTION_IN=1, /**< The cell is moving towards the origin. */
- CELL_DIRECTION_OUT=2, /**< The cell is moving away from the origin. */
-} cell_direction_t;
-
-/** Initial value for both sides of a circuit transmission window when the
- * circuit is initialized. Measured in cells. */
-#define CIRCWINDOW_START 1000
-#define CIRCWINDOW_START_MIN 100
-#define CIRCWINDOW_START_MAX 1000
-/** Amount to increment a circuit window when we get a circuit SENDME. */
-#define CIRCWINDOW_INCREMENT 100
-/** Initial value on both sides of a stream transmission window when the
- * stream is initialized. Measured in cells. */
-#define STREAMWINDOW_START 500
-#define STREAMWINDOW_START_MAX 500
-/** Amount to increment a stream window when we get a stream SENDME. */
-#define STREAMWINDOW_INCREMENT 50
-
-/** Maximum number of queued cells on a circuit for which we are the
- * midpoint before we give up and kill it. This must be >= circwindow
- * to avoid killing innocent circuits, and >= circwindow*2 to give
- * leaky-pipe a chance of working someday. The ORCIRC_MAX_MIDDLE_KILL_THRESH
- * ratio controls the margin of error between emitting a warning and
- * killing the circuit.
- */
-#define ORCIRC_MAX_MIDDLE_CELLS (CIRCWINDOW_START_MAX*2)
-/** Ratio of hard (circuit kill) to soft (warning) thresholds for the
- * ORCIRC_MAX_MIDDLE_CELLS tests.
- */
-#define ORCIRC_MAX_MIDDLE_KILL_THRESH (1.1f)
-
-/* Cell commands. These values are defined in tor-spec.txt. */
-#define CELL_PADDING 0
-#define CELL_CREATE 1
-#define CELL_CREATED 2
-#define CELL_RELAY 3
-#define CELL_DESTROY 4
-#define CELL_CREATE_FAST 5
-#define CELL_CREATED_FAST 6
-#define CELL_VERSIONS 7
-#define CELL_NETINFO 8
-#define CELL_RELAY_EARLY 9
-#define CELL_CREATE2 10
-#define CELL_CREATED2 11
-#define CELL_PADDING_NEGOTIATE 12
-
-#define CELL_VPADDING 128
-#define CELL_CERTS 129
-#define CELL_AUTH_CHALLENGE 130
-#define CELL_AUTHENTICATE 131
-#define CELL_AUTHORIZE 132
-#define CELL_COMMAND_MAX_ 132
-
-/** How long to test reachability before complaining to the user. */
-#define TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT (20*60)
-
-/** Legal characters in a nickname. */
-#define LEGAL_NICKNAME_CHARACTERS \
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
-
-/** Name to use in client TLS certificates if no nickname is given. Once
- * Tor 0.1.2.x is obsolete, we can remove this. */
-#define DEFAULT_CLIENT_NICKNAME "client"
-
-/** Name chosen by routers that don't configure nicknames */
-#define UNNAMED_ROUTER_NICKNAME "Unnamed"
-
-/** Number of bytes in a SOCKS4 header. */
-#define SOCKS4_NETWORK_LEN 8
-
-/*
- * Relay payload:
- * Relay command [1 byte]
- * Recognized [2 bytes]
- * Stream ID [2 bytes]
- * Partial SHA-1 [4 bytes]
- * Length [2 bytes]
- * Relay payload [498 bytes]
- */
-
-/** Number of bytes in a cell, minus cell header. */
-#define CELL_PAYLOAD_SIZE 509
-/** Number of bytes in a cell transmitted over the network, in the longest
- * form */
-#define CELL_MAX_NETWORK_SIZE 514
-
-/** Maximum length of a header on a variable-length cell. */
-#define VAR_CELL_MAX_HEADER_SIZE 7
-
-static int get_cell_network_size(int wide_circ_ids);
-static inline int get_cell_network_size(int wide_circ_ids)
-{
- return wide_circ_ids ? CELL_MAX_NETWORK_SIZE : CELL_MAX_NETWORK_SIZE - 2;
-}
-static int get_var_cell_header_size(int wide_circ_ids);
-static inline int get_var_cell_header_size(int wide_circ_ids)
-{
- return wide_circ_ids ? VAR_CELL_MAX_HEADER_SIZE :
- VAR_CELL_MAX_HEADER_SIZE - 2;
-}
-static int get_circ_id_size(int wide_circ_ids);
-static inline int get_circ_id_size(int wide_circ_ids)
-{
- return wide_circ_ids ? 4 : 2;
-}
-
-/** Number of bytes in a relay cell's header (not including general cell
- * header). */
-#define RELAY_HEADER_SIZE (1+2+2+4+2)
-/** Largest number of bytes that can fit in a relay cell payload. */
-#define RELAY_PAYLOAD_SIZE (CELL_PAYLOAD_SIZE-RELAY_HEADER_SIZE)
-
-/** Identifies a circuit on an or_connection */
-typedef uint32_t circid_t;
-/** Identifies a stream on a circuit */
-typedef uint16_t streamid_t;
-
-/* channel_t typedef; struct channel_s is in channel.h */
-
-typedef struct channel_s channel_t;
-
-/* channel_listener_t typedef; struct channel_listener_s is in channel.h */
-
-typedef struct channel_listener_s channel_listener_t;
-
-/* channel states for channel_t */
-
-typedef enum {
- /*
- * Closed state - channel is inactive
- *
- * Permitted transitions from:
- * - CHANNEL_STATE_CLOSING
- * Permitted transitions to:
- * - CHANNEL_STATE_OPENING
- */
- CHANNEL_STATE_CLOSED = 0,
- /*
- * Opening state - channel is trying to connect
- *
- * Permitted transitions from:
- * - CHANNEL_STATE_CLOSED
- * Permitted transitions to:
- * - CHANNEL_STATE_CLOSING
- * - CHANNEL_STATE_ERROR
- * - CHANNEL_STATE_OPEN
- */
- CHANNEL_STATE_OPENING,
- /*
- * Open state - channel is active and ready for use
- *
- * Permitted transitions from:
- * - CHANNEL_STATE_MAINT
- * - CHANNEL_STATE_OPENING
- * Permitted transitions to:
- * - CHANNEL_STATE_CLOSING
- * - CHANNEL_STATE_ERROR
- * - CHANNEL_STATE_MAINT
- */
- CHANNEL_STATE_OPEN,
- /*
- * Maintenance state - channel is temporarily offline for subclass specific
- * maintenance activities such as TLS renegotiation.
- *
- * Permitted transitions from:
- * - CHANNEL_STATE_OPEN
- * Permitted transitions to:
- * - CHANNEL_STATE_CLOSING
- * - CHANNEL_STATE_ERROR
- * - CHANNEL_STATE_OPEN
- */
- CHANNEL_STATE_MAINT,
- /*
- * Closing state - channel is shutting down
- *
- * Permitted transitions from:
- * - CHANNEL_STATE_MAINT
- * - CHANNEL_STATE_OPEN
- * Permitted transitions to:
- * - CHANNEL_STATE_CLOSED,
- * - CHANNEL_STATE_ERROR
- */
- CHANNEL_STATE_CLOSING,
- /*
- * Error state - channel has experienced a permanent error
- *
- * Permitted transitions from:
- * - CHANNEL_STATE_CLOSING
- * - CHANNEL_STATE_MAINT
- * - CHANNEL_STATE_OPENING
- * - CHANNEL_STATE_OPEN
- * Permitted transitions to:
- * - None
- */
- CHANNEL_STATE_ERROR,
- /*
- * Placeholder for maximum state value
- */
- CHANNEL_STATE_LAST
-} channel_state_t;
-
-/* channel listener states for channel_listener_t */
-
-typedef enum {
- /*
- * Closed state - channel listener is inactive
- *
- * Permitted transitions from:
- * - CHANNEL_LISTENER_STATE_CLOSING
- * Permitted transitions to:
- * - CHANNEL_LISTENER_STATE_LISTENING
- */
- CHANNEL_LISTENER_STATE_CLOSED = 0,
- /*
- * Listening state - channel listener is listening for incoming
- * connections
- *
- * Permitted transitions from:
- * - CHANNEL_LISTENER_STATE_CLOSED
- * Permitted transitions to:
- * - CHANNEL_LISTENER_STATE_CLOSING
- * - CHANNEL_LISTENER_STATE_ERROR
- */
- CHANNEL_LISTENER_STATE_LISTENING,
- /*
- * Closing state - channel listener is shutting down
- *
- * Permitted transitions from:
- * - CHANNEL_LISTENER_STATE_LISTENING
- * Permitted transitions to:
- * - CHANNEL_LISTENER_STATE_CLOSED,
- * - CHANNEL_LISTENER_STATE_ERROR
- */
- CHANNEL_LISTENER_STATE_CLOSING,
- /*
- * Error state - channel listener has experienced a permanent error
- *
- * Permitted transitions from:
- * - CHANNEL_STATE_CLOSING
- * - CHANNEL_STATE_LISTENING
- * Permitted transitions to:
- * - None
- */
- CHANNEL_LISTENER_STATE_ERROR,
- /*
- * Placeholder for maximum state value
- */
- CHANNEL_LISTENER_STATE_LAST
-} channel_listener_state_t;
-
-/* TLS channel stuff */
-
-typedef struct channel_tls_s channel_tls_t;
-
-/* circuitmux_t typedef; struct circuitmux_s is in circuitmux.h */
-
-typedef struct circuitmux_s circuitmux_t;
-
-/** Parsed onion routing cell. All communication between nodes
- * is via cells. */
-typedef struct cell_t {
- circid_t circ_id; /**< Circuit which received the cell. */
- uint8_t command; /**< Type of the cell: one of CELL_PADDING, CELL_CREATE,
- * CELL_DESTROY, etc */
- uint8_t payload[CELL_PAYLOAD_SIZE]; /**< Cell body. */
-} cell_t;
-
-/** Parsed variable-length onion routing cell. */
-typedef struct var_cell_t {
- /** Type of the cell: CELL_VERSIONS, etc. */
- uint8_t command;
- /** Circuit thich received the cell */
- circid_t circ_id;
- /** Number of bytes actually stored in <b>payload</b> */
- uint16_t payload_len;
- /** Payload of this cell */
- uint8_t payload[FLEXIBLE_ARRAY_MEMBER];
-} var_cell_t;
-
-/** A parsed Extended ORPort message. */
-typedef struct ext_or_cmd_t {
- uint16_t cmd; /** Command type */
- uint16_t len; /** Body length */
- char body[FLEXIBLE_ARRAY_MEMBER]; /** Message body */
-} ext_or_cmd_t;
-
-/** A cell as packed for writing to the network. */
-typedef struct packed_cell_t {
- /** Next cell queued on this circuit. */
- TOR_SIMPLEQ_ENTRY(packed_cell_t) next;
- char body[CELL_MAX_NETWORK_SIZE]; /**< Cell as packed for network. */
- uint32_t inserted_timestamp; /**< Time (in timestamp units) when this cell
- * was inserted */
-} packed_cell_t;
-
-/** A queue of cells on a circuit, waiting to be added to the
- * or_connection_t's outbuf. */
-typedef struct cell_queue_t {
- /** Linked list of packed_cell_t*/
- TOR_SIMPLEQ_HEAD(cell_simpleq, packed_cell_t) head;
- int n; /**< The number of cells in the queue. */
-} cell_queue_t;
-
-/** A single queued destroy cell. */
-typedef struct destroy_cell_t {
- TOR_SIMPLEQ_ENTRY(destroy_cell_t) next;
- circid_t circid;
- uint32_t inserted_timestamp; /**< Time (in timestamp units) when this cell
- * was inserted */
- uint8_t reason;
-} destroy_cell_t;
-
-/** A queue of destroy cells on a channel. */
-typedef struct destroy_cell_queue_t {
- /** Linked list of packed_cell_t */
- TOR_SIMPLEQ_HEAD(dcell_simpleq, destroy_cell_t) head;
- int n; /**< The number of cells in the queue. */
-} destroy_cell_queue_t;
-
-/** Beginning of a RELAY cell payload. */
-typedef struct {
- uint8_t command; /**< The end-to-end relay command. */
- uint16_t recognized; /**< Used to tell whether cell is for us. */
- streamid_t stream_id; /**< Which stream is this cell associated with? */
- char integrity[4]; /**< Used to tell whether cell is corrupted. */
- uint16_t length; /**< How long is the payload body? */
-} relay_header_t;
-
-typedef struct socks_request_t socks_request_t;
-
-typedef struct entry_port_cfg_t {
- /* Client port types (socks, dns, trans, natd) only: */
- uint8_t isolation_flags; /**< Zero or more isolation flags */
- int session_group; /**< A session group, or -1 if this port is not in a
- * session group. */
-
- /* Socks only: */
- /** When both no-auth and user/pass are advertised by a SOCKS client, select
- * no-auth. */
- unsigned int socks_prefer_no_auth : 1;
- /** When ISO_SOCKSAUTH is in use, Keep-Alive circuits indefinitely. */
- unsigned int socks_iso_keep_alive : 1;
-
- /* Client port types only: */
- unsigned int ipv4_traffic : 1;
- unsigned int ipv6_traffic : 1;
- unsigned int prefer_ipv6 : 1;
- unsigned int dns_request : 1;
- unsigned int onion_traffic : 1;
-
- /** For a socks listener: should we cache IPv4/IPv6 DNS information that
- * exit nodes tell us?
- *
- * @{ */
- unsigned int cache_ipv4_answers : 1;
- unsigned int cache_ipv6_answers : 1;
- /** @} */
- /** For a socks listeners: if we find an answer in our client-side DNS cache,
- * should we use it?
- *
- * @{ */
- unsigned int use_cached_ipv4_answers : 1;
- unsigned int use_cached_ipv6_answers : 1;
- /** @} */
- /** For socks listeners: When we can automap an address to IPv4 or IPv6,
- * do we prefer IPv6? */
- unsigned int prefer_ipv6_virtaddr : 1;
-
-} entry_port_cfg_t;
-
-typedef struct server_port_cfg_t {
- /* Server port types (or, dir) only: */
- unsigned int no_advertise : 1;
- unsigned int no_listen : 1;
- unsigned int all_addrs : 1;
- unsigned int bind_ipv4_only : 1;
- unsigned int bind_ipv6_only : 1;
-} server_port_cfg_t;
-
-/* Values for connection_t.magic: used to make sure that downcasts (casts from
-* connection_t to foo_connection_t) are safe. */
-#define BASE_CONNECTION_MAGIC 0x7C3C304Eu
-#define OR_CONNECTION_MAGIC 0x7D31FF03u
-#define EDGE_CONNECTION_MAGIC 0xF0374013u
-#define ENTRY_CONNECTION_MAGIC 0xbb4a5703
-#define DIR_CONNECTION_MAGIC 0x9988ffeeu
-#define CONTROL_CONNECTION_MAGIC 0x8abc765du
-#define LISTENER_CONNECTION_MAGIC 0x1a1ac741u
-
-struct buf_t;
-
-/** Description of a connection to another host or process, and associated
- * data.
- *
- * A connection is named based on what it's connected to -- an "OR
- * connection" has a Tor node on the other end, an "exit
- * connection" has a website or other server on the other end, and an
- * "AP connection" has an application proxy (and thus a user) on the
- * other end.
- *
- * Every connection has a type and a state. Connections never change
- * their type, but can go through many state changes in their lifetime.
- *
- * Every connection has two associated input and output buffers.
- * Listeners don't use them. For non-listener connections, incoming
- * data is appended to conn->inbuf, and outgoing data is taken from
- * conn->outbuf. Connections differ primarily in the functions called
- * to fill and drain these buffers.
- */
-typedef struct connection_t {
- uint32_t magic; /**< For memory debugging: must equal one of
- * *_CONNECTION_MAGIC. */
-
- uint8_t state; /**< Current state of this connection. */
- unsigned int type:5; /**< What kind of connection is this? */
- unsigned int purpose:5; /**< Only used for DIR and EXIT types currently. */
-
- /* The next fields are all one-bit booleans. Some are only applicable to
- * connection subtypes, but we hold them here anyway, to save space.
- */
- unsigned int read_blocked_on_bw:1; /**< Boolean: should we start reading
- * again once the bandwidth throttler allows it? */
- unsigned int write_blocked_on_bw:1; /**< Boolean: should we start writing
- * again once the bandwidth throttler allows
- * writes? */
- unsigned int hold_open_until_flushed:1; /**< Despite this connection's being
- * marked for close, do we flush it
- * before closing it? */
- unsigned int inbuf_reached_eof:1; /**< Boolean: did read() return 0 on this
- * conn? */
- /** Set to 1 when we're inside connection_flushed_some to keep us from
- * calling connection_handle_write() recursively. */
- unsigned int in_flushed_some:1;
- /** True if connection_handle_write is currently running on this connection.
- */
- unsigned int in_connection_handle_write:1;
-
- /* For linked connections:
- */
- unsigned int linked:1; /**< True if there is, or has been, a linked_conn. */
- /** True iff we'd like to be notified about read events from the
- * linked conn. */
- unsigned int reading_from_linked_conn:1;
- /** True iff we're willing to write to the linked conn. */
- unsigned int writing_to_linked_conn:1;
- /** True iff we're currently able to read on the linked conn, and our
- * read_event should be made active with libevent. */
- unsigned int active_on_link:1;
- /** True iff we've called connection_close_immediate() on this linked
- * connection. */
- unsigned int linked_conn_is_closed:1;
-
- /** CONNECT/SOCKS proxy client handshake state (for outgoing connections). */
- unsigned int proxy_state:4;
-
- /** Our socket; set to TOR_INVALID_SOCKET if this connection is closed,
- * or has no socket. */
- tor_socket_t s;
- int conn_array_index; /**< Index into the global connection array. */
-
- struct event *read_event; /**< Libevent event structure. */
- struct event *write_event; /**< Libevent event structure. */
- 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
- * said we could write? */
-
- time_t timestamp_created; /**< When was this connection_t created? */
-
- 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.
- */
- 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. */
- uint16_t marked_for_close; /**< Should we close this conn on the next
- * iteration of the main loop? (If true, holds
- * the line number where this connection was
- * marked.) */
- 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. */
- /** Another connection that's connected to this one in lieu of a socket. */
- struct connection_t *linked_conn;
-
- /** Unique identifier for this connection on this Tor instance. */
- uint64_t global_identifier;
-
- /** Bytes read since last call to control_event_conn_bandwidth_used().
- * Only used if we're configured to emit CONN_BW events. */
- uint32_t n_read_conn_bw;
-
- /** Bytes written since last call to control_event_conn_bandwidth_used().
- * Only used if we're configured to emit CONN_BW events. */
- uint32_t n_written_conn_bw;
-} connection_t;
-
-/** Subtype of connection_t; used for a listener socket. */
-typedef struct listener_connection_t {
- connection_t base_;
-
- /** If the connection is a CONN_TYPE_AP_DNS_LISTENER, this field points
- * to the evdns_server_port it uses to listen to and answer connections. */
- struct evdns_server_port *dns_server_port;
-
- entry_port_cfg_t entry_cfg;
-
-} listener_connection_t;
-
-/** Minimum length of the random part of an AUTH_CHALLENGE cell. */
-#define OR_AUTH_CHALLENGE_LEN 32
-
-/**
- * @name Certificate types for CERTS cells.
- *
- * These values are defined by the protocol, and affect how an X509
- * certificate in a CERTS cell is interpreted and used.
- *
- * @{ */
-/** A certificate that authenticates a TLS link key. The subject key
- * must match the key used in the TLS handshake; it must be signed by
- * the identity key. */
-#define OR_CERT_TYPE_TLS_LINK 1
-/** A self-signed identity certificate. The subject key must be a
- * 1024-bit RSA key. */
-#define OR_CERT_TYPE_ID_1024 2
-/** A certificate that authenticates a key used in an AUTHENTICATE cell
- * in the v3 handshake. The subject key must be a 1024-bit RSA key; it
- * must be signed by the identity key */
-#define OR_CERT_TYPE_AUTH_1024 3
-/* DOCDOC */
-#define OR_CERT_TYPE_RSA_ED_CROSSCERT 7
-/**@}*/
-
-/** The first supported type of AUTHENTICATE cell. It contains
- * a bunch of structures signed with an RSA1024 key. The signed
- * structures include a HMAC using negotiated TLS secrets, and a digest
- * of all cells sent or received before the AUTHENTICATE cell (including
- * the random server-generated AUTH_CHALLENGE cell).
- */
-#define AUTHTYPE_RSA_SHA256_TLSSECRET 1
-/** As AUTHTYPE_RSA_SHA256_TLSSECRET, but instead of using the
- * negotiated TLS secrets, uses exported keying material from the TLS
- * session as described in RFC 5705.
- *
- * Not used by today's tors, since everything that supports this
- * also supports ED25519_SHA256_5705, which is better.
- **/
-#define AUTHTYPE_RSA_SHA256_RFC5705 2
-/** As AUTHTYPE_RSA_SHA256_RFC5705, but uses an Ed25519 identity key to
- * authenticate. */
-#define AUTHTYPE_ED25519_SHA256_RFC5705 3
-/*
- * NOTE: authchallenge_type_is_better() relies on these AUTHTYPE codes
- * being sorted in order of preference. If we someday add one with
- * a higher numerical value that we don't like as much, we should revise
- * authchallenge_type_is_better().
- */
-
-/** The length of the part of the AUTHENTICATE cell body that the client and
- * server can generate independently (when using RSA_SHA256_TLSSECRET). It
- * contains everything except the client's timestamp, the client's randomly
- * generated nonce, and the signature. */
-#define V3_AUTH_FIXED_PART_LEN (8+(32*6))
-/** The length of the part of the AUTHENTICATE cell body that the client
- * signs. */
-#define V3_AUTH_BODY_LEN (V3_AUTH_FIXED_PART_LEN + 8 + 16)
-
-/** Structure to hold all the certificates we've received on an OR connection
- */
-typedef struct or_handshake_certs_t {
- /** True iff we originated this connection. */
- int started_here;
- /** The cert for the 'auth' RSA key that's supposed to sign the AUTHENTICATE
- * cell. Signed with the RSA identity key. */
- tor_x509_cert_t *auth_cert;
- /** The cert for the 'link' RSA key that was used to negotiate the TLS
- * connection. Signed with the RSA identity key. */
- tor_x509_cert_t *link_cert;
- /** A self-signed identity certificate: the RSA identity key signed
- * with itself. */
- tor_x509_cert_t *id_cert;
- /** The Ed25519 signing key, signed with the Ed25519 identity key. */
- struct tor_cert_st *ed_id_sign;
- /** A digest of the X509 link certificate for the TLS connection, signed
- * with the Ed25519 siging key. */
- struct tor_cert_st *ed_sign_link;
- /** The Ed25519 authentication key (that's supposed to sign an AUTHENTICATE
- * cell) , signed with the Ed25519 siging key. */
- struct tor_cert_st *ed_sign_auth;
- /** The Ed25519 identity key, crosssigned with the RSA identity key. */
- uint8_t *ed_rsa_crosscert;
- /** The length of <b>ed_rsa_crosscert</b> in bytes */
- size_t ed_rsa_crosscert_len;
-} or_handshake_certs_t;
-
-/** Stores flags and information related to the portion of a v2/v3 Tor OR
- * connection handshake that happens after the TLS handshake is finished.
- */
-typedef struct or_handshake_state_t {
- /** When was the VERSIONS cell sent on this connection? Used to get
- * an estimate of the skew in the returning NETINFO reply. */
- time_t sent_versions_at;
- /** True iff we originated this connection */
- unsigned int started_here : 1;
- /** True iff we have received and processed a VERSIONS cell. */
- unsigned int received_versions : 1;
- /** True iff we have received and processed an AUTH_CHALLENGE cell */
- unsigned int received_auth_challenge : 1;
- /** True iff we have received and processed a CERTS cell. */
- unsigned int received_certs_cell : 1;
- /** True iff we have received and processed an AUTHENTICATE cell */
- unsigned int received_authenticate : 1;
-
- /* True iff we've received valid authentication to some identity. */
- unsigned int authenticated : 1;
- unsigned int authenticated_rsa : 1;
- unsigned int authenticated_ed25519 : 1;
-
- /* True iff we have sent a netinfo cell */
- unsigned int sent_netinfo : 1;
-
- /** The signing->ed25519 link certificate corresponding to the x509
- * certificate we used on the TLS connection (if this is a server-side
- * connection). We make a copy of this here to prevent a race condition
- * caused by TLS context rotation. */
- struct tor_cert_st *own_link_cert;
-
- /** True iff we should feed outgoing cells into digest_sent and
- * digest_received respectively.
- *
- * From the server's side of the v3 handshake, we want to capture everything
- * from the VERSIONS cell through and including the AUTH_CHALLENGE cell.
- * From the client's, we want to capture everything from the VERSIONS cell
- * through but *not* including the AUTHENTICATE cell.
- *
- * @{ */
- unsigned int digest_sent_data : 1;
- unsigned int digest_received_data : 1;
- /**@}*/
-
- /** Identity RSA digest that we have received and authenticated for our peer
- * on this connection. */
- uint8_t authenticated_rsa_peer_id[DIGEST_LEN];
- /** Identity Ed25519 public key that we have received and authenticated for
- * our peer on this connection. */
- ed25519_public_key_t authenticated_ed25519_peer_id;
-
- /** Digests of the cells that we have sent or received as part of a V3
- * handshake. Used for making and checking AUTHENTICATE cells.
- *
- * @{
- */
- crypto_digest_t *digest_sent;
- crypto_digest_t *digest_received;
- /** @} */
-
- /** Certificates that a connection initiator sent us in a CERTS cell; we're
- * holding on to them until we get an AUTHENTICATE cell.
- */
- or_handshake_certs_t *certs;
-} or_handshake_state_t;
-
-/** Length of Extended ORPort connection identifier. */
-#define EXT_OR_CONN_ID_LEN DIGEST_LEN /* 20 */
-/*
- * OR_CONN_HIGHWATER and OR_CONN_LOWWATER moved from connection_or.c so
- * channeltls.c can see them too.
- */
-
-/** When adding cells to an OR connection's outbuf, keep adding until the
- * outbuf is at least this long, or we run out of cells. */
-#define OR_CONN_HIGHWATER (32*1024)
-
-/** Add cells to an OR connection's outbuf whenever the outbuf's data length
- * drops below this size. */
-#define OR_CONN_LOWWATER (16*1024)
-
-/** Subtype of connection_t for an "OR connection" -- that is, one that speaks
- * cells over TLS. */
-typedef struct or_connection_t {
- connection_t base_;
-
- /** Hash of the public RSA key for the other side's identity key, or zeroes
- * if the other side hasn't shown us a valid identity key. */
- char identity_digest[DIGEST_LEN];
-
- /** Extended ORPort connection identifier. */
- char *ext_or_conn_id;
- /** 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
- * client. */
- char *ext_or_auth_correct_client_hash;
- /** String carrying the name of the pluggable transport
- * (e.g. "obfs2") that is obfuscating this connection. If no
- * pluggable transports are used, it's NULL. */
- char *ext_or_transport;
-
- char *nickname; /**< Nickname of OR on other side (if any). */
-
- tor_tls_t *tls; /**< TLS connection state. */
- int tls_error; /**< Last tor_tls error code. */
- /** When we last used this conn for any client traffic. If not
- * recent, we can rate limit it further. */
-
- /* 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>. */
-
- /** 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
- * sure we aren't getting MITMed, either because we're connected to an
- * address listed in a server descriptor, or because an authenticated
- * NETINFO cell listed the address we're connected to as recognized. */
- unsigned int is_canonical:1;
-
- /** True iff this is an outgoing connection. */
- unsigned int is_outgoing:1;
- unsigned int proxy_type:2; /**< One of PROXY_NONE...PROXY_SOCKS5 */
- unsigned int wide_circ_ids:1;
- /** True iff this connection has had its bootstrap failure logged with
- * control_event_bootstrap_problem. */
- unsigned int have_noted_bootstrap_problem:1;
- /** True iff this is a client connection and its address has been put in the
- * geoip cache and handled by the DoS mitigation subsystem. We use this to
- * insure we have a coherent count of concurrent connection. */
- unsigned int tracked_for_dos_mitigation : 1;
-
- uint16_t link_proto; /**< What protocol version are we using? 0 for
- * "none negotiated yet." */
- uint16_t idle_timeout; /**< How long can this connection sit with no
- * circuits on it before we close it? Based on
- * IDLE_CIRCUIT_TIMEOUT_{NON,}CANONICAL and
- * on is_canonical, randomized. */
- or_handshake_state_t *handshake_state; /**< If we are setting this connection
- * up, state information to do so. */
-
- time_t timestamp_lastempty; /**< When was the outbuf last completely empty?*/
-
- token_bucket_rw_t bucket; /**< Used for rate limiting when the connection is
- * in state CONN_OPEN. */
-
- /*
- * Count the number of bytes flushed out on this orconn, and the number of
- * bytes TLS actually sent - used for overhead estimation for scheduling.
- */
- uint64_t bytes_xmitted, bytes_xmitted_by_tls;
-} or_connection_t;
-
-/** Subtype of connection_t for an "edge connection" -- that is, an entry (ap)
- * connection, or an exit. */
-typedef struct edge_connection_t {
- connection_t base_;
-
- struct edge_connection_t *next_stream; /**< Points to the next stream at this
- * edge, if any */
- int package_window; /**< How many more relay cells can I send into the
- * circuit? */
- int deliver_window; /**< How many more relay cells can end at me? */
-
- struct circuit_t *on_circuit; /**< The circuit (if any) that this edge
- * connection is using. */
-
- /** A pointer to which node in the circ this conn exits at. Set for AP
- * connections and for hidden service exit connections. */
- struct crypt_path_t *cpath_layer;
- /** What rendezvous service are we querying for (if an AP) or providing (if
- * an exit)? */
- rend_data_t *rend_data;
-
- /* Hidden service connection identifier for edge connections. Used by the HS
- * client-side code to identify client SOCKS connections and by the
- * service-side code to match HS circuits with their streams. */
- struct hs_ident_edge_conn_t *hs_ident;
-
- uint32_t address_ttl; /**< TTL for address-to-addr mapping on exit
- * connection. Exit connections only. */
- uint32_t begincell_flags; /** Flags sent or received in the BEGIN cell
- * for this connection */
-
- streamid_t stream_id; /**< The stream ID used for this edge connection on its
- * circuit */
-
- /** The reason why this connection is closing; passed to the controller. */
- uint16_t end_reason;
-
- /** Bytes read since last call to control_event_stream_bandwidth_used() */
- uint32_t n_read;
-
- /** Bytes written since last call to control_event_stream_bandwidth_used() */
- uint32_t n_written;
-
- /** True iff this connection is for a DNS request only. */
- unsigned int is_dns_request:1;
- /** True iff this connection is for a PTR DNS request. (exit only) */
- unsigned int is_reverse_dns_lookup:1;
-
- unsigned int edge_has_sent_end:1; /**< For debugging; only used on edge
- * connections. Set once we've set the stream end,
- * and check in connection_about_to_close_connection().
- */
- /** True iff we've blocked reading until the circuit has fewer queued
- * cells. */
- unsigned int edge_blocked_on_circ:1;
-
- /** Unique ID for directory requests; this used to be in connection_t, but
- * that's going away and being used on channels instead. We still tag
- * edge connections with dirreq_id from circuits, so it's copied here. */
- uint64_t dirreq_id;
-} edge_connection_t;
-
-/** Subtype of edge_connection_t for an "entry connection" -- that is, a SOCKS
- * connection, a DNS request, a TransPort connection or a NATD connection */
-typedef struct entry_connection_t {
- edge_connection_t edge_;
-
- /** Nickname of planned exit node -- used with .exit support. */
- /* XXX prop220: we need to make chosen_exit_name able to encode Ed IDs too.
- * That's logically part of the UI parts for prop220 though. */
- char *chosen_exit_name;
-
- socks_request_t *socks_request; /**< SOCKS structure describing request (AP
- * only.) */
-
- /* === Isolation related, AP only. === */
- entry_port_cfg_t entry_cfg;
- /** AP only: The newnym epoch in which we created this connection. */
- unsigned nym_epoch;
-
- /** AP only: The original requested address before we rewrote it. */
- char *original_dest_address;
- /* Other fields to isolate on already exist. The ClientAddr is addr. The
- ClientProtocol is a combination of type and socks_request->
- socks_version. SocksAuth is socks_request->username/password.
- DestAddr is in socks_request->address. */
-
- /** Number of times we've reassigned this application connection to
- * a new circuit. We keep track because the timeout is longer if we've
- * already retried several times. */
- uint8_t num_socks_retries;
-
- /** For AP connections only: buffer for data that we have sent
- * optimistically, which we might need to re-send if we have to
- * retry this connection. */
- struct buf_t *pending_optimistic_data;
- /* For AP connections only: buffer for data that we previously sent
- * optimistically which we are currently re-sending as we retry this
- * connection. */
- struct buf_t *sending_optimistic_data;
-
- /** If this is a DNSPort connection, this field holds the pending DNS
- * request that we're going to try to answer. */
- struct evdns_server_request *dns_server_request;
-
-#define DEBUGGING_17659
-
-#ifdef DEBUGGING_17659
- uint16_t marked_pending_circ_line;
- const char *marked_pending_circ_file;
-#endif
-
-#define NUM_CIRCUITS_LAUNCHED_THRESHOLD 10
- /** Number of times we've launched a circuit to handle this stream. If
- * it gets too high, that could indicate an inconsistency between our
- * "launch a circuit to handle this stream" logic and our "attach our
- * stream to one of the available circuits" logic. */
- unsigned int num_circuits_launched:4;
-
- /** True iff this stream must attach to a one-hop circuit (e.g. for
- * begin_dir). */
- unsigned int want_onehop:1;
- /** True iff this stream should use a BEGIN_DIR relay command to establish
- * itself rather than BEGIN (either via onehop or via a whole circuit). */
- unsigned int use_begindir:1;
-
- /** For AP connections only. If 1, and we fail to reach the chosen exit,
- * stop requiring it. */
- unsigned int chosen_exit_optional:1;
- /** For AP connections only. If non-zero, this exit node was picked as
- * a result of the TrackHostExit, and the value decrements every time
- * we fail to complete a circuit to our chosen exit -- if it reaches
- * zero, abandon the associated mapaddress. */
- unsigned int chosen_exit_retries:3;
-
- /** True iff this is an AP connection that came from a transparent or
- * NATd connection */
- unsigned int is_transparent_ap:1;
-
- /** For AP connections only: Set if this connection's target exit node
- * allows optimistic data (that is, data sent on this stream before
- * the exit has sent a CONNECTED cell) and we have chosen to use it.
- */
- unsigned int may_use_optimistic_data : 1;
-} entry_connection_t;
-
-/** Subtype of connection_t for an "directory connection" -- that is, an HTTP
- * connection to retrieve or serve directory material. */
-typedef struct dir_connection_t {
- connection_t base_;
-
- /** Which 'resource' did we ask the directory for? This is typically the part
- * of the URL string that defines, relative to the directory conn purpose,
- * what thing we want. For example, in router descriptor downloads by
- * descriptor digest, it contains "d/", then one or more +-separated
- * fingerprints.
- **/
- char *requested_resource;
- unsigned int dirconn_direct:1; /**< Is this dirconn direct, or via Tor? */
-
- /** If we're fetching descriptors, what router purpose shall we assign
- * to them? */
- uint8_t router_purpose;
-
- /** List of spooled_resource_t for objects that we're spooling. We use
- * it from back to front. */
- smartlist_t *spool;
- /** The compression object doing on-the-fly compression for spooled data. */
- tor_compress_state_t *compress_state;
-
- /** What rendezvous service are we querying for? */
- rend_data_t *rend_data;
-
- /* Hidden service connection identifier for dir connections: Used by HS
- client-side code to fetch HS descriptors, and by the service-side code to
- upload descriptors. */
- struct hs_ident_dir_conn_t *hs_ident;
-
- /** If this is a one-hop connection, tracks the state of the directory guard
- * for this connection (if any). */
- struct circuit_guard_state_t *guard_state;
-
- char identity_digest[DIGEST_LEN]; /**< Hash of the public RSA key for
- * the directory server's signing key. */
-
- /** Unique ID for directory requests; this used to be in connection_t, but
- * that's going away and being used on channels instead. The dirserver still
- * needs this for the incoming side, so it's moved here. */
- uint64_t dirreq_id;
-
-#ifdef MEASUREMENTS_21206
- /** Number of RELAY_DATA cells received. */
- uint32_t data_cells_received;
-
- /** Number of RELAY_DATA cells sent. */
- uint32_t data_cells_sent;
-#endif /* defined(MEASUREMENTS_21206) */
-} dir_connection_t;
-
-/** Subtype of connection_t for an connection to a controller. */
-typedef struct control_connection_t {
- connection_t base_;
-
- uint64_t event_mask; /**< Bitfield: which events does this controller
- * care about?
- * EVENT_MAX_ is >31, so we need a 64 bit mask */
-
- /** True if we have sent a protocolinfo reply on this connection. */
- unsigned int have_sent_protocolinfo:1;
- /** True if we have received a takeownership command on this
- * connection. */
- unsigned int is_owning_control_connection:1;
-
- /** List of ephemeral onion services belonging to this connection. */
- smartlist_t *ephemeral_onion_services;
-
- /** If we have sent an AUTHCHALLENGE reply on this connection and
- * have not received a successful AUTHENTICATE command, points to
- * the value which the client must send to authenticate itself;
- * otherwise, NULL. */
- char *safecookie_client_hash;
-
- /** Amount of space allocated in incoming_cmd. */
- uint32_t incoming_cmd_len;
- /** Number of bytes currently stored in incoming_cmd. */
- uint32_t incoming_cmd_cur_len;
- /** A control command that we're reading from the inbuf, but which has not
- * yet arrived completely. */
- char *incoming_cmd;
-} control_connection_t;
-
-/** Cast a connection_t subtype pointer to a connection_t **/
-#define TO_CONN(c) (&(((c)->base_)))
-
-/** Cast a entry_connection_t subtype pointer to a edge_connection_t **/
-#define ENTRY_TO_EDGE_CONN(c) (&(((c))->edge_))
-/** Cast a entry_connection_t subtype pointer to a connection_t **/
-#define ENTRY_TO_CONN(c) (TO_CONN(ENTRY_TO_EDGE_CONN(c)))
-
-/** Convert a connection_t* to an or_connection_t*; assert if the cast is
- * invalid. */
-static or_connection_t *TO_OR_CONN(connection_t *);
-/** Convert a connection_t* to a dir_connection_t*; assert if the cast is
- * invalid. */
-static dir_connection_t *TO_DIR_CONN(connection_t *);
-/** Convert a connection_t* to an edge_connection_t*; assert if the cast is
- * invalid. */
-static edge_connection_t *TO_EDGE_CONN(connection_t *);
-/** Convert a connection_t* to an entry_connection_t*; assert if the cast is
- * invalid. */
-static entry_connection_t *TO_ENTRY_CONN(connection_t *);
-/** Convert a edge_connection_t* to an entry_connection_t*; assert if the cast
- * is invalid. */
-static entry_connection_t *EDGE_TO_ENTRY_CONN(edge_connection_t *);
-/** Convert a connection_t* to an control_connection_t*; assert if the cast is
- * invalid. */
-static control_connection_t *TO_CONTROL_CONN(connection_t *);
-/** Convert a connection_t* to an listener_connection_t*; assert if the cast is
- * invalid. */
-static listener_connection_t *TO_LISTENER_CONN(connection_t *);
-
-static inline or_connection_t *TO_OR_CONN(connection_t *c)
-{
- tor_assert(c->magic == OR_CONNECTION_MAGIC);
- return DOWNCAST(or_connection_t, c);
-}
-static inline dir_connection_t *TO_DIR_CONN(connection_t *c)
-{
- tor_assert(c->magic == DIR_CONNECTION_MAGIC);
- return DOWNCAST(dir_connection_t, c);
-}
-static inline edge_connection_t *TO_EDGE_CONN(connection_t *c)
-{
- tor_assert(c->magic == EDGE_CONNECTION_MAGIC ||
- c->magic == ENTRY_CONNECTION_MAGIC);
- return DOWNCAST(edge_connection_t, c);
-}
-static inline entry_connection_t *TO_ENTRY_CONN(connection_t *c)
-{
- tor_assert(c->magic == ENTRY_CONNECTION_MAGIC);
- return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, edge_.base_);
-}
-static inline entry_connection_t *EDGE_TO_ENTRY_CONN(edge_connection_t *c)
-{
- tor_assert(c->base_.magic == ENTRY_CONNECTION_MAGIC);
- return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, edge_);
-}
-static inline control_connection_t *TO_CONTROL_CONN(connection_t *c)
-{
- tor_assert(c->magic == CONTROL_CONNECTION_MAGIC);
- return DOWNCAST(control_connection_t, c);
-}
-static inline listener_connection_t *TO_LISTENER_CONN(connection_t *c)
-{
- tor_assert(c->magic == LISTENER_CONNECTION_MAGIC);
- return DOWNCAST(listener_connection_t, c);
-}
-
-/** What action type does an address policy indicate: accept or reject? */
-typedef enum {
- ADDR_POLICY_ACCEPT=1,
- ADDR_POLICY_REJECT=2,
-} addr_policy_action_t;
-#define addr_policy_action_bitfield_t ENUM_BF(addr_policy_action_t)
-
-/** A reference-counted address policy rule. */
-typedef struct addr_policy_t {
- int refcnt; /**< Reference count */
- /** What to do when the policy matches.*/
- addr_policy_action_bitfield_t policy_type:2;
- unsigned int is_private:1; /**< True iff this is the pseudo-address,
- * "private". */
- unsigned int is_canonical:1; /**< True iff this policy is the canonical
- * copy (stored in a hash table to avoid
- * duplication of common policies) */
- maskbits_t maskbits; /**< Accept/reject all addresses <b>a</b> such that the
- * first <b>maskbits</b> bits of <b>a</b> match
- * <b>addr</b>. */
- /** Base address to accept or reject.
- *
- * Note that wildcards are treated
- * differntly depending on address family. An AF_UNSPEC address means
- * "All addresses, IPv4 or IPv6." An AF_INET address with maskbits==0 means
- * "All IPv4 addresses" and an AF_INET6 address with maskbits == 0 means
- * "All IPv6 addresses".
- **/
- tor_addr_t addr;
- uint16_t prt_min; /**< Lowest port number to accept/reject. */
- uint16_t prt_max; /**< Highest port number to accept/reject. */
-} addr_policy_t;
-
-/** A cached_dir_t represents a cacheable directory object, along with its
- * compressed form. */
-typedef struct cached_dir_t {
- char *dir; /**< Contents of this object, NUL-terminated. */
- char *dir_compressed; /**< Compressed contents of this object. */
- size_t dir_len; /**< Length of <b>dir</b> (not counting its NUL). */
- size_t dir_compressed_len; /**< Length of <b>dir_compressed</b>. */
- time_t published; /**< When was this object published. */
- common_digests_t digests; /**< Digests of this object (networkstatus only) */
- /** Sha3 digest (also ns only) */
- uint8_t digest_sha3_as_signed[DIGEST256_LEN];
- int refcnt; /**< Reference count for this cached_dir_t. */
-} cached_dir_t;
-
-/** Enum used to remember where a signed_descriptor_t is stored and how to
- * manage the memory for signed_descriptor_body. */
-typedef enum {
- /** The descriptor isn't stored on disk at all: the copy in memory is
- * canonical; the saved_offset field is meaningless. */
- SAVED_NOWHERE=0,
- /** The descriptor is stored in the cached_routers file: the
- * signed_descriptor_body is meaningless; the signed_descriptor_len and
- * saved_offset are used to index into the mmaped cache file. */
- SAVED_IN_CACHE,
- /** The descriptor is stored in the cached_routers.new file: the
- * signed_descriptor_body and saved_offset fields are both set. */
- /* FFFF (We could also mmap the file and grow the mmap as needed, or
- * lazy-load the descriptor text by using seek and read. We don't, for
- * now.)
- */
- SAVED_IN_JOURNAL
-} saved_location_t;
-#define saved_location_bitfield_t ENUM_BF(saved_location_t)
-
-/** Enumeration: what directory object is being downloaded?
- * This determines which schedule is selected to perform the download. */
-typedef enum {
- DL_SCHED_GENERIC = 0,
- DL_SCHED_CONSENSUS = 1,
- DL_SCHED_BRIDGE = 2,
-} download_schedule_t;
-#define download_schedule_bitfield_t ENUM_BF(download_schedule_t)
-
-/** Enumeration: is the download schedule for downloading from an authority,
- * or from any available directory mirror?
- * During bootstrap, "any" means a fallback (or an authority, if there
- * are no fallbacks).
- * When we have a valid consensus, "any" means any directory server. */
-typedef enum {
- DL_WANT_ANY_DIRSERVER = 0,
- DL_WANT_AUTHORITY = 1,
-} download_want_authority_t;
-#define download_want_authority_bitfield_t \
- ENUM_BF(download_want_authority_t)
-
-/** Enumeration: do we want to increment the schedule position each time a
- * connection is attempted (these attempts can be concurrent), or do we want
- * to increment the schedule position after a connection fails? */
-typedef enum {
- DL_SCHED_INCREMENT_FAILURE = 0,
- DL_SCHED_INCREMENT_ATTEMPT = 1,
-} download_schedule_increment_t;
-#define download_schedule_increment_bitfield_t \
- ENUM_BF(download_schedule_increment_t)
-
-/** Information about our plans for retrying downloads for a downloadable
- * directory object.
- * Each type of downloadable directory object has a corresponding retry
- * <b>schedule</b>, which can be different depending on whether the object is
- * being downloaded from an authority or a mirror (<b>want_authority</b>).
- * <b>next_attempt_at</b> contains the next time we will attempt to download
- * the object.
- * For schedules that <b>increment_on</b> failure, <b>n_download_failures</b>
- * is used to determine the position in the schedule. (Each schedule is a
- * smartlist of integer delays, parsed from a CSV option.) Every time a
- * connection attempt fails, <b>n_download_failures</b> is incremented,
- * the new delay value is looked up from the schedule, and
- * <b>next_attempt_at</b> is set delay seconds from the time the previous
- * connection failed. Therefore, at most one failure-based connection can be
- * in progress for each download_status_t.
- * For schedules that <b>increment_on</b> attempt, <b>n_download_attempts</b>
- * is used to determine the position in the schedule. Every time a
- * connection attempt is made, <b>n_download_attempts</b> is incremented,
- * the new delay value is looked up from the schedule, and
- * <b>next_attempt_at</b> is set delay seconds from the time the previous
- * connection was attempted. Therefore, multiple concurrent attempted-based
- * connections can be in progress for each download_status_t.
- * After an object is successfully downloaded, any other concurrent connections
- * are terminated. A new schedule which starts at position 0 is used for
- * subsequent downloads of the same object.
- */
-typedef struct download_status_t {
- time_t next_attempt_at; /**< When should we try downloading this object
- * again? */
- uint8_t n_download_failures; /**< Number of failed downloads of the most
- * recent object, since the last success. */
- uint8_t n_download_attempts; /**< Number of (potentially concurrent) attempts
- * to download the most recent object, since
- * the last success. */
- download_schedule_bitfield_t schedule : 8; /**< What kind of object is being
- * downloaded? This determines the
- * schedule used for the download.
- */
- download_want_authority_bitfield_t want_authority : 1; /**< Is the download
- * happening from an authority
- * or a mirror? This determines
- * the schedule used for the
- * download. */
- download_schedule_increment_bitfield_t increment_on : 1; /**< does this
- * schedule increment on each attempt,
- * or after each failure? */
- uint8_t last_backoff_position; /**< number of attempts/failures, depending
- * on increment_on, when we last recalculated
- * the delay. Only updated if backoff
- * == 1. */
- int last_delay_used; /**< last delay used for random exponential backoff;
- * only updated if backoff == 1 */
-} download_status_t;
-
-/** If n_download_failures is this high, the download can never happen. */
-#define IMPOSSIBLE_TO_DOWNLOAD 255
-
-/** The max size we expect router descriptor annotations we create to
- * be. We'll accept larger ones if we see them on disk, but we won't
- * create any that are larger than this. */
-#define ROUTER_ANNOTATION_BUF_LEN 256
-
-/** Information need to cache an onion router's descriptor. */
-typedef struct signed_descriptor_t {
- /** Pointer to the raw server descriptor, preceded by annotations. Not
- * necessarily NUL-terminated. If saved_location is SAVED_IN_CACHE, this
- * pointer is null. */
- char *signed_descriptor_body;
- /** Length of the annotations preceding the server descriptor. */
- size_t annotations_len;
- /** Length of the server descriptor. */
- size_t signed_descriptor_len;
- /** Digest of the server descriptor, computed as specified in
- * dir-spec.txt. */
- char signed_descriptor_digest[DIGEST_LEN];
- /** Identity digest of the router. */
- char identity_digest[DIGEST_LEN];
- /** Declared publication time of the descriptor. */
- time_t published_on;
- /** For routerdescs only: digest of the corresponding extrainfo. */
- char extra_info_digest[DIGEST_LEN];
- /** For routerdescs only: A SHA256-digest of the extrainfo (if any) */
- char extra_info_digest256[DIGEST256_LEN];
- /** Certificate for ed25519 signing key. */
- struct tor_cert_st *signing_key_cert;
- /** For routerdescs only: Status of downloading the corresponding
- * extrainfo. */
- download_status_t ei_dl_status;
- /** Where is the descriptor saved? */
- saved_location_t saved_location;
- /** If saved_location is SAVED_IN_CACHE or SAVED_IN_JOURNAL, the offset of
- * this descriptor in the corresponding file. */
- off_t saved_offset;
- /** What position is this descriptor within routerlist->routers or
- * routerlist->old_routers? -1 for none. */
- int routerlist_index;
- /** The valid-until time of the most recent consensus that listed this
- * descriptor. 0 for "never listed in a consensus, so far as we know." */
- time_t last_listed_as_valid_until;
- /* If true, we do not ever try to save this object in the cache. */
- unsigned int do_not_cache : 1;
- /* If true, this item is meant to represent an extrainfo. */
- unsigned int is_extrainfo : 1;
- /* If true, we got an extrainfo for this item, and the digest was right,
- * but it was incompatible. */
- unsigned int extrainfo_is_bogus : 1;
- /* If true, we are willing to transmit this item unencrypted. */
- unsigned int send_unencrypted : 1;
-} signed_descriptor_t;
-
-/** A signed integer representing a country code. */
-typedef int16_t country_t;
-
-/** Flags used to summarize the declared protocol versions of a relay,
- * so we don't need to parse them again and again. */
-typedef struct protover_summary_flags_t {
- /** True iff we have a proto line for this router, or a versions line
- * from which we could infer the protocols. */
- unsigned int protocols_known:1;
-
- /** True iff this router has a version or protocol list that allows it to
- * accept EXTEND2 cells. This requires Relay=2. */
- unsigned int supports_extend2_cells: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. */
- unsigned int supports_ed25519_link_handshake_compat:1;
-
- /** True iff this router has a protocol list that allows it to negotiate
- * ed25519 identity keys on a link handshake, at all. This requires some
- * LinkAuth=X for X >= 3. */
- unsigned int supports_ed25519_link_handshake_any:1;
-
- /** True iff this router has a protocol list that allows it to be an
- * introduction point supporting ed25519 authentication key which is part of
- * 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 be an hidden
- * service directory supporting version 3 as seen in proposal 224. This
- * requires HSDir=2. */
- unsigned int supports_v3_hsdir : 1;
-
- /** True iff this router has a protocol list that allows it to be an hidden
- * service rendezvous point supporting version 3 as seen in proposal 224.
- * This requires HSRend=2. */
- unsigned int supports_v3_rendezvous_point: 1;
-} protover_summary_flags_t;
-
-/** Information about another onion router in the network. */
-typedef struct {
- 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 IPv6 address, if it has one. */
- /* XXXXX187 Actually these should probably be part of a list of addresses,
- * not just a special case. Use abstractions to access these; don't do it
- * directly. */
- tor_addr_t ipv6_addr;
- uint16_t ipv6_orport;
-
- crypto_pk_t *onion_pkey; /**< Public RSA key for onions. */
- crypto_pk_t *identity_pkey; /**< Public RSA key for signing. */
- /** Public curve25519 key for onions */
- curve25519_public_key_t *onion_curve25519_pkey;
- /** What's the earliest expiration time on all the certs in this
- * routerinfo? */
- time_t cert_expiration_time;
-
- char *platform; /**< What software/operating system is this OR using? */
-
- char *protocol_list; /**< Encoded list of subprotocol versions supported
- * by this OR */
-
- /* link info */
- uint32_t bandwidthrate; /**< How many bytes does this OR add to its token
- * bucket per second? */
- uint32_t bandwidthburst; /**< How large is this OR's token bucket? */
- /** How many bytes/s is this router known to handle? */
- uint32_t bandwidthcapacity;
- smartlist_t *exit_policy; /**< What streams will this OR permit
- * to exit on IPv4? NULL for 'reject *:*'. */
- /** What streams will this OR permit to exit on IPv6?
- * NULL for 'reject *:*' */
- struct short_policy_t *ipv6_exit_policy;
- long uptime; /**< How many seconds the router claims to have been up */
- smartlist_t *declared_family; /**< Nicknames of router which this router
- * claims are its family. */
- char *contact_info; /**< Declared contact info for this router. */
- unsigned int is_hibernating:1; /**< Whether the router claims to be
- * hibernating */
- unsigned int caches_extra_info:1; /**< Whether the router says it caches and
- * serves extrainfo documents. */
- unsigned int allow_single_hop_exits:1; /**< Whether the router says
- * it allows single hop exits. */
-
- unsigned int wants_to_be_hs_dir:1; /**< True iff this router claims to be
- * a hidden service directory. */
- unsigned int policy_is_reject_star:1; /**< True iff the exit policy for this
- * router rejects everything. */
- /** True if, after we have added this router, we should re-launch
- * tests for it. */
- unsigned int needs_retest_if_added:1;
-
- /** True iff this router included "tunnelled-dir-server" in its descriptor,
- * implying it accepts tunnelled directory requests, or it advertised
- * dir_port > 0. */
- unsigned int supports_tunnelled_dir_requests:1;
-
- /** Used during voting to indicate that we should not include an entry for
- * this routerinfo. Used only during voting. */
- unsigned int omit_from_vote:1;
-
- /** Flags to summarize the protocol versions for this routerinfo_t. */
- protover_summary_flags_t pv;
-
-/** Tor can use this router for general positions in circuits; we got it
- * from a directory server as usual, or we're an authority and a server
- * uploaded it. */
-#define ROUTER_PURPOSE_GENERAL 0
-/** Tor should avoid using this router for circuit-building: we got it
- * from a controller. If the controller wants to use it, it'll have to
- * ask for it by identity. */
-#define ROUTER_PURPOSE_CONTROLLER 1
-/** Tor should use this router only for bridge positions in circuits: we got
- * it via a directory request from the bridge itself, or a bridge
- * authority. */
-#define ROUTER_PURPOSE_BRIDGE 2
-/** Tor should not use this router; it was marked in cached-descriptors with
- * a purpose we didn't recognize. */
-#define ROUTER_PURPOSE_UNKNOWN 255
-
- /** In what way did we find out about this router? One of ROUTER_PURPOSE_*.
- * Routers of different purposes are kept segregated and used for different
- * things; see notes on ROUTER_PURPOSE_* macros above.
- */
- uint8_t purpose;
-} routerinfo_t;
-
-/** Information needed to keep and cache a signed extra-info document. */
-typedef struct extrainfo_t {
- signed_descriptor_t cache_info;
- /** SHA256 digest of this document */
- uint8_t digest256[DIGEST256_LEN];
- /** The router's nickname. */
- char nickname[MAX_NICKNAME_LEN+1];
- /** True iff we found the right key for this extra-info, verified the
- * signature, and found it to be bad. */
- unsigned int bad_sig : 1;
- /** If present, we didn't have the right key to verify this extra-info,
- * so this is a copy of the signature in the document. */
- char *pending_sig;
- /** Length of pending_sig. */
- size_t pending_sig_len;
-} extrainfo_t;
-
-/** Contents of a single router entry in a network status object.
- */
-typedef struct routerstatus_t {
- time_t published_on; /**< When was this router published? */
- char nickname[MAX_NICKNAME_LEN+1]; /**< The nickname this router says it
- * has. */
- char identity_digest[DIGEST_LEN]; /**< Digest of the router's identity
- * key. */
- /** 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 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. */
- unsigned int is_exit:1; /**< True iff this router is a good exit. */
- unsigned int is_stable:1; /**< True iff this router stays up a long time. */
- unsigned int is_fast:1; /**< True iff this router has good bandwidth. */
- /** True iff this router is called 'running' in the consensus. We give it
- * this funny name so that we don't accidentally use this bit as a view of
- * whether we think the router is *currently* running. If that's what you
- * want to know, look at is_running in node_t. */
- unsigned int is_flagged_running:1;
- unsigned int is_named:1; /**< True iff "nickname" belongs to this router. */
- unsigned int is_unnamed:1; /**< True iff "nickname" belongs to another
- * router. */
- unsigned int is_valid:1; /**< True iff this router isn't invalid. */
- unsigned int is_possible_guard:1; /**< True iff this router would be a good
- * choice as an entry guard. */
- unsigned int is_bad_exit:1; /**< True iff this node is a bad choice for
- * an exit node. */
- unsigned int is_hs_dir:1; /**< True iff this router is a v2-or-later hidden
- * service directory. */
- unsigned int is_v2_dir:1; /** True iff this router publishes an open DirPort
- * or it claims to accept tunnelled dir requests.
- */
-
- unsigned int has_bandwidth:1; /**< The vote/consensus had bw info */
- unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */
- unsigned int bw_is_unmeasured:1; /**< This is a consensus entry, with
- * the Unmeasured flag set. */
-
- /** Flags to summarize the protocol versions for this routerstatus_t. */
- protover_summary_flags_t pv;
-
- uint32_t bandwidth_kb; /**< Bandwidth (capacity) of the router as reported in
- * the vote/consensus, in kilobytes/sec. */
-
- /** The consensus has guardfraction information for this router. */
- unsigned int has_guardfraction:1;
- /** The guardfraction value of this router. */
- uint32_t guardfraction_percentage;
-
- char *exitsummary; /**< exit policy summary -
- * XXX weasel: this probably should not stay a string. */
-
- /* ---- The fields below aren't derived from the networkstatus; they
- * hold local information only. */
-
- time_t last_dir_503_at; /**< When did this router last tell us that it
- * was too busy to serve directory info? */
- download_status_t dl_status;
-
-} routerstatus_t;
-
-/** A single entry in a parsed policy summary, describing a range of ports. */
-typedef struct short_policy_entry_t {
- uint16_t min_port, max_port;
-} short_policy_entry_t;
-
-/** A short_poliy_t is the parsed version of a policy summary. */
-typedef struct short_policy_t {
- /** True if the members of 'entries' are port ranges to accept; false if
- * they are port ranges to reject */
- unsigned int is_accept : 1;
- /** The actual number of values in 'entries'. */
- unsigned int n_entries : 31;
- /** An array of 0 or more short_policy_entry_t values, each describing a
- * range of ports that this policy accepts or rejects (depending on the
- * value of is_accept).
- */
- short_policy_entry_t entries[FLEXIBLE_ARRAY_MEMBER];
-} short_policy_t;
-
-/** A microdescriptor is the smallest amount of information needed to build a
- * circuit through a router. They are generated by the directory authorities,
- * using information from the uploaded routerinfo documents. They are not
- * self-signed, but are rather authenticated by having their hash in a signed
- * networkstatus document. */
-typedef struct microdesc_t {
- /** Hashtable node, used to look up the microdesc by its digest. */
- HT_ENTRY(microdesc_t) node;
-
- /* Cache information */
-
- /** When was this microdescriptor last listed in a consensus document?
- * Once a microdesc has been unlisted long enough, we can drop it.
- */
- time_t last_listed;
- /** Where is this microdescriptor currently stored? */
- saved_location_bitfield_t saved_location : 3;
- /** If true, do not attempt to cache this microdescriptor on disk. */
- unsigned int no_save : 1;
- /** If true, this microdesc has an entry in the microdesc_map */
- unsigned int held_in_map : 1;
- /** Reference count: how many node_ts have a reference to this microdesc? */
- unsigned int held_by_nodes;
-
- /** If saved_location == SAVED_IN_CACHE, this field holds the offset of the
- * microdescriptor in the cache. */
- off_t off;
-
- /* The string containing the microdesc. */
-
- /** A pointer to the encoded body of the microdescriptor. If the
- * saved_location is SAVED_IN_CACHE, then the body is a pointer into an
- * mmap'd region. Otherwise, it is a malloc'd string. The string might not
- * be NUL-terminated; take the length from <b>bodylen</b>. */
- char *body;
- /** The length of the microdescriptor in <b>body</b>. */
- size_t bodylen;
- /** A SHA256-digest of the microdescriptor. */
- char digest[DIGEST256_LEN];
-
- /* Fields in the microdescriptor. */
-
- /** As routerinfo_t.onion_pkey */
- crypto_pk_t *onion_pkey;
- /** As routerinfo_t.onion_curve25519_pkey */
- curve25519_public_key_t *onion_curve25519_pkey;
- /** Ed25519 identity key, if included. */
- ed25519_public_key_t *ed25519_identity_pkey;
- /** As routerinfo_t.ipv6_addr */
- tor_addr_t ipv6_addr;
- /** As routerinfo_t.ipv6_orport */
- uint16_t ipv6_orport;
- /** As routerinfo_t.family */
- smartlist_t *family;
- /** IPv4 exit policy summary */
- short_policy_t *exit_policy;
- /** IPv6 exit policy summary */
- short_policy_t *ipv6_exit_policy;
-
-} microdesc_t;
-
-/** A node_t represents a Tor router.
- *
- * Specifically, a node_t is a Tor router as we are using it: a router that
- * we are considering for circuits, connections, and so on. A node_t is a
- * thin wrapper around the routerstatus, routerinfo, and microdesc for a
- * single router, and provides a consistent interface for all of them.
- *
- * Also, a node_t has mutable state. While a routerinfo, a routerstatus,
- * and a microdesc have[*] only the information read from a router
- * descriptor, a consensus entry, and a microdescriptor (respectively)...
- * a node_t has flags based on *our own current opinion* of the node.
- *
- * [*] Actually, there is some leftover information in each that is mutable.
- * We should try to excise that.
- */
-typedef struct node_t {
- /* Indexing information */
-
- /** Used to look up the node_t by its identity digest. */
- HT_ENTRY(node_t) ht_ent;
- /** Used to look up the node_t by its ed25519 identity digest. */
- HT_ENTRY(node_t) ed_ht_ent;
- /** Position of the node within the list of nodes */
- int nodelist_idx;
-
- /** The identity digest of this node_t. No more than one node_t per
- * identity may exist at a time. */
- char identity[DIGEST_LEN];
-
- /** The ed25519 identity of this node_t. This field is nonzero iff we
- * currently have an ed25519 identity for this node in either md or ri,
- * _and_ this node has been inserted to the ed25519-to-node map in the
- * nodelist.
- */
- ed25519_public_key_t ed25519_id;
-
- microdesc_t *md;
- routerinfo_t *ri;
- routerstatus_t *rs;
-
- /* local info: copied from routerstatus, then possibly frobbed based
- * on experience. Authorities set this stuff directly. Note that
- * these reflect knowledge of the primary (IPv4) OR port only. */
-
- unsigned int is_running:1; /**< As far as we know, is this OR currently
- * running? */
- unsigned int is_valid:1; /**< Has a trusted dirserver validated this OR?
- * (For Authdir: Have we validated this OR?) */
- unsigned int is_fast:1; /** Do we think this is a fast OR? */
- unsigned int is_stable:1; /** Do we think this is a stable OR? */
- unsigned int is_possible_guard:1; /**< Do we think this is an OK guard? */
- unsigned int is_exit:1; /**< Do we think this is an OK exit? */
- unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked,
- * or otherwise nasty? */
- unsigned int is_hs_dir:1; /**< True iff this router is a hidden service
- * directory according to the authorities. */
-
- /* Local info: warning state. */
-
- unsigned int name_lookup_warned:1; /**< Have we warned the user for referring
- * to this (unnamed) router by nickname?
- */
-
- /** Local info: we treat this node as if it rejects everything */
- unsigned int rejects_all:1;
-
- /* 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? */
- 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? */
- country_t country;
-
- /* The below items are used only by authdirservers for
- * reachability testing. */
-
- /** When was the last time we could reach this OR? */
- time_t last_reachable; /* IPv4. */
- time_t last_reachable6; /* IPv6. */
-
- /* Hidden service directory index data. This is used by a service or client
- * in order to know what's the hs directory index for this node at the time
- * the consensus is set. */
- struct hsdir_index_t hsdir_index;
-} node_t;
-
-/** Linked list of microdesc hash lines for a single router in a directory
- * vote.
- */
-typedef struct vote_microdesc_hash_t {
- /** Next element in the list, or NULL. */
- struct vote_microdesc_hash_t *next;
- /** The raw contents of the microdesc hash line, from the "m" through the
- * newline. */
- char *microdesc_hash_line;
-} vote_microdesc_hash_t;
-
-/** The claim about a single router, made in a vote. */
-typedef struct vote_routerstatus_t {
- routerstatus_t status; /**< Underlying 'status' object for this router.
- * Flags are redundant. */
- /** How many known-flags are allowed in a vote? This is the width of
- * the flags field of vote_routerstatus_t */
-#define MAX_KNOWN_FLAGS_IN_VOTE 64
- uint64_t flags; /**< Bit-field for all recognized flags; index into
- * networkstatus_t.known_flags. */
- char *version; /**< The version that the authority says this router is
- * running. */
- char *protocols; /**< The protocols that this authority says this router
- * provides. */
- unsigned int has_measured_bw:1; /**< The vote had a measured bw */
- /** True iff the vote included an entry for ed25519 ID, or included
- * "id ed25519 none" to indicate that there was no ed25519 ID. */
- unsigned int has_ed25519_listing:1;
- /** True if the Ed25519 listing here is the consensus-opinion for the
- * Ed25519 listing; false if there was no consensus on Ed25519 key status,
- * or if this VRS doesn't reflect it. */
- unsigned int ed25519_reflects_consensus:1;
- uint32_t measured_bw_kb; /**< Measured bandwidth (capacity) of the router */
- /** The hash or hashes that the authority claims this microdesc has. */
- vote_microdesc_hash_t *microdesc;
- /** Ed25519 identity for this router, or zero if it has none. */
- uint8_t ed25519_id[ED25519_PUBKEY_LEN];
-} vote_routerstatus_t;
-
-/** A signature of some document by an authority. */
-typedef struct document_signature_t {
- /** Declared SHA-1 digest of this voter's identity key */
- char identity_digest[DIGEST_LEN];
- /** Declared SHA-1 digest of signing key used by this voter. */
- char signing_key_digest[DIGEST_LEN];
- /** Algorithm used to compute the digest of the document. */
- digest_algorithm_t alg;
- /** Signature of the signed thing. */
- char *signature;
- /** Length of <b>signature</b> */
- int signature_len;
- unsigned int bad_signature : 1; /**< Set to true if we've tried to verify
- * the sig, and we know it's bad. */
- unsigned int good_signature : 1; /**< Set to true if we've verified the sig
- * as good. */
-} document_signature_t;
-
-/** Information about a single voter in a vote or a consensus. */
-typedef struct networkstatus_voter_info_t {
- /** Declared SHA-1 digest of this voter's identity key */
- char identity_digest[DIGEST_LEN];
- char *nickname; /**< Nickname of this voter */
- /** Digest of this voter's "legacy" identity key, if any. In vote only; for
- * 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 */
- char *contact; /**< Contact information for this voter. */
- char vote_digest[DIGEST_LEN]; /**< Digest of this voter's vote, as signed. */
-
- /* Nothing from here on is signed. */
- /** The signature of the document and the signature's status. */
- smartlist_t *sigs;
-} networkstatus_voter_info_t;
-
-typedef struct networkstatus_sr_info_t {
- /* Indicate if the dirauth partitipates in the SR protocol with its vote.
- * This is tied to the SR flag in the vote. */
- unsigned int participate:1;
- /* Both vote and consensus: Current and previous SRV. If list is empty,
- * this means none were found in either the consensus or vote. */
- struct sr_srv_t *previous_srv;
- struct sr_srv_t *current_srv;
- /* Vote only: List of commitments. */
- smartlist_t *commits;
-} networkstatus_sr_info_t;
-
-/** Enumerates the possible seriousness values of a networkstatus document. */
-typedef enum {
- NS_TYPE_VOTE,
- NS_TYPE_CONSENSUS,
- NS_TYPE_OPINION,
-} networkstatus_type_t;
-
-/** Enumerates recognized flavors of a consensus networkstatus document. All
- * flavors of a consensus are generated from the same set of votes, but they
- * present different types information to different versions of Tor. */
-typedef enum {
- FLAV_NS = 0,
- FLAV_MICRODESC = 1,
-} consensus_flavor_t;
-
-/** How many different consensus flavors are there? */
-#define N_CONSENSUS_FLAVORS ((int)(FLAV_MICRODESC)+1)
-
-/** A common structure to hold a v3 network status vote, or a v3 network
- * status consensus. */
-typedef struct networkstatus_t {
- networkstatus_type_t type; /**< Vote, consensus, or opinion? */
- consensus_flavor_t flavor; /**< If a consensus, what kind? */
- unsigned int has_measured_bws : 1;/**< True iff this networkstatus contains
- * measured= bandwidth values. */
-
- time_t published; /**< Vote only: Time when vote was written. */
- time_t valid_after; /**< Time after which this vote or consensus applies. */
- time_t fresh_until; /**< Time before which this is the most recent vote or
- * consensus. */
- time_t valid_until; /**< Time after which this vote or consensus should not
- * be used. */
-
- /** Consensus only: what method was used to produce this consensus? */
- int consensus_method;
- /** Vote only: what methods is this voter willing to use? */
- smartlist_t *supported_methods;
-
- /** List of 'package' lines describing hashes of downloadable packages */
- smartlist_t *package_lines;
-
- /** How long does this vote/consensus claim that authorities take to
- * distribute their votes to one another? */
- int vote_seconds;
- /** How long does this vote/consensus claim that authorities take to
- * distribute their consensus signatures to one another? */
- int dist_seconds;
-
- /** Comma-separated list of recommended client software, or NULL if this
- * voter has no opinion. */
- char *client_versions;
- char *server_versions;
-
- /** Lists of subprotocol versions which are _recommended_ for relays and
- * clients, or which are _require_ for relays and clients. Tor shouldn't
- * make any more network connections if a required protocol is missing.
- */
- char *recommended_relay_protocols;
- char *recommended_client_protocols;
- char *required_relay_protocols;
- char *required_client_protocols;
-
- /** List of flags that this vote/consensus applies to routers. If a flag is
- * not listed here, the voter has no opinion on what its value should be. */
- smartlist_t *known_flags;
-
- /** List of key=value strings for the parameters in this vote or
- * consensus, sorted by key. */
- smartlist_t *net_params;
-
- /** List of key=value strings for the bw weight parameters in the
- * consensus. */
- smartlist_t *weight_params;
-
- /** List of networkstatus_voter_info_t. For a vote, only one element
- * is included. For a consensus, one element is included for every voter
- * whose vote contributed to the consensus. */
- smartlist_t *voters;
-
- struct authority_cert_t *cert; /**< Vote only: the voter's certificate. */
-
- /** Digests of this document, as signed. */
- common_digests_t digests;
- /** A SHA3-256 digest of the document, not including signatures: used for
- * consensus diffs */
- uint8_t digest_sha3_as_signed[DIGEST256_LEN];
-
- /** List of router statuses, sorted by identity digest. For a vote,
- * the elements are vote_routerstatus_t; for a consensus, the elements
- * are routerstatus_t. */
- smartlist_t *routerstatus_list;
-
- /** If present, a map from descriptor digest to elements of
- * routerstatus_list. */
- digestmap_t *desc_digest_map;
-
- /** Contains the shared random protocol data from a vote or consensus. */
- networkstatus_sr_info_t sr_info;
-} networkstatus_t;
-
-/** A set of signatures for a networkstatus consensus. Unless otherwise
- * noted, all fields are as for networkstatus_t. */
-typedef struct ns_detached_signatures_t {
- time_t valid_after;
- time_t fresh_until;
- time_t valid_until;
- strmap_t *digests; /**< Map from flavor name to digestset_t */
- strmap_t *signatures; /**< Map from flavor name to list of
- * document_signature_t */
-} ns_detached_signatures_t;
-
-/** Allowable types of desc_store_t. */
-typedef enum store_type_t {
- ROUTER_STORE = 0,
- EXTRAINFO_STORE = 1
-} store_type_t;
-
-/** A 'store' is a set of descriptors saved on disk, with accompanying
- * journal, mmaped as needed, rebuilt as needed. */
-typedef struct desc_store_t {
- /** Filename (within DataDir) for the store. We append .tmp to this
- * filename for a temporary file when rebuilding the store, and .new to this
- * filename for the journal. */
- const char *fname_base;
- /** Human-readable description of what this store contains. */
- const char *description;
-
- tor_mmap_t *mmap; /**< A mmap for the main file in the store. */
-
- store_type_t type; /**< What's stored in this store? */
-
- /** The size of the router log, in bytes. */
- size_t journal_len;
- /** The size of the router store, in bytes. */
- size_t store_len;
- /** Total bytes dropped since last rebuild: this is space currently
- * used in the cache and the journal that could be freed by a rebuild. */
- size_t bytes_dropped;
-} desc_store_t;
-
-/** Contents of a directory of onion routers. */
-typedef struct {
- /** Map from server identity digest to a member of routers. */
- struct digest_ri_map_t *identity_map;
- /** Map from server descriptor digest to a signed_descriptor_t from
- * routers or old_routers. */
- struct digest_sd_map_t *desc_digest_map;
- /** Map from extra-info digest to an extrainfo_t. Only exists for
- * routers in routers or old_routers. */
- struct digest_ei_map_t *extra_info_map;
- /** Map from extra-info digests to a signed_descriptor_t for a router
- * descriptor having that extra-info digest. Only exists for
- * routers in routers or old_routers. */
- struct digest_sd_map_t *desc_by_eid_map;
- /** List of routerinfo_t for all currently live routers we know. */
- smartlist_t *routers;
- /** List of signed_descriptor_t for older router descriptors we're
- * caching. */
- smartlist_t *old_routers;
- /** Store holding server descriptors. If present, any router whose
- * cache_info.saved_location == SAVED_IN_CACHE is stored in this file
- * starting at cache_info.saved_offset */
- desc_store_t desc_store;
- /** Store holding extra-info documents. */
- desc_store_t extrainfo_store;
-} routerlist_t;
-
-/** 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
- * general-purpose tunnels, the onion_key is NULL. */
-typedef struct extend_info_t {
- char nickname[MAX_HEX_NICKNAME_LEN+1]; /**< This router's nickname for
- * display. */
- /** Hash of this router's RSA identity key. */
- 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. */
- curve25519_public_key_t curve25519_onion_key;
-} extend_info_t;
-
-/** Certificate for v3 directory protocol: binds long-term authority identity
- * keys to medium-term authority signing keys. */
-typedef struct authority_cert_t {
- /** Information relating to caching this cert on disk and looking it up. */
- signed_descriptor_t cache_info;
- /** This authority's long-term authority identity key. */
- crypto_pk_t *identity_key;
- /** This authority's medium-term signing key. */
- crypto_pk_t *signing_key;
- /** The digest of <b>signing_key</b> */
- 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 directory port. */
- uint16_t dir_port;
-} authority_cert_t;
-
-/** Bitfield enum type listing types of information that directory authorities
- * can be authoritative about, and that directory caches may or may not cache.
- *
- * Note that the granularity here is based on authority granularity and on
- * cache capabilities. Thus, one particular bit may correspond in practice to
- * a few types of directory info, so long as every authority that pronounces
- * officially about one of the types prounounces officially about all of them,
- * and so long as every cache that caches one of them caches all of them.
- */
-typedef enum {
- NO_DIRINFO = 0,
- /** Serves/signs v3 directory information: votes, consensuses, certs */
- V3_DIRINFO = 1 << 2,
- /** Serves bridge descriptors. */
- BRIDGE_DIRINFO = 1 << 4,
- /** Serves extrainfo documents. */
- EXTRAINFO_DIRINFO=1 << 5,
- /** Serves microdescriptors. */
- MICRODESC_DIRINFO=1 << 6,
-} dirinfo_type_t;
-
-#define ALL_DIRINFO ((dirinfo_type_t)((1<<7)-1))
-
-#define CRYPT_PATH_MAGIC 0x70127012u
-
-struct fast_handshake_state_t;
-struct ntor_handshake_state_t;
-#define ONION_HANDSHAKE_TYPE_TAP 0x0000
-#define ONION_HANDSHAKE_TYPE_FAST 0x0001
-#define ONION_HANDSHAKE_TYPE_NTOR 0x0002
-#define MAX_ONION_HANDSHAKE_TYPE 0x0002
-typedef struct {
- uint16_t tag;
- union {
- struct fast_handshake_state_t *fast;
- crypto_dh_t *tap;
- struct ntor_handshake_state_t *ntor;
- } u;
-} onion_handshake_state_t;
-
-typedef struct relay_crypto_t {
- /* crypto environments */
- /** Encryption key and counter for cells heading towards the OR at this
- * step. */
- crypto_cipher_t *f_crypto;
- /** Encryption key and counter for cells heading back from the OR at this
- * step. */
- crypto_cipher_t *b_crypto;
-
- /** Digest state for cells heading towards the OR at this step. */
- crypto_digest_t *f_digest; /* for integrity checking */
- /** Digest state for cells heading away from the OR at this step. */
- crypto_digest_t *b_digest;
-
-} relay_crypto_t;
-
-/** Holds accounting information for a single step in the layered encryption
- * performed by a circuit. Used only at the client edge of a circuit. */
-typedef struct crypt_path_t {
- uint32_t magic;
-
- /** Cryptographic state used for encrypting and authenticating relay
- * cells to and from this hop. */
- relay_crypto_t crypto;
-
- /** Current state of the handshake as performed with the OR at this
- * step. */
- onion_handshake_state_t handshake_state;
- /** Diffie-hellman handshake state for performing an introduction
- * operations */
- crypto_dh_t *rend_dh_handshake_state;
-
- /** Negotiated key material shared with the OR at this step. */
- char rend_circ_nonce[DIGEST_LEN];/* KH in tor-spec.txt */
-
- /** Information to extend to the OR at this step. */
- extend_info_t *extend_info;
-
- /** Is the circuit built to this step? Must be one of:
- * - CPATH_STATE_CLOSED (The circuit has not been extended to this step)
- * - CPATH_STATE_AWAITING_KEYS (We have sent an EXTEND/CREATE to this step
- * and not received an EXTENDED/CREATED)
- * - CPATH_STATE_OPEN (The circuit has been extended to this step) */
- uint8_t state;
-#define CPATH_STATE_CLOSED 0
-#define CPATH_STATE_AWAITING_KEYS 1
-#define CPATH_STATE_OPEN 2
- struct crypt_path_t *next; /**< Link to next crypt_path_t in the circuit.
- * (The list is circular, so the last node
- * links to the first.) */
- struct crypt_path_t *prev; /**< Link to previous crypt_path_t in the
- * circuit. */
-
- int package_window; /**< How many cells are we allowed to originate ending
- * at this step? */
- int deliver_window; /**< How many cells are we willing to deliver originating
- * at this step? */
-} crypt_path_t;
-
-/** A reference-counted pointer to a crypt_path_t, used only to share
- * the final rendezvous cpath to be used on a service-side rendezvous
- * circuit among multiple circuits built in parallel to the same
- * destination rendezvous point. */
-typedef struct {
- /** The reference count. */
- unsigned int refcount;
- /** The pointer. Set to NULL when the crypt_path_t is put into use
- * on an opened rendezvous circuit. */
- crypt_path_t *cpath;
-} crypt_path_reference_t;
-
-#define CPATH_KEY_MATERIAL_LEN (20*2+16*2)
-
-#define DH_KEY_LEN DH_BYTES
-
-/** Information used to build a circuit. */
-typedef struct {
- /** Intended length of the final circuit. */
- int desired_path_len;
- /** How to extend to the planned exit node. */
- extend_info_t *chosen_exit;
- /** Whether every node in the circ must have adequate uptime. */
- unsigned int need_uptime : 1;
- /** Whether every node in the circ must have adequate capacity. */
- unsigned int need_capacity : 1;
- /** Whether the last hop was picked with exiting in mind. */
- unsigned int is_internal : 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. */
- unsigned int onehop_tunnel : 1;
- /** The crypt_path_t to append after rendezvous: used for rendezvous. */
- crypt_path_t *pending_final_cpath;
- /** A ref-counted reference to the crypt_path_t to append after
- * rendezvous; used on the service side. */
- crypt_path_reference_t *service_pending_final_cpath_ref;
- /** How many times has building a circuit for this task failed? */
- int failure_count;
- /** At what time should we give up on this task? */
- time_t expiry_time;
-} cpath_build_state_t;
-
-/** "magic" value for an origin_circuit_t */
-#define ORIGIN_CIRCUIT_MAGIC 0x35315243u
-/** "magic" value for an or_circuit_t */
-#define OR_CIRCUIT_MAGIC 0x98ABC04Fu
-/** "magic" value for a circuit that would have been freed by circuit_free,
- * but which we're keeping around until a cpuworker reply arrives. See
- * circuit_free() for more documentation. */
-#define DEAD_CIRCUIT_MAGIC 0xdeadc14c
-
-struct create_cell_t;
-
-/** Entry in the cell stats list of a circuit; used only if CELL_STATS
- * events are enabled. */
-typedef struct testing_cell_stats_entry_t {
- uint8_t command; /**< cell command number. */
- /** Waiting time in centiseconds if this event is for a removed cell,
- * or 0 if this event is for adding a cell to the queue. 22 bits can
- * store more than 11 hours, enough to assume that a circuit with this
- * delay would long have been closed. */
- unsigned int waiting_time:22;
- unsigned int removed:1; /**< 0 for added to, 1 for removed from queue. */
- unsigned int exitward:1; /**< 0 for app-ward, 1 for exit-ward. */
-} testing_cell_stats_entry_t;
-
-/**
- * A circuit is a path over the onion routing
- * network. Applications can connect to one end of the circuit, and can
- * create exit connections at the other end of the circuit. AP and exit
- * connections have only one circuit associated with them (and thus these
- * connection types are closed when the circuit is closed), whereas
- * OR connections multiplex many circuits at once, and stay standing even
- * when there are no circuits running over them.
- *
- * A circuit_t structure can fill one of two roles. First, a or_circuit_t
- * links two connections together: either an edge connection and an OR
- * connection, or two OR connections. (When joined to an OR connection, a
- * circuit_t affects only cells sent to a particular circID on that
- * connection. When joined to an edge connection, a circuit_t affects all
- * data.)
-
- * Second, an origin_circuit_t holds the cipher keys and state for sending data
- * along a given circuit. At the OP, it has a sequence of ciphers, each
- * of which is shared with a single OR along the circuit. Separate
- * ciphers are used for data going "forward" (away from the OP) and
- * "backward" (towards the OP). At the OR, a circuit has only two stream
- * ciphers: one for data going forward, and one for data going backward.
- */
-typedef struct circuit_t {
- uint32_t magic; /**< For memory and type debugging: must equal
- * ORIGIN_CIRCUIT_MAGIC or OR_CIRCUIT_MAGIC. */
-
- /** The channel that is next in this circuit. */
- channel_t *n_chan;
-
- /**
- * The circuit_id used in the next (forward) hop of this circuit;
- * this is unique to n_chan, but this ordered pair is globally
- * unique:
- *
- * (n_chan->global_identifier, n_circ_id)
- */
- circid_t n_circ_id;
-
- /**
- * Circuit mux associated with n_chan to which this circuit is attached;
- * NULL if we have no n_chan.
- */
- circuitmux_t *n_mux;
-
- /** Queue of cells waiting to be transmitted on n_chan */
- cell_queue_t n_chan_cells;
-
- /**
- * The hop to which we want to extend this circuit. Should be NULL if
- * the circuit has attached to a channel.
- */
- extend_info_t *n_hop;
-
- /** True iff we are waiting for n_chan_cells to become less full before
- * allowing p_streams to add any more cells. (Origin circuit only.) */
- unsigned int streams_blocked_on_n_chan : 1;
- /** True iff we are waiting for p_chan_cells to become less full before
- * allowing n_streams to add any more cells. (OR circuit only.) */
- unsigned int streams_blocked_on_p_chan : 1;
-
- /** True iff we have queued a delete backwards on this circuit, but not put
- * it on the output buffer. */
- unsigned int p_delete_pending : 1;
- /** True iff we have queued a delete forwards on this circuit, but not put
- * it on the output buffer. */
- unsigned int n_delete_pending : 1;
-
- /** True iff this circuit has received a DESTROY cell in either direction */
- unsigned int received_destroy : 1;
-
- uint8_t state; /**< Current status of this circuit. */
- uint8_t purpose; /**< Why are we creating this circuit? */
-
- /** How many relay data cells can we package (read from edge streams)
- * on this circuit before we receive a circuit-level sendme cell asking
- * for more? */
- int package_window;
- /** How many relay data cells will we deliver (write to edge streams)
- * on this circuit? When deliver_window gets low, we send some
- * circuit-level sendme cells to indicate that we're willing to accept
- * more. */
- int deliver_window;
-
- /** Temporary field used during circuits_handle_oom. */
- uint32_t age_tmp;
-
- /** For storage while n_chan is pending (state CIRCUIT_STATE_CHAN_WAIT). */
- struct create_cell_t *n_chan_create_cell;
-
- /** When did circuit construction actually begin (ie send the
- * CREATE cell or begin cannibalization).
- *
- * Note: This timer will get reset if we decide to cannibalize
- * a circuit. It may also get reset during certain phases of hidden
- * service circuit use.
- *
- * We keep this timestamp with a higher resolution than most so that the
- * circuit-build-time tracking code can get millisecond resolution.
- */
- struct timeval timestamp_began;
-
- /** This timestamp marks when the init_circuit_base constructor ran. */
- struct timeval timestamp_created;
-
- /** When the circuit was first used, or 0 if the circuit is clean.
- *
- * XXXX Note that some code will artificially adjust this value backward
- * in time in order to indicate that a circuit shouldn't be used for new
- * streams, but that it can stay alive as long as it has streams on it.
- * That's a kludge we should fix.
- *
- * XXX The CBT code uses this field to record when HS-related
- * circuits entered certain states. This usage probably won't
- * interfere with this field's primary purpose, but we should
- * document it more thoroughly to make sure of that.
- *
- * XXX The SocksPort option KeepaliveIsolateSOCKSAuth will artificially
- * adjust this value forward each time a suitable stream is attached to an
- * already constructed circuit, potentially keeping the circuit alive
- * indefinitely.
- */
- time_t timestamp_dirty;
-
- uint16_t marked_for_close; /**< Should we close this circuit at the end of
- * the main loop? (If true, holds the line number
- * where this circuit was marked.) */
- const char *marked_for_close_file; /**< For debugging: in which file was this
- * circuit marked for close? */
- /** For what reason (See END_CIRC_REASON...) is this circuit being closed?
- * This field is set in circuit_mark_for_close and used later in
- * circuit_about_to_free. */
- int marked_for_close_reason;
- /** As marked_for_close_reason, but reflects the underlying reason for
- * closing this circuit.
- */
- int marked_for_close_orig_reason;
-
- /** Unique ID for measuring tunneled network status requests. */
- uint64_t dirreq_id;
-
- /** Index in smartlist of all circuits (global_circuitlist). */
- int global_circuitlist_idx;
-
- /** Various statistics about cells being added to or removed from this
- * circuit's queues; used only if CELL_STATS events are enabled and
- * cleared after being sent to control port. */
- smartlist_t *testing_cell_stats;
-
- /** If set, points to an HS token that this circuit might be carrying.
- * Used by the HS circuitmap. */
- hs_token_t *hs_token;
- /** Hashtable node: used to look up the circuit by its HS token using the HS
- circuitmap. */
- HT_ENTRY(circuit_t) hs_circuitmap_node;
-} circuit_t;
-
-/** Largest number of relay_early cells that we can send on a given
- * circuit. */
-#define MAX_RELAY_EARLY_CELLS_PER_CIRCUIT 8
-
-/**
- * Describes the circuit building process in simplified terms based
- * on the path bias accounting state for a circuit.
- *
- * NOTE: These state values are enumerated in the order for which we
- * expect circuits to transition through them. If you add states,
- * you need to preserve this overall ordering. The various pathbias
- * state transition and accounting functions (pathbias_mark_* and
- * pathbias_count_*) contain ordinal comparisons to enforce proper
- * state transitions for corrections.
- *
- * This state machine and the associated logic was created to prevent
- * miscounting due to unknown cases of circuit reuse. See also tickets
- * #6475 and #7802.
- */
-typedef enum {
- /** This circuit is "new". It has not yet completed a first hop
- * or been counted by the path bias code. */
- PATH_STATE_NEW_CIRC = 0,
- /** This circuit has completed one/two hops, and has been counted by
- * the path bias logic. */
- PATH_STATE_BUILD_ATTEMPTED = 1,
- /** This circuit has been completely built */
- PATH_STATE_BUILD_SUCCEEDED = 2,
- /** Did we try to attach any SOCKS streams or hidserv introductions to
- * this circuit?
- *
- * Note: If we ever implement end-to-end stream timing through test
- * stream probes (#5707), we must *not* set this for those probes
- * (or any other automatic streams) because the adversary could
- * just tag at a later point.
- */
- PATH_STATE_USE_ATTEMPTED = 3,
- /** Did any SOCKS streams or hidserv introductions actually succeed on
- * this circuit?
- *
- * If any streams detatch/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.
- */
- PATH_STATE_USE_SUCCEEDED = 4,
-
- /**
- * This is a special state to indicate that we got a corrupted
- * relay cell on a circuit and we don't intend to probe it.
- */
- PATH_STATE_USE_FAILED = 5,
-
- /**
- * This is a special state to indicate that we already counted
- * the circuit. Used to guard against potential state machine
- * violations.
- */
- PATH_STATE_ALREADY_COUNTED = 6,
-} path_state_t;
-#define path_state_bitfield_t ENUM_BF(path_state_t)
-
-/** An origin_circuit_t holds data necessary to build and use a circuit.
- */
-typedef struct origin_circuit_t {
- circuit_t base_;
-
- /** Linked list of AP streams (or EXIT streams if hidden service)
- * associated with this circuit. */
- edge_connection_t *p_streams;
-
- /** Bytes read on this circuit since last call to
- * control_event_circ_bandwidth_used(). Only used if we're configured
- * to emit CIRC_BW events. */
- uint32_t n_read_circ_bw;
-
- /** Bytes written to on this circuit since last call to
- * control_event_circ_bandwidth_used(). Only used if we're configured
- * to emit CIRC_BW events. */
- uint32_t n_written_circ_bw;
-
- /** Total known-valid relay cell bytes since last call to
- * control_event_circ_bandwidth_used(). Only used if we're configured
- * to emit CIRC_BW events. */
- uint32_t n_delivered_read_circ_bw;
-
- /** Total written relay cell bytes since last call to
- * control_event_circ_bandwidth_used(). Only used if we're configured
- * to emit CIRC_BW events. */
- uint32_t n_delivered_written_circ_bw;
-
- /** Total overhead data in all known-valid relay data cells since last
- * call to control_event_circ_bandwidth_used(). Only used if we're
- * configured to emit CIRC_BW events. */
- uint32_t n_overhead_read_circ_bw;
-
- /** Total written overhead data in all relay data cells since last call to
- * control_event_circ_bandwidth_used(). Only used if we're configured
- * to emit CIRC_BW events. */
- uint32_t n_overhead_written_circ_bw;
-
- /** Build state for this circuit. It includes the intended path
- * length, the chosen exit router, rendezvous information, etc.
- */
- cpath_build_state_t *build_state;
- /** The doubly-linked list of crypt_path_t entries, one per hop,
- * for this circuit. This includes ciphers for each hop,
- * integrity-checking digests for each hop, and package/delivery
- * windows for each hop.
- */
- crypt_path_t *cpath;
-
- /** Holds all rendezvous data on either client or service side. */
- rend_data_t *rend_data;
-
- /** Holds hidden service identifier on either client or service side. This
- * is for both introduction and rendezvous circuit. */
- struct hs_ident_circuit_t *hs_ident;
-
- /** Holds the data that the entry guard system uses to track the
- * status of the guard this circuit is using, and thereby to determine
- * whether this circuit can be used. */
- struct circuit_guard_state_t *guard_state;
-
- /** Index into global_origin_circuit_list for this circuit. -1 if not
- * present. */
- int global_origin_circuit_list_idx;
-
- /** How many more relay_early cells can we send on this circuit, according
- * to the specification? */
- unsigned int remaining_relay_early_cells : 4;
-
- /** Set if this circuit is insanely old and we already informed the user */
- unsigned int is_ancient : 1;
-
- /** Set if this circuit has already been opened. Used to detect
- * cannibalized circuits. */
- unsigned int has_opened : 1;
-
- /**
- * Path bias state machine. Used to ensure integrity of our
- * circuit building and usage accounting. See path_state_t
- * for more details.
- */
- path_state_bitfield_t path_state : 3;
-
- /* If this flag is set, we should not consider attaching any more
- * connections to this circuit. */
- unsigned int unusable_for_new_conns : 1;
-
- /**
- * Tristate variable to guard against pathbias miscounting
- * due to circuit purpose transitions changing the decision
- * of pathbias_should_count(). This variable is informational
- * only. The current results of pathbias_should_count() are
- * the official decision for pathbias accounting.
- */
- uint8_t pathbias_shouldcount;
-#define PATHBIAS_SHOULDCOUNT_UNDECIDED 0
-#define PATHBIAS_SHOULDCOUNT_IGNORED 1
-#define PATHBIAS_SHOULDCOUNT_COUNTED 2
-
- /** For path probing. Store the temporary probe stream ID
- * for response comparison */
- streamid_t pathbias_probe_id;
-
- /** For path probing. Store the temporary probe address nonce
- * (in host byte order) for response comparison. */
- uint32_t pathbias_probe_nonce;
-
- /** Set iff this is a hidden-service circuit which has timed out
- * according to our current circuit-build timeout, but which has
- * been kept around because it might still succeed in connecting to
- * its destination, and which is not a fully-connected rendezvous
- * circuit.
- *
- * (We clear this flag for client-side rendezvous circuits when they
- * are 'joined' to the other side's rendezvous circuit, so that
- * connection_ap_handshake_attach_circuit can put client streams on
- * the circuit. We also clear this flag for service-side rendezvous
- * circuits when they are 'joined' to a client's rend circ, but only
- * for symmetry with the client case. Client-side introduction
- * circuits are closed when we get a joined rend circ, and
- * service-side introduction circuits never have this flag set.) */
- unsigned int hs_circ_has_timed_out : 1;
-
- /** Set iff this circuit has been given a relaxed timeout because
- * no circuits have opened. Used to prevent spamming logs. */
- unsigned int relaxed_timeout : 1;
-
- /** Set iff this is a service-side rendezvous circuit for which a
- * new connection attempt has been launched. We consider launching
- * a new service-side rend circ to a client when the previous one
- * fails; now that we don't necessarily close a service-side rend
- * circ when we launch a new one to the same client, this flag keeps
- * us from launching two retries for the same failed rend circ. */
- unsigned int hs_service_side_rend_circ_has_been_relaunched : 1;
-
- /** What commands were sent over this circuit that decremented the
- * RELAY_EARLY counter? This is for debugging task 878. */
- uint8_t relay_early_commands[MAX_RELAY_EARLY_CELLS_PER_CIRCUIT];
-
- /** How many RELAY_EARLY cells have been sent over this circuit? This is
- * for debugging task 878, too. */
- int relay_early_cells_sent;
-
- /** The next stream_id that will be tried when we're attempting to
- * construct a new AP stream originating at this circuit. */
- streamid_t next_stream_id;
-
- /* The intro key replaces the hidden service's public key if purpose is
- * S_ESTABLISH_INTRO or S_INTRO, provided that no unversioned rendezvous
- * descriptor is used. */
- crypto_pk_t *intro_key;
-
- /** Quasi-global identifier for this circuit; used for control.c */
- /* XXXX NM This can get re-used after 2**32 circuits. */
- uint32_t global_identifier;
-
- /** True if we have associated one stream to this circuit, thereby setting
- * the isolation parameters for this circuit. Note that this doesn't
- * necessarily mean that we've <em>attached</em> any streams to the circuit:
- * we may only have marked up this circuit during the launch process.
- */
- unsigned int isolation_values_set : 1;
- /** True iff any stream has <em>ever</em> been attached to this circuit.
- *
- * In a better world we could use timestamp_dirty for this, but
- * timestamp_dirty is far too overloaded at the moment.
- */
- unsigned int isolation_any_streams_attached : 1;
-
- /** A bitfield of ISO_* flags for every isolation field such that this
- * circuit has had streams with more than one value for that field
- * attached to it. */
- uint8_t isolation_flags_mixed;
-
- /** @name Isolation parameters
- *
- * If any streams have been associated with this circ (isolation_values_set
- * == 1), and all streams associated with the circuit have had the same
- * value for some field ((isolation_flags_mixed & ISO_FOO) == 0), then these
- * elements hold the value for that field.
- *
- * Note again that "associated" is not the same as "attached": we
- * preliminarily associate streams with a circuit while the circuit is being
- * launched, so that we can tell whether we need to launch more circuits.
- *
- * @{
- */
- uint8_t client_proto_type;
- uint8_t client_proto_socksver;
- uint16_t dest_port;
- tor_addr_t client_addr;
- char *dest_address;
- int session_group;
- unsigned nym_epoch;
- size_t socks_username_len;
- uint8_t socks_password_len;
- /* Note that the next two values are NOT NUL-terminated; see
- socks_username_len and socks_password_len for their lengths. */
- char *socks_username;
- char *socks_password;
- /** Global identifier for the first stream attached here; used by
- * ISO_STREAM. */
- uint64_t associated_isolated_stream_global_id;
- /**@}*/
- /** A list of addr_policy_t for this circuit in particular. Used by
- * adjust_exit_policy_from_exitpolicy_failure.
- */
- smartlist_t *prepend_policy;
-
- /** How long do we wait before closing this circuit if it remains
- * completely idle after it was built, in seconds? This value
- * is randomized on a per-circuit basis from CircuitsAvailableTimoeut
- * to 2*CircuitsAvailableTimoeut. */
- int circuit_idle_timeout;
-
-} origin_circuit_t;
-
-struct onion_queue_t;
-
-/** An or_circuit_t holds information needed to implement a circuit at an
- * OR. */
-typedef struct or_circuit_t {
- circuit_t base_;
-
- /** Pointer to an entry on the onion queue, if this circuit is waiting for a
- * chance to give an onionskin to a cpuworker. Used only in onion.c */
- struct onion_queue_t *onionqueue_entry;
- /** Pointer to a workqueue entry, if this circuit has given an onionskin to
- * a cpuworker and is waiting for a response. Used to decide whether it is
- * safe to free a circuit or if it is still in use by a cpuworker. */
- struct workqueue_entry_s *workqueue_entry;
-
- /** The circuit_id used in the previous (backward) hop of this circuit. */
- circid_t p_circ_id;
- /** Queue of cells waiting to be transmitted on p_conn. */
- cell_queue_t p_chan_cells;
- /** The channel that is previous in this circuit. */
- channel_t *p_chan;
- /**
- * Circuit mux associated with p_chan to which this circuit is attached;
- * NULL if we have no p_chan.
- */
- circuitmux_t *p_mux;
- /** Linked list of Exit streams associated with this circuit. */
- edge_connection_t *n_streams;
- /** Linked list of Exit streams associated with this circuit that are
- * still being resolved. */
- edge_connection_t *resolving_streams;
-
- /** Cryptographic state used for encrypting and authenticating relay
- * cells to and from this hop. */
- relay_crypto_t crypto;
-
- /** Points to spliced circuit if purpose is REND_ESTABLISHED, and circuit
- * is not marked for close. */
- struct or_circuit_t *rend_splice;
-
- /** Stores KH for the handshake. */
- char rend_circ_nonce[DIGEST_LEN];/* KH in tor-spec.txt */
-
- /** How many more relay_early cells can we send on this circuit, according
- * to the specification? */
- unsigned int remaining_relay_early_cells : 4;
-
- /* We have already received an INTRODUCE1 cell on this circuit. */
- unsigned int already_received_introduce1 : 1;
-
- /** If set, this circuit carries HS traffic. Consider it in any HS
- * statistics. */
- unsigned int circuit_carries_hs_traffic_stats : 1;
-
- /** Number of cells that were removed from circuit queue; reset every
- * time when writing buffer stats to disk. */
- uint32_t processed_cells;
-
- /** Total time in milliseconds that cells spent in both app-ward and
- * exit-ward queues of this circuit; reset every time when writing
- * buffer stats to disk. */
- uint64_t total_cell_waiting_time;
-} or_circuit_t;
-
-#if REND_COOKIE_LEN != DIGEST_LEN
-#error "The REND_TOKEN_LEN macro assumes REND_COOKIE_LEN == DIGEST_LEN"
-#endif
-#define REND_TOKEN_LEN DIGEST_LEN
-
-/** Convert a circuit subtype to a circuit_t. */
-#define TO_CIRCUIT(x) (&((x)->base_))
-
-/** Convert a circuit_t* to a pointer to the enclosing or_circuit_t. Assert
- * if the cast is impossible. */
-static or_circuit_t *TO_OR_CIRCUIT(circuit_t *);
-static const or_circuit_t *CONST_TO_OR_CIRCUIT(const circuit_t *);
-/** Convert a circuit_t* to a pointer to the enclosing origin_circuit_t.
- * Assert if the cast is impossible. */
-static origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *);
-static const origin_circuit_t *CONST_TO_ORIGIN_CIRCUIT(const circuit_t *);
-
-/** Return 1 iff <b>node</b> has Exit flag and no BadExit flag.
- * Otherwise, return 0.
- */
-static inline int node_is_good_exit(const node_t *node)
-{
- return node->is_exit && ! node->is_bad_exit;
-}
-
-static inline or_circuit_t *TO_OR_CIRCUIT(circuit_t *x)
-{
- tor_assert(x->magic == OR_CIRCUIT_MAGIC);
- return DOWNCAST(or_circuit_t, x);
-}
-static inline const or_circuit_t *CONST_TO_OR_CIRCUIT(const circuit_t *x)
-{
- tor_assert(x->magic == OR_CIRCUIT_MAGIC);
- return DOWNCAST(or_circuit_t, x);
-}
-static inline origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *x)
-{
- tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC);
- return DOWNCAST(origin_circuit_t, x);
-}
-static inline const origin_circuit_t *CONST_TO_ORIGIN_CIRCUIT(
- const circuit_t *x)
-{
- tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC);
- return DOWNCAST(origin_circuit_t, x);
-}
-
-/* limits for TCP send and recv buffer size used for constrained sockets */
-#define MIN_CONSTRAINED_TCP_BUFFER 2048
-#define MAX_CONSTRAINED_TCP_BUFFER 262144 /* 256k */
-
-/** @name Isolation flags
-
- Ways to isolate client streams
-
- @{
-*/
-/** Isolate based on destination port */
-#define ISO_DESTPORT (1u<<0)
-/** Isolate based on destination address */
-#define ISO_DESTADDR (1u<<1)
-/** Isolate based on SOCKS authentication */
-#define ISO_SOCKSAUTH (1u<<2)
-/** Isolate based on client protocol choice */
-#define ISO_CLIENTPROTO (1u<<3)
-/** Isolate based on client address */
-#define ISO_CLIENTADDR (1u<<4)
-/** Isolate based on session group (always on). */
-#define ISO_SESSIONGRP (1u<<5)
-/** Isolate based on newnym epoch (always on). */
-#define ISO_NYM_EPOCH (1u<<6)
-/** Isolate all streams (Internal only). */
-#define ISO_STREAM (1u<<7)
-/**@}*/
-
-/** Default isolation level for ports. */
-#define ISO_DEFAULT (ISO_CLIENTADDR|ISO_SOCKSAUTH|ISO_SESSIONGRP|ISO_NYM_EPOCH)
-
-/** Indicates that we haven't yet set a session group on a port_cfg_t. */
-#define SESSION_GROUP_UNSET -1
-/** Session group reserved for directory connections */
-#define SESSION_GROUP_DIRCONN -2
-/** Session group reserved for resolve requests launched by a controller */
-#define SESSION_GROUP_CONTROL_RESOLVE -3
-/** First automatically allocated session group number */
-#define SESSION_GROUP_FIRST_AUTO -4
-
-/** Configuration for a single port that we're listening on. */
-typedef struct port_cfg_t {
- tor_addr_t addr; /**< The actual IP to listen on, if !is_unix_addr. */
- int port; /**< The configured port, or CFG_AUTO_PORT to tell Tor to pick its
- * own port. */
- uint8_t type; /**< One of CONN_TYPE_*_LISTENER */
- unsigned is_unix_addr : 1; /**< True iff this is an AF_UNIX address. */
-
- unsigned is_group_writable : 1;
- unsigned is_world_writable : 1;
- unsigned relax_dirmode_check : 1;
-
- entry_port_cfg_t entry_cfg;
-
- server_port_cfg_t server_cfg;
-
- /* Unix sockets only: */
- /** Path for an AF_UNIX address */
- char unix_addr[FLEXIBLE_ARRAY_MEMBER];
-} port_cfg_t;
-
-typedef struct routerset_t routerset_t;
-
-/** A magic value for the (Socks|OR|...)Port options below, telling Tor
- * to pick its own port. */
-#define CFG_AUTO_PORT 0xc4005e
-
-/** 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;
-
-/** Configuration options for a Tor process. */
-typedef struct {
- uint32_t magic_;
-
- /** What should the tor process actually do? */
- enum {
- CMD_RUN_TOR=0, CMD_LIST_FINGERPRINT, CMD_HASH_PASSWORD,
- CMD_VERIFY_CONFIG, CMD_RUN_UNITTESTS, CMD_DUMP_CONFIG,
- CMD_KEYGEN,
- CMD_KEY_EXPIRATION,
- } command;
- char *command_arg; /**< Argument for command-line option. */
-
- config_line_t *Logs; /**< New-style list of configuration lines
- * for logs */
- int LogTimeGranularity; /**< Log resolution in milliseconds. */
-
- int LogMessageDomains; /**< Boolean: Should we log the domain(s) in which
- * each log message occurs? */
- 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
- * configured by the user. */
- char *DataDirectory; /**< Where to store long-term data, as modified. */
- int DataDirectoryGroupReadable; /**< Boolean: Is the DataDirectory g+r? */
-
- char *KeyDirectory_option; /**< Where to store keys, as
- * configured by the user. */
- char *KeyDirectory; /**< Where to store keys data, as modified. */
- int KeyDirectoryGroupReadable; /**< Boolean: Is the KeyDirectory g+r? */
-
- char *CacheDirectory_option; /**< Where to store cached data, as
- * configured by the user. */
- char *CacheDirectory; /**< Where to store cached data, as modified. */
- 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. */
- char *PidFile; /**< Where to store PID of Tor process. */
-
- routerset_t *ExitNodes; /**< Structure containing nicknames, digests,
- * country codes and IP address patterns of ORs to
- * consider as exits. */
- routerset_t *EntryNodes;/**< Structure containing nicknames, digests,
- * country codes and IP address patterns of ORs to
- * consider as entry points. */
- int StrictNodes; /**< Boolean: When none of our EntryNodes or ExitNodes
- * are up, or we need to access a node in ExcludeNodes,
- * do we just fail instead? */
- routerset_t *ExcludeNodes;/**< Structure containing nicknames, digests,
- * country codes and IP address patterns of ORs
- * not to use in circuits. But see StrictNodes
- * above. */
- routerset_t *ExcludeExitNodes;/**< Structure containing nicknames, digests,
- * country codes and IP address patterns of
- * ORs not to consider as exits. */
-
- /** Union of ExcludeNodes and ExcludeExitNodes */
- routerset_t *ExcludeExitNodesUnion_;
-
- int DisableAllSwap; /**< Boolean: Attempt to call mlockall() on our
- * process for all current and future memory. */
-
- config_line_t *ExitPolicy; /**< Lists of exit policy components. */
- int ExitPolicyRejectPrivate; /**< Should we not exit to reserved private
- * addresses, and our own published addresses?
- */
- int ExitPolicyRejectLocalInterfaces; /**< Should we not exit to local
- * interface addresses?
- * Includes OutboundBindAddresses and
- * configured ports. */
- int ReducedExitPolicy; /**<Should we use the Reduced Exit Policy? */
- config_line_t *SocksPolicy; /**< Lists of socks policy components */
- config_line_t *DirPolicy; /**< Lists of dir policy components */
- /** Local address to bind outbound sockets */
- config_line_t *OutboundBindAddress;
- /** Local address to bind outbound relay sockets */
- config_line_t *OutboundBindAddressOR;
- /** Local address to bind outbound exit sockets */
- config_line_t *OutboundBindAddressExit;
- /** Addresses derived from the various OutboundBindAddress lines.
- * [][0] is IPv4, [][1] is IPv6
- */
- tor_addr_t OutboundBindAddresses[OUTBOUND_ADDR_MAX][2];
- /** Directory server only: which versions of
- * Tor should we tell users to run? */
- config_line_t *RecommendedVersions;
- config_line_t *RecommendedClientVersions;
- config_line_t *RecommendedServerVersions;
- config_line_t *RecommendedPackages;
- /** Whether dirservers allow router descriptors with private IPs. */
- int DirAllowPrivateAddresses;
- /** Whether routers accept EXTEND cells to routers with private IPs. */
- int ExtendAllowPrivateAddresses;
- char *User; /**< Name of user to run Tor as. */
- config_line_t *ORPort_lines; /**< Ports to listen on for OR connections. */
- /** Ports to listen on for extended OR connections. */
- config_line_t *ExtORPort_lines;
- /** Ports to listen on for SOCKS connections. */
- config_line_t *SocksPort_lines;
- /** Ports to listen on for transparent pf/netfilter connections. */
- config_line_t *TransPort_lines;
- char *TransProxyType; /**< What kind of transparent proxy
- * implementation are we using? */
- /** Parsed value of TransProxyType. */
- enum {
- TPT_DEFAULT,
- TPT_PF_DIVERT,
- TPT_IPFW,
- TPT_TPROXY,
- } TransProxyType_parsed;
- config_line_t *NATDPort_lines; /**< Ports to listen on for transparent natd
- * connections. */
- /** Ports to listen on for HTTP Tunnel connections. */
- config_line_t *HTTPTunnelPort_lines;
- config_line_t *ControlPort_lines; /**< Ports to listen on for control
- * connections. */
- config_line_t *ControlSocket; /**< List of Unix Domain Sockets to listen on
- * for control connections. */
-
- int ControlSocketsGroupWritable; /**< Boolean: Are control sockets g+rw? */
- int UnixSocksGroupWritable; /**< Boolean: Are SOCKS Unix sockets g+rw? */
- /** Ports to listen on for directory connections. */
- config_line_t *DirPort_lines;
- config_line_t *DNSPort_lines; /**< Ports to listen on for DNS requests. */
-
- /* MaxMemInQueues value as input by the user. We clean this up to be
- * MaxMemInQueues. */
- uint64_t MaxMemInQueues_raw;
- uint64_t MaxMemInQueues;/**< If we have more memory than this allocated
- * for queues and buffers, run the OOM handler */
- /** Above this value, consider ourselves low on RAM. */
- uint64_t MaxMemInQueues_low_threshold;
-
- /** @name port booleans
- *
- * Derived booleans: For server ports and ControlPort, true iff there is a
- * non-listener port on an AF_INET or AF_INET6 address of the given type
- * configured in one of the _lines options above.
- * For client ports, also true if there is a unix socket configured.
- * If you are checking for client ports, you may want to use:
- * SocksPort_set || TransPort_set || NATDPort_set || DNSPort_set ||
- * HTTPTunnelPort_set
- * rather than SocksPort_set.
- *
- * @{
- */
- unsigned int ORPort_set : 1;
- unsigned int SocksPort_set : 1;
- unsigned int TransPort_set : 1;
- unsigned int NATDPort_set : 1;
- unsigned int ControlPort_set : 1;
- unsigned int DirPort_set : 1;
- unsigned int DNSPort_set : 1;
- unsigned int ExtORPort_set : 1;
- unsigned int HTTPTunnelPort_set : 1;
- /**@}*/
-
- int AssumeReachable; /**< Whether to publish our descriptor regardless. */
- int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */
- int V3AuthoritativeDir; /**< Boolean: is this an authoritative directory
- * for version 3 directories? */
- int VersioningAuthoritativeDir; /**< Boolean: is this an authoritative
- * directory that's willing to recommend
- * versions? */
- int BridgeAuthoritativeDir; /**< Boolean: is this an authoritative directory
- * that aggregates bridge descriptors? */
-
- /** If set on a bridge relay, it will include this value on a new
- * "bridge-distribution-request" line in its bridge descriptor. */
- char *BridgeDistribution;
-
- /** If set on a bridge authority, it will answer requests on its dirport
- * for bridge statuses -- but only if the requests use this password. */
- char *BridgePassword;
- /** If BridgePassword is set, this is a SHA256 digest of the basic http
- * authenticator for it. Used so we can do a time-independent comparison. */
- char *BridgePassword_AuthDigest_;
-
- int UseBridges; /**< Boolean: should we start all circuits with a bridge? */
- config_line_t *Bridges; /**< List of bootstrap bridge addresses. */
-
- config_line_t *ClientTransportPlugin; /**< List of client
- transport plugins. */
-
- config_line_t *ServerTransportPlugin; /**< List of client
- transport plugins. */
-
- /** List of TCP/IP addresses that transports should listen at. */
- config_line_t *ServerTransportListenAddr;
-
- /** List of options that must be passed to pluggable transports. */
- config_line_t *ServerTransportOptions;
-
- int BridgeRelay; /**< Boolean: are we acting as a bridge relay? We make
- * this explicit so we can change how we behave in the
- * future. */
-
- /** Boolean: if we know the bridge's digest, should we get new
- * descriptors from the bridge authorities or from the bridge itself? */
- int UpdateBridgesFromAuthority;
-
- int AvoidDiskWrites; /**< Boolean: should we never cache things to disk?
- * Not used yet. */
- int ClientOnly; /**< Boolean: should we never evolve into a server role? */
-
- int ReducedConnectionPadding; /**< Boolean: Should we try to keep connections
- open shorter and pad them less against
- connection-level traffic analysis? */
- /** Autobool: if auto, then connection padding will be negotiated by client
- * and server. If 0, it will be fully disabled. If 1, the client will still
- * pad to the server regardless of server support. */
- int ConnectionPadding;
-
- /** To what authority types do we publish our descriptor? Choices are
- * "v1", "v2", "v3", "bridge", or "". */
- smartlist_t *PublishServerDescriptor;
- /** A bitfield of authority types, derived from PublishServerDescriptor. */
- dirinfo_type_t PublishServerDescriptor_;
- /** Boolean: do we publish hidden service descriptors to the HS auths? */
- int PublishHidServDescriptors;
- int FetchServerDescriptors; /**< Do we fetch server descriptors as normal? */
- int FetchHidServDescriptors; /**< and hidden service descriptors? */
-
- int MinUptimeHidServDirectoryV2; /**< As directory authority, accept hidden
- * service directories after what time? */
-
- int FetchUselessDescriptors; /**< Do we fetch non-running descriptors too? */
- int AllDirActionsPrivate; /**< Should every directory action be sent
- * through a Tor circuit? */
-
- /** Run in 'tor2web mode'? (I.e. only make client connections to hidden
- * services, and use a single hop for all hidden-service-related
- * circuits.) */
- int Tor2webMode;
-
- /** A routerset that should be used when picking RPs for HS circuits. */
- routerset_t *Tor2webRendezvousPoints;
-
- /** A routerset that should be used when picking middle nodes for HS
- * circuits. */
- routerset_t *HSLayer2Nodes;
-
- /** A routerset that should be used when picking third-hop nodes for HS
- * circuits. */
- routerset_t *HSLayer3Nodes;
-
- /** Onion Services in HiddenServiceSingleHopMode make one-hop (direct)
- * circuits between the onion service server, and the introduction and
- * rendezvous points. (Onion service descriptors are still posted using
- * 3-hop paths, to avoid onion service directories blocking the service.)
- * This option makes every hidden service instance hosted by
- * this tor instance a Single Onion Service.
- * HiddenServiceSingleHopMode requires HiddenServiceNonAnonymousMode to be
- * set to 1.
- * Use rend_service_allow_non_anonymous_connection() or
- * rend_service_reveal_startup_time() instead of using this option directly.
- */
- int HiddenServiceSingleHopMode;
- /* Makes hidden service clients and servers non-anonymous on this tor
- * instance. Allows the non-anonymous HiddenServiceSingleHopMode. Enables
- * non-anonymous behaviour in the hidden service protocol.
- * Use rend_service_non_anonymous_mode_enabled() instead of using this option
- * directly.
- */
- int HiddenServiceNonAnonymousMode;
-
- int ConnLimit; /**< Demanded minimum number of simultaneous connections. */
- int ConnLimit_; /**< Maximum allowed number of simultaneous connections. */
- int ConnLimit_high_thresh; /**< start trying to lower socket usage if we
- * have this many. */
- int ConnLimit_low_thresh; /**< try to get down to here after socket
- * exhaustion. */
- int RunAsDaemon; /**< If true, run in the background. (Unix only) */
- int FascistFirewall; /**< Whether to prefer ORs reachable on open ports. */
- smartlist_t *FirewallPorts; /**< Which ports our firewall allows
- * (strings). */
- config_line_t *ReachableAddresses; /**< IP:ports our firewall allows. */
- config_line_t *ReachableORAddresses; /**< IP:ports for OR conns. */
- config_line_t *ReachableDirAddresses; /**< IP:ports for Dir conns. */
-
- int ConstrainedSockets; /**< Shrink xmit and recv socket buffers. */
- uint64_t ConstrainedSockSize; /**< Size of constrained buffers. */
-
- /** Whether we should drop exit streams from Tors that we don't know are
- * relays. One of "0" (never refuse), "1" (always refuse), or "-1" (do
- * what the consensus says, defaulting to 'refuse' if the consensus says
- * nothing). */
- int RefuseUnknownExits;
-
- /** Application ports that require all nodes in circ to have sufficient
- * uptime. */
- smartlist_t *LongLivedPorts;
- /** Application ports that are likely to be unencrypted and
- * unauthenticated; we reject requests for them to prevent the
- * user from screwing up and leaking plaintext secrets to an
- * observer somewhere on the Internet. */
- smartlist_t *RejectPlaintextPorts;
- /** Related to RejectPlaintextPorts above, except this config option
- * controls whether we warn (in the log and via a controller status
- * event) every time a risky connection is attempted. */
- smartlist_t *WarnPlaintextPorts;
- /** Should we try to reuse the same exit node for a given host */
- smartlist_t *TrackHostExits;
- int TrackHostExitsExpire; /**< Number of seconds until we expire an
- * addressmap */
- config_line_t *AddressMap; /**< List of address map directives. */
- int AutomapHostsOnResolve; /**< If true, when we get a resolve request for a
- * hostname ending with one of the suffixes in
- * <b>AutomapHostsSuffixes</b>, map it to a
- * virtual address. */
- /** List of suffixes for <b>AutomapHostsOnResolve</b>. The special value
- * "." means "match everything." */
- smartlist_t *AutomapHostsSuffixes;
- int RendPostPeriod; /**< How often do we post each rendezvous service
- * descriptor? Remember to publish them independently. */
- int KeepalivePeriod; /**< How often do we send padding cells to keep
- * connections alive? */
- int SocksTimeout; /**< How long do we let a socks connection wait
- * unattached before we fail it? */
- int LearnCircuitBuildTimeout; /**< If non-zero, we attempt to learn a value
- * for CircuitBuildTimeout based on timeout
- * history. Use circuit_build_times_disabled()
- * rather than checking this value directly. */
- int CircuitBuildTimeout; /**< Cull non-open circuits that were born at
- * least this many seconds ago. Used until
- * adaptive algorithm learns a new value. */
- int CircuitsAvailableTimeout; /**< Try to have an open circuit for at
- least this long after last activity */
- int CircuitStreamTimeout; /**< If non-zero, detach streams from circuits
- * and try a new circuit if the stream has been
- * waiting for this many seconds. If zero, use
- * our default internal timeout schedule. */
- int MaxOnionQueueDelay; /*< DOCDOC */
- int NewCircuitPeriod; /**< How long do we use a circuit before building
- * a new one? */
- int MaxCircuitDirtiness; /**< Never use circs that were first used more than
- this interval ago. */
- uint64_t BandwidthRate; /**< How much bandwidth, on average, are we willing
- * to use in a second? */
- uint64_t BandwidthBurst; /**< How much bandwidth, at maximum, are we willing
- * to use in a second? */
- uint64_t MaxAdvertisedBandwidth; /**< How much bandwidth are we willing to
- * tell other nodes we have? */
- uint64_t RelayBandwidthRate; /**< How much bandwidth, on average, are we
- * willing to use for all relayed conns? */
- uint64_t RelayBandwidthBurst; /**< How much bandwidth, at maximum, will we
- * use in a second for all relayed conns? */
- uint64_t PerConnBWRate; /**< Long-term bw on a single TLS conn, if set. */
- uint64_t PerConnBWBurst; /**< Allowed burst on a single TLS conn, if set. */
- int NumCPUs; /**< How many CPUs should we try to use? */
- config_line_t *RendConfigLines; /**< List of configuration lines
- * for rendezvous services. */
- config_line_t *HidServAuth; /**< List of configuration lines for client-side
- * authorizations for hidden services */
- char *ContactInfo; /**< Contact info to be published in the directory. */
-
- int HeartbeatPeriod; /**< Log heartbeat messages after this many seconds
- * have passed. */
- int MainloopStats; /**< Log main loop statistics as part of the
- * heartbeat messages. */
-
- char *HTTPProxy; /**< hostname[:port] to use as http proxy, if any. */
- tor_addr_t HTTPProxyAddr; /**< Parsed IPv4 addr for http proxy, if any. */
- uint16_t HTTPProxyPort; /**< Parsed port for http proxy, if any. */
- char *HTTPProxyAuthenticator; /**< username:password string, if any. */
-
- char *HTTPSProxy; /**< hostname[:port] to use as https proxy, if any. */
- tor_addr_t HTTPSProxyAddr; /**< Parsed addr for https proxy, if any. */
- uint16_t HTTPSProxyPort; /**< Parsed port for https proxy, if any. */
- char *HTTPSProxyAuthenticator; /**< username:password string, if any. */
-
- char *Socks4Proxy; /**< hostname:port to use as a SOCKS4 proxy, if any. */
- tor_addr_t Socks4ProxyAddr; /**< Derived from Socks4Proxy. */
- uint16_t Socks4ProxyPort; /**< Derived from Socks4Proxy. */
-
- char *Socks5Proxy; /**< hostname:port to use as a SOCKS5 proxy, if any. */
- tor_addr_t Socks5ProxyAddr; /**< Derived from Sock5Proxy. */
- uint16_t Socks5ProxyPort; /**< Derived from Socks5Proxy. */
- char *Socks5ProxyUsername; /**< Username for SOCKS5 authentication, if any */
- char *Socks5ProxyPassword; /**< Password for SOCKS5 authentication, if any */
-
- /** List of configuration lines for replacement directory authorities.
- * If you just want to replace one class of authority at a time,
- * use the "Alternate*Authority" options below instead. */
- config_line_t *DirAuthorities;
-
- /** List of fallback directory servers */
- config_line_t *FallbackDir;
- /** Whether to use the default hard-coded FallbackDirs */
- int UseDefaultFallbackDirs;
-
- /** Weight to apply to all directory authority rates if considering them
- * along with fallbackdirs */
- double DirAuthorityFallbackRate;
-
- /** If set, use these main (currently v3) directory authorities and
- * not the default ones. */
- config_line_t *AlternateDirAuthority;
-
- /** If set, use these bridge authorities and not the default one. */
- config_line_t *AlternateBridgeAuthority;
-
- config_line_t *MyFamily_lines; /**< Declared family for this OR. */
- config_line_t *MyFamily; /**< Declared family for this OR, normalized */
- config_line_t *NodeFamilies; /**< List of config lines for
- * node families */
- smartlist_t *NodeFamilySets; /**< List of parsed NodeFamilies values. */
- config_line_t *AuthDirBadExit; /**< Address policy for descriptors to
- * mark as bad exits. */
- config_line_t *AuthDirReject; /**< Address policy for descriptors to
- * reject. */
- config_line_t *AuthDirInvalid; /**< Address policy for descriptors to
- * never mark as valid. */
- /** @name AuthDir...CC
- *
- * Lists of country codes to mark as BadExit, or Invalid, or to
- * reject entirely.
- *
- * @{
- */
- smartlist_t *AuthDirBadExitCCs;
- smartlist_t *AuthDirInvalidCCs;
- smartlist_t *AuthDirRejectCCs;
- /**@}*/
-
- int AuthDirListBadExits; /**< True iff we should list bad exits,
- * and vote for all other exits as good. */
- int AuthDirMaxServersPerAddr; /**< Do not permit more than this
- * number of servers per IP address. */
- int AuthDirHasIPv6Connectivity; /**< Boolean: are we on IPv6? */
- int AuthDirPinKeys; /**< Boolean: Do we enforce key-pinning? */
-
- /** If non-zero, always vote the Fast flag for any relay advertising
- * this amount of capacity or more. */
- uint64_t AuthDirFastGuarantee;
-
- /** If non-zero, this advertised capacity or more is always sufficient
- * to satisfy the bandwidth requirement for the Guard flag. */
- uint64_t AuthDirGuardBWGuarantee;
-
- char *AccountingStart; /**< How long is the accounting interval, and when
- * does it start? */
- uint64_t AccountingMax; /**< How many bytes do we allow per accounting
- * interval before hibernation? 0 for "never
- * hibernate." */
- /** How do we determine when our AccountingMax has been reached?
- * "max" for when in or out reaches AccountingMax
- * "sum" for when in plus out reaches AccountingMax
- * "in" for when in reaches AccountingMax
- * "out" for when out reaches AccountingMax */
- char *AccountingRule_option;
- enum { ACCT_MAX, ACCT_SUM, ACCT_IN, ACCT_OUT } AccountingRule;
-
- /** Base64-encoded hash of accepted passwords for the control system. */
- config_line_t *HashedControlPassword;
- /** As HashedControlPassword, but not saved. */
- config_line_t *HashedControlSessionPassword;
-
- int CookieAuthentication; /**< Boolean: do we enable cookie-based auth for
- * the control system? */
- char *CookieAuthFile; /**< Filesystem location of a ControlPort
- * authentication cookie. */
- char *ExtORPortCookieAuthFile; /**< Filesystem location of Extended
- * ORPort authentication cookie. */
- int CookieAuthFileGroupReadable; /**< Boolean: Is the CookieAuthFile g+r? */
- int ExtORPortCookieAuthFileGroupReadable; /**< Boolean: Is the
- * ExtORPortCookieAuthFile g+r? */
- int LeaveStreamsUnattached; /**< Boolean: Does Tor attach new streams to
- * circuits itself (0), or does it expect a controller
- * to cope? (1) */
- int DisablePredictedCircuits; /**< Boolean: does Tor preemptively
- * make circuits in the background (0),
- * or not (1)? */
-
- /** Process specifier for a controller that ‘owns’ this Tor
- * instance. Tor will terminate if its owning controller does. */
- char *OwningControllerProcess;
- /** FD specifier for a controller that owns this Tor instance. */
- int OwningControllerFD;
-
- int ShutdownWaitLength; /**< When we get a SIGINT and we're a server, how
- * long do we wait before exiting? */
- char *SafeLogging; /**< Contains "relay", "1", "0" (meaning no scrubbing). */
-
- /* Derived from SafeLogging */
- enum {
- SAFELOG_SCRUB_ALL, SAFELOG_SCRUB_RELAY, SAFELOG_SCRUB_NONE
- } SafeLogging_;
-
- int Sandbox; /**< Boolean: should sandboxing be enabled? */
- int SafeSocks; /**< Boolean: should we outright refuse application
- * connections that use socks4 or socks5-with-local-dns? */
- int ProtocolWarnings; /**< Boolean: when other parties screw up the Tor
- * protocol, is it a warn or an info in our logs? */
- int TestSocks; /**< Boolean: when we get a socks connection, do we loudly
- * log whether it was DNS-leaking or not? */
- int HardwareAccel; /**< Boolean: Should we enable OpenSSL hardware
- * acceleration where available? */
- /** Token Bucket Refill resolution in milliseconds. */
- int TokenBucketRefillInterval;
- char *AccelName; /**< Optional hardware acceleration engine name. */
- char *AccelDir; /**< Optional hardware acceleration engine search dir. */
-
- /** Boolean: Do we try to enter from a smallish number
- * of fixed nodes? */
- int UseEntryGuards_option;
- /** Internal variable to remember whether we're actually acting on
- * UseEntryGuards_option -- when we're a non-anonymous Tor2web client or
- * Single Onion Service, it is always false, otherwise we use the value of
- * UseEntryGuards_option. */
- int UseEntryGuards;
-
- int NumEntryGuards; /**< How many entry guards do we try to establish? */
-
- /** If 1, we use any guardfraction information we see in the
- * consensus. If 0, we don't. If -1, let the consensus parameter
- * decide. */
- int UseGuardFraction;
-
- int NumDirectoryGuards; /**< How many dir guards do we try to establish?
- * If 0, use value from NumEntryGuards. */
- int NumPrimaryGuards; /**< How many primary guards do we want? */
-
- int RephistTrackTime; /**< How many seconds do we keep rephist info? */
- /** Should we always fetch our dir info on the mirror schedule (which
- * means directly from the authorities) no matter our other config? */
- int FetchDirInfoEarly;
-
- /** Should we fetch our dir info at the start of the consensus period? */
- int FetchDirInfoExtraEarly;
-
- int DirCache; /**< Cache all directory documents and accept requests via
- * tunnelled dir conns from clients. If 1, enabled (default);
- * If 0, disabled. */
-
- char *VirtualAddrNetworkIPv4; /**< Address and mask to hand out for virtual
- * MAPADDRESS requests for IPv4 addresses */
- char *VirtualAddrNetworkIPv6; /**< Address and mask to hand out for virtual
- * MAPADDRESS requests for IPv6 addresses */
- int ServerDNSSearchDomains; /**< Boolean: If set, we don't force exit
- * addresses to be FQDNs, but rather search for them in
- * the local domains. */
- int ServerDNSDetectHijacking; /**< Boolean: If true, check for DNS failure
- * hijacking. */
- int ServerDNSRandomizeCase; /**< Boolean: Use the 0x20-hack to prevent
- * DNS poisoning attacks. */
- char *ServerDNSResolvConfFile; /**< If provided, we configure our internal
- * resolver from the file here rather than from
- * /etc/resolv.conf (Unix) or the registry (Windows). */
- char *DirPortFrontPage; /**< This is a full path to a file with an html
- disclaimer. This allows a server administrator to show
- that they're running Tor and anyone visiting their server
- will know this without any specialized knowledge. */
- int DisableDebuggerAttachment; /**< Currently Linux only specific attempt to
- disable ptrace; needs BSD testing. */
- /** Boolean: if set, we start even if our resolv.conf file is missing
- * or broken. */
- int ServerDNSAllowBrokenConfig;
- /** Boolean: if set, then even connections to private addresses will get
- * rate-limited. */
- int CountPrivateBandwidth;
- smartlist_t *ServerDNSTestAddresses; /**< A list of addresses that definitely
- * should be resolvable. Used for
- * testing our DNS server. */
- int EnforceDistinctSubnets; /**< If true, don't allow multiple routers in the
- * same network zone in the same circuit. */
- int AllowNonRFC953Hostnames; /**< If true, we allow connections to hostnames
- * with weird characters. */
- /** If true, we try resolving hostnames with weird characters. */
- int ServerDNSAllowNonRFC953Hostnames;
-
- /** If true, we try to download extra-info documents (and we serve them,
- * if we are a cache). For authorities, this is always true. */
- int DownloadExtraInfo;
-
- /** If true, we're configured to collect statistics on clients
- * requesting network statuses from us as directory. */
- int DirReqStatistics_option;
- /** Internal variable to remember whether we're actually acting on
- * DirReqStatistics_option -- yes if it's set and we're a server, else no. */
- int DirReqStatistics;
-
- /** If true, the user wants us to collect statistics on port usage. */
- int ExitPortStatistics;
-
- /** If true, the user wants us to collect connection statistics. */
- int ConnDirectionStatistics;
-
- /** If true, the user wants us to collect cell statistics. */
- int CellStatistics;
-
- /** If true, the user wants us to collect padding statistics. */
- int PaddingStatistics;
-
- /** If true, the user wants us to collect statistics as entry node. */
- int EntryStatistics;
-
- /** If true, the user wants us to collect statistics as hidden service
- * directory, introduction point, or rendezvous point. */
- int HiddenServiceStatistics_option;
- /** Internal variable to remember whether we're actually acting on
- * HiddenServiceStatistics_option -- yes if it's set and we're a server,
- * else no. */
- int HiddenServiceStatistics;
-
- /** If true, include statistics file contents in extra-info documents. */
- int ExtraInfoStatistics;
-
- /** If true, do not believe anybody who tells us that a domain resolves
- * to an internal address, or that an internal address has a PTR mapping.
- * Helps avoid some cross-site attacks. */
- int ClientDNSRejectInternalAddresses;
-
- /** If true, do not accept any requests to connect to internal addresses
- * over randomly chosen exits. */
- int ClientRejectInternalAddresses;
-
- /** If true, clients may connect over IPv4. If false, they will avoid
- * connecting over IPv4. We enforce this for OR and Dir connections. */
- 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
- * directly. */
- int ClientUseIPv6;
- /** If true, prefer an IPv6 OR port over an IPv4 one for entry node
- * connections. If auto, bridge clients prefer IPv6, and other clients
- * prefer IPv4. Use node_ipv6_or_preferred() instead of accessing this value
- * directly. */
- 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
- * accessing this value directly. */
- int ClientPreferIPv6DirPort;
-
- /** The length of time that we think a consensus should be fresh. */
- int V3AuthVotingInterval;
- /** The length of time we think it will take to distribute votes. */
- int V3AuthVoteDelay;
- /** The length of time we think it will take to distribute signatures. */
- int V3AuthDistDelay;
- /** The number of intervals we think a consensus should be valid. */
- int V3AuthNIntervalsValid;
-
- /** Should advertise and sign consensuses with a legacy key, for key
- * migration purposes? */
- int V3AuthUseLegacyKey;
-
- /** Location of bandwidth measurement file */
- char *V3BandwidthsFile;
-
- /** Location of guardfraction file */
- char *GuardfractionFile;
-
- /** Authority only: key=value pairs that we add to our networkstatus
- * consensus vote on the 'params' line. */
- char *ConsensusParams;
-
- /** Authority only: minimum number of measured bandwidths we must see
- * before we only believe measured bandwidths to assign flags. */
- int MinMeasuredBWsForAuthToIgnoreAdvertised;
-
- /** The length of time that we think an initial consensus should be fresh.
- * Only altered on testing networks. */
- int TestingV3AuthInitialVotingInterval;
-
- /** The length of time we think it will take to distribute initial votes.
- * Only altered on testing networks. */
- int TestingV3AuthInitialVoteDelay;
-
- /** The length of time we think it will take to distribute initial
- * signatures. Only altered on testing networks.*/
- int TestingV3AuthInitialDistDelay;
-
- /** Offset in seconds added to the starting time for consensus
- voting. Only altered on testing networks. */
- int TestingV3AuthVotingStartOffset;
-
- /** If an authority has been around for less than this amount of time, it
- * does not believe its reachability information is accurate. Only
- * altered on testing networks. */
- int TestingAuthDirTimeToLearnReachability;
-
- /** Clients don't download any descriptor this recent, since it will
- * probably not have propagated to enough caches. Only altered on testing
- * networks. */
- int TestingEstimatedDescriptorPropagationTime;
-
- /** Schedule for when servers should download things in general. Only
- * altered on testing networks. */
- int TestingServerDownloadInitialDelay;
-
- /** Schedule for when clients should download things in general. Only
- * altered on testing networks. */
- int TestingClientDownloadInitialDelay;
-
- /** Schedule for when servers should download consensuses. Only altered
- * on testing networks. */
- int TestingServerConsensusDownloadInitialDelay;
-
- /** Schedule for when clients should download consensuses. Only altered
- * on testing networks. */
- int TestingClientConsensusDownloadInitialDelay;
-
- /** Schedule for when clients should download consensuses from authorities
- * if they are bootstrapping (that is, they don't have a usable, reasonably
- * live consensus). Only used by clients fetching from a list of fallback
- * directory mirrors.
- *
- * This schedule is incremented by (potentially concurrent) connection
- * attempts, unlike other schedules, which are incremented by connection
- * failures. Only altered on testing networks. */
- int ClientBootstrapConsensusAuthorityDownloadInitialDelay;
-
- /** Schedule for when clients should download consensuses from fallback
- * directory mirrors if they are bootstrapping (that is, they don't have a
- * usable, reasonably live consensus). Only used by clients fetching from a
- * list of fallback directory mirrors.
- *
- * This schedule is incremented by (potentially concurrent) connection
- * attempts, unlike other schedules, which are incremented by connection
- * failures. Only altered on testing networks. */
- int ClientBootstrapConsensusFallbackDownloadInitialDelay;
-
- /** Schedule for when clients should download consensuses from authorities
- * if they are bootstrapping (that is, they don't have a usable, reasonably
- * live consensus). Only used by clients which don't have or won't fetch
- * from a list of fallback directory mirrors.
- *
- * This schedule is incremented by (potentially concurrent) connection
- * attempts, unlike other schedules, which are incremented by connection
- * failures. Only altered on testing networks. */
- int ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay;
-
- /** Schedule for when clients should download bridge descriptors. Only
- * altered on testing networks. */
- int TestingBridgeDownloadInitialDelay;
-
- /** Schedule for when clients should download bridge descriptors when they
- * have no running bridges. Only altered on testing networks. */
- int TestingBridgeBootstrapDownloadInitialDelay;
-
- /** When directory clients have only a few descriptors to request, they
- * batch them until they have more, or until this amount of time has
- * passed. Only altered on testing networks. */
- int TestingClientMaxIntervalWithoutRequest;
-
- /** How long do we let a directory connection stall before expiring
- * it? Only altered on testing networks. */
- int TestingDirConnectionMaxStall;
-
- /** How many simultaneous in-progress connections will we make when trying
- * to fetch a consensus before we wait for one to complete, timeout, or
- * error out? Only altered on testing networks. */
- int ClientBootstrapConsensusMaxInProgressTries;
-
- /** If true, we take part in a testing network. Change the defaults of a
- * couple of other configuration options and allow to change the values
- * of certain configuration options. */
- int TestingTorNetwork;
-
- /** Minimum value for the Exit flag threshold on testing networks. */
- uint64_t TestingMinExitFlagThreshold;
-
- /** Minimum value for the Fast flag threshold on testing networks. */
- uint64_t TestingMinFastFlagThreshold;
-
- /** Relays in a testing network which should be voted Exit
- * regardless of exit policy. */
- routerset_t *TestingDirAuthVoteExit;
- int TestingDirAuthVoteExitIsStrict;
-
- /** Relays in a testing network which should be voted Guard
- * regardless of uptime and bandwidth. */
- routerset_t *TestingDirAuthVoteGuard;
- int TestingDirAuthVoteGuardIsStrict;
-
- /** Relays in a testing network which should be voted HSDir
- * regardless of uptime and DirPort. */
- routerset_t *TestingDirAuthVoteHSDir;
- int TestingDirAuthVoteHSDirIsStrict;
-
- /** Enable CONN_BW events. Only altered on testing networks. */
- int TestingEnableConnBwEvent;
-
- /** Enable CELL_STATS events. Only altered on testing networks. */
- int TestingEnableCellStatsEvent;
-
- /** If true, and we have GeoIP data, and we're a bridge, keep a per-country
- * count of how many client addresses have contacted us so that we can help
- * the bridge authority guess which countries have blocked access to us. */
- int BridgeRecordUsageByCountry;
-
- /** Optionally, IPv4 and IPv6 GeoIP data. */
- char *GeoIPFile;
- char *GeoIPv6File;
-
- /** Autobool: if auto, then any attempt to Exclude{Exit,}Nodes a particular
- * country code will exclude all nodes in ?? and A1. If true, all nodes in
- * ?? and A1 are excluded. Has no effect if we don't know any GeoIP data. */
- int GeoIPExcludeUnknown;
-
- /** If true, SIGHUP should reload the torrc. Sometimes controllers want
- * to make this false. */
- int ReloadTorrcOnSIGHUP;
-
- /* The main parameter for picking circuits within a connection.
- *
- * If this value is positive, when picking a cell to relay on a connection,
- * we always relay from the circuit whose weighted cell count is lowest.
- * Cells are weighted exponentially such that if one cell is sent
- * 'CircuitPriorityHalflife' seconds before another, it counts for half as
- * much.
- *
- * If this value is zero, we're disabling the cell-EWMA algorithm.
- *
- * If this value is negative, we're using the default approach
- * according to either Tor or a parameter set in the consensus.
- */
- double CircuitPriorityHalflife;
-
- /** Set to true if the TestingTorNetwork configuration option is set.
- * This is used so that options_validate() has a chance to realize that
- * the defaults have changed. */
- int UsingTestNetworkDefaults_;
-
- /** If 1, we try to use microdescriptors to build circuits. If 0, we don't.
- * If -1, Tor decides. */
- int UseMicrodescriptors;
-
- /** File where we should write the ControlPort. */
- char *ControlPortWriteToFile;
- /** Should that file be group-readable? */
- int ControlPortFileGroupReadable;
-
-#define MAX_MAX_CLIENT_CIRCUITS_PENDING 1024
- /** Maximum number of non-open general-purpose origin circuits to allow at
- * 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;
-
- /**
- * Parameters for path-bias detection.
- * @{
- * These options override the default behavior of Tor's (**currently
- * experimental**) path bias detection algorithm. To try to find broken or
- * misbehaving guard nodes, Tor looks for nodes where more than a certain
- * fraction of circuits through that guard fail to get built.
- *
- * The PathBiasCircThreshold option controls how many circuits we need to
- * build through a guard before we make these checks. The
- * PathBiasNoticeRate, PathBiasWarnRate and PathBiasExtremeRate options
- * control what fraction of circuits must succeed through a guard so we
- * won't write log messages. If less than PathBiasExtremeRate circuits
- * succeed *and* PathBiasDropGuards is set to 1, we disable use of that
- * guard.
- *
- * When we have seen more than PathBiasScaleThreshold circuits through a
- * guard, we scale our observations by 0.5 (governed by the consensus) so
- * that new observations don't get swamped by old ones.
- *
- * By default, or if a negative value is provided for one of these options,
- * Tor uses reasonable defaults from the networkstatus consensus document.
- * If no defaults are available there, these options default to 150, .70,
- * .50, .30, 0, and 300 respectively.
- */
- int PathBiasCircThreshold;
- double PathBiasNoticeRate;
- double PathBiasWarnRate;
- double PathBiasExtremeRate;
- int PathBiasDropGuards;
- int PathBiasScaleThreshold;
- /** @} */
-
- /**
- * Parameters for path-bias use detection
- * @{
- * Similar to the above options, these options override the default behavior
- * of Tor's (**currently experimental**) path use bias detection algorithm.
- *
- * Where as the path bias parameters govern thresholds for successfully
- * building circuits, these four path use bias parameters govern thresholds
- * only for circuit usage. Circuits which receive no stream usage are not
- * counted by this detection algorithm. A used circuit is considered
- * successful if it is capable of carrying streams or otherwise receiving
- * well-formed responses to RELAY cells.
- *
- * By default, or if a negative value is provided for one of these options,
- * Tor uses reasonable defaults from the networkstatus consensus document.
- * If no defaults are available there, these options default to 20, .80,
- * .60, and 100, respectively.
- */
- int PathBiasUseThreshold;
- double PathBiasNoticeUseRate;
- double PathBiasExtremeUseRate;
- int PathBiasScaleUseThreshold;
- /** @} */
-
- int IPv6Exit; /**< Do we support exiting to IPv6 addresses? */
-
- /** Fraction: */
- double PathsNeededToBuildCircuits;
-
- /** What expiry time shall we place on our SSL certs? "0" means we
- * should guess a suitable value. */
- int SSLKeyLifetime;
-
- /** How long (seconds) do we keep a guard before picking a new one? */
- int GuardLifetime;
-
- /** Is this an exit node? This is a tristate, where "1" means "yes, and use
- * the default exit policy if none is given" and "0" means "no; exit policy
- * is 'reject *'" and "auto" (-1) means "same as 1, but warn the user."
- *
- * XXXX Eventually, the default will be 0. */
- int ExitRelay;
-
- /** For how long (seconds) do we declare our signing keys to be valid? */
- int SigningKeyLifetime;
- /** For how long (seconds) do we declare our link keys to be valid? */
- int TestingLinkCertLifetime;
- /** For how long (seconds) do we declare our auth keys to be valid? */
- int TestingAuthKeyLifetime;
-
- /** How long before signing keys expire will we try to make a new one? */
- int TestingSigningKeySlop;
- /** How long before link keys expire will we try to make a new one? */
- int TestingLinkKeySlop;
- /** How long before auth keys expire will we try to make a new one? */
- int TestingAuthKeySlop;
-
- /** Force use of offline master key features: never generate a master
- * ed25519 identity key except from tor --keygen */
- int OfflineMasterKey;
-
- enum {
- FORCE_PASSPHRASE_AUTO=0,
- FORCE_PASSPHRASE_ON,
- FORCE_PASSPHRASE_OFF
- } keygen_force_passphrase;
- int use_keygen_passphrase_fd;
- int keygen_passphrase_fd;
- int change_key_passphrase;
- char *master_key_fname;
-
- /** Autobool: Do we try to retain capabilities if we can? */
- int KeepBindCapabilities;
-
- /** Maximum total size of unparseable descriptors to log during the
- * lifetime of this Tor process.
- */
- uint64_t MaxUnparseableDescSizeToLog;
-
- /** Bool (default: 1): Switch for the shared random protocol. Only
- * relevant to a directory authority. If off, the authority won't
- * participate in the protocol. If on (default), a flag is added to the
- * vote indicating participation. */
- int AuthDirSharedRandomness;
-
- /** If 1, we skip all OOS checks. */
- int DisableOOSCheck;
-
- /** Autobool: Should we include Ed25519 identities in extend2 cells?
- * If -1, we should do whatever the consensus parameter says. */
- int ExtendByEd25519ID;
-
- /** Bool (default: 1): When testing routerinfos as a directory authority,
- * do we enforce Ed25519 identity match? */
- /* NOTE: remove this option someday. */
- int AuthDirTestEd25519LinkKeys;
-
- /** Bool (default: 0): Tells if a %include was used on torrc */
- int IncludeUsed;
-
- /** The seconds after expiration which we as a relay should keep old
- * consensuses around so that we can generate diffs from them. If 0,
- * use the default. */
- int MaxConsensusAgeForDiffs;
-
- /** Bool (default: 0). Tells Tor to never try to exec another program.
- */
- int NoExec;
-
- /** Have the KIST scheduler run every X milliseconds. If less than zero, do
- * not use the KIST scheduler but use the old vanilla scheduler instead. If
- * zero, do what the consensus says and fall back to using KIST as if this is
- * set to "10 msec" if the consensus doesn't say anything. */
- int KISTSchedRunInterval;
-
- /** A multiplier for the KIST per-socket limit calculation. */
- double KISTSockBufSizeFactor;
-
- /** The list of scheduler type string ordered by priority that is first one
- * has to be tried first. Default: KIST,KISTLite,Vanilla */
- smartlist_t *Schedulers;
- /* An ordered list of scheduler_types mapped from Schedulers. */
- smartlist_t *SchedulerTypes_;
-
- /** List of files that were opened by %include in torrc and torrc-defaults */
- smartlist_t *FilesOpenedByIncludes;
-
- /** If true, Tor shouldn't install any posix signal handlers, since it is
- * running embedded inside another process.
- */
- int DisableSignalHandlers;
-
- /** Autobool: Is the circuit creation DoS mitigation subsystem enabled? */
- int DoSCircuitCreationEnabled;
- /** Minimum concurrent connection needed from one single address before any
- * defense is used. */
- int DoSCircuitCreationMinConnections;
- /** Circuit rate used to refill the token bucket. */
- int DoSCircuitCreationRate;
- /** 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
- * 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
- * address. A random time delta is added to the defense time of an address
- * which will be between 1 second and half of this value. */
- int DoSCircuitCreationDefenseTimePeriod;
-
- /** Autobool: Is the DoS connection mitigation subsystem enabled? */
- int DoSConnectionEnabled;
- /** Maximum concurrent connection allowed per address. */
- int DoSConnectionMaxConcurrentCount;
- /** When an address is reaches the maximum count, what defense should be
- * used against it. See the dos_conn_defense_type_t enum. */
- int DoSConnectionDefenseType;
-
- /** Autobool: Do we refuse single hop client rendezvous? */
- int DoSRefuseSingleHopClientRendezvous;
-} or_options_t;
-
-#define LOG_PROTOCOL_WARN (get_protocol_warning_severity_level())
-
-/** Persistent state for an onion router, as saved to disk. */
-typedef struct {
- 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
- * should be saved right away. */
- time_t next_write;
-
- /** When was the state last written to disk? */
- time_t LastWritten;
-
- /** Fields for accounting bandwidth use. */
- time_t AccountingIntervalStart;
- uint64_t AccountingBytesReadInInterval;
- uint64_t AccountingBytesWrittenInInterval;
- int AccountingSecondsActive;
- int AccountingSecondsToReachSoftLimit;
- time_t AccountingSoftLimitHitAt;
- uint64_t AccountingBytesAtSoftLimit;
- uint64_t AccountingExpectedUsage;
-
- /** A list of Entry Guard-related configuration lines. (pre-prop271) */
- config_line_t *EntryGuards;
-
- /** A list of guard-related configuration lines. (post-prop271) */
- config_line_t *Guard;
-
- config_line_t *TransportProxies;
-
- /** Cached revision counters for active hidden services on this host */
- 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,
- * of the entries of Values. The "Values" lists hold decimal string
- * representations of the number of bytes read or written in each
- * interval. The "Maxima" list holds decimal strings describing the highest
- * rate achieved during the interval.
- */
- time_t BWHistoryReadEnds;
- int BWHistoryReadInterval;
- smartlist_t *BWHistoryReadValues;
- smartlist_t *BWHistoryReadMaxima;
- time_t BWHistoryWriteEnds;
- int BWHistoryWriteInterval;
- smartlist_t *BWHistoryWriteValues;
- smartlist_t *BWHistoryWriteMaxima;
- time_t BWHistoryDirReadEnds;
- int BWHistoryDirReadInterval;
- smartlist_t *BWHistoryDirReadValues;
- smartlist_t *BWHistoryDirReadMaxima;
- time_t BWHistoryDirWriteEnds;
- int BWHistoryDirWriteInterval;
- smartlist_t *BWHistoryDirWriteValues;
- smartlist_t *BWHistoryDirWriteMaxima;
-
- /** Build time histogram */
- config_line_t * BuildtimeHistogram;
- int TotalBuildTimes;
- int CircuitBuildAbandonedCount;
-
- /** What version of Tor wrote this state file? */
- char *TorVersion;
-
- /** Holds any unrecognized values we found in the state file, in the order
- * in which we found them. */
- config_line_t *ExtraLines;
-
- /** When did we last rotate our onion key? "0" for 'no idea'. */
- time_t LastRotatedOnionKey;
-} or_state_t;
-
-#define MAX_SOCKS_REPLY_LEN 1024
-#define MAX_SOCKS_ADDR_LEN 256
-#define SOCKS_NO_AUTH 0x00
-#define SOCKS_USER_PASS 0x02
-
-/** Please open a TCP connection to this addr:port. */
-#define SOCKS_COMMAND_CONNECT 0x01
-/** Please turn this FQDN into an IP address, privately. */
-#define SOCKS_COMMAND_RESOLVE 0xF0
-/** Please turn this IP address into an FQDN, privately. */
-#define SOCKS_COMMAND_RESOLVE_PTR 0xF1
-
-/* || 0 is for -Wparentheses-equality (-Wall?) appeasement under clang */
-#define SOCKS_COMMAND_IS_CONNECT(c) (((c)==SOCKS_COMMAND_CONNECT) || 0)
-#define SOCKS_COMMAND_IS_RESOLVE(c) ((c)==SOCKS_COMMAND_RESOLVE || \
- (c)==SOCKS_COMMAND_RESOLVE_PTR)
-
-/** State of a SOCKS request from a user to an OP. Also used to encode other
- * information for non-socks user request (such as those on TransPort and
- * DNSPort) */
-struct socks_request_t {
- /** Which version of SOCKS did the client use? One of "0, 4, 5" -- where
- * 0 means that no socks handshake ever took place, and this is just a
- * stub connection (e.g. see connection_ap_make_link()). */
- uint8_t socks_version;
- /** If using socks5 authentication, which authentication type did we
- * negotiate? currently we support 0 (no authentication) and 2
- * (username/password). */
- uint8_t auth_type;
- /** What is this stream's goal? One of the SOCKS_COMMAND_* values */
- uint8_t command;
- /** Which kind of listener created this stream? */
- uint8_t listener_type;
- size_t replylen; /**< Length of <b>reply</b>. */
- uint8_t reply[MAX_SOCKS_REPLY_LEN]; /**< Write an entry into this string if
- * we want to specify our own socks reply,
- * rather than using the default socks4 or
- * socks5 socks reply. We use this for the
- * two-stage socks5 handshake.
- */
- char address[MAX_SOCKS_ADDR_LEN]; /**< What address did the client ask to
- connect to/resolve? */
- uint16_t port; /**< What port did the client ask to connect to? */
- unsigned int has_finished : 1; /**< Has the SOCKS handshake finished? Used to
- * make sure we send back a socks reply for
- * every connection. */
- unsigned int got_auth : 1; /**< Have we received any authentication data? */
- /** If this is set, we will choose "no authentication" instead of
- * "username/password" authentication if both are offered. Used as input to
- * parse_socks. */
- unsigned int socks_prefer_no_auth : 1;
-
- /** Number of bytes in username; 0 if username is NULL */
- size_t usernamelen;
- /** Number of bytes in password; 0 if password is NULL */
- uint8_t passwordlen;
- /** The negotiated username value if any (for socks5), or the entire
- * authentication string (for socks4). This value is NOT nul-terminated;
- * see usernamelen for its length. */
- char *username;
- /** The negotiated password value if any (for socks5). This value is NOT
- * nul-terminated; see passwordlen for its length. */
- char *password;
-};
-
-/********************************* circuitbuild.c **********************/
-
-/** How many hops does a general-purpose circuit have by default? */
-#define DEFAULT_ROUTE_LEN 3
-
-/* Circuit Build Timeout "public" structures. */
-
-/** Precision multiplier for the Bw weights */
-#define BW_WEIGHT_SCALE 10000
-#define BW_MIN_WEIGHT_SCALE 1
-#define BW_MAX_WEIGHT_SCALE INT32_MAX
-
-/** Total size of the circuit timeout history to accumulate.
- * 1000 is approx 2.5 days worth of continual-use circuits. */
-#define CBT_NCIRCUITS_TO_OBSERVE 1000
-
-/** Width of the histogram bins in milliseconds */
-#define CBT_BIN_WIDTH ((build_time_t)50)
-
-/** Number of modes to use in the weighted-avg computation of Xm */
-#define CBT_DEFAULT_NUM_XM_MODES 3
-#define CBT_MIN_NUM_XM_MODES 1
-#define CBT_MAX_NUM_XM_MODES 20
-
-/** A build_time_t is milliseconds */
-typedef uint32_t build_time_t;
-
-/**
- * CBT_BUILD_ABANDONED is our flag value to represent a force-closed
- * circuit (Aka a 'right-censored' pareto value).
- */
-#define CBT_BUILD_ABANDONED ((build_time_t)(INT32_MAX-1))
-#define CBT_BUILD_TIME_MAX ((build_time_t)(INT32_MAX))
-
-/** Save state every 10 circuits */
-#define CBT_SAVE_STATE_EVERY 10
-
-/* Circuit build times consensus parameters */
-
-/**
- * How long to wait before actually closing circuits that take too long to
- * build in terms of CDF quantile.
- */
-#define CBT_DEFAULT_CLOSE_QUANTILE 95
-#define CBT_MIN_CLOSE_QUANTILE CBT_MIN_QUANTILE_CUTOFF
-#define CBT_MAX_CLOSE_QUANTILE CBT_MAX_QUANTILE_CUTOFF
-
-/**
- * How many circuits count as recent when considering if the
- * connection has gone gimpy or changed.
- */
-#define CBT_DEFAULT_RECENT_CIRCUITS 20
-#define CBT_MIN_RECENT_CIRCUITS 3
-#define CBT_MAX_RECENT_CIRCUITS 1000
-
-/**
- * Maximum count of timeouts that finish the first hop in the past
- * RECENT_CIRCUITS before calculating a new timeout.
- *
- * This tells us whether to abandon timeout history and set
- * the timeout back to whatever circuit_build_times_get_initial_timeout()
- * gives us.
- */
-#define CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT (CBT_DEFAULT_RECENT_CIRCUITS*9/10)
-#define CBT_MIN_MAX_RECENT_TIMEOUT_COUNT 3
-#define CBT_MAX_MAX_RECENT_TIMEOUT_COUNT 10000
-
-/** Minimum circuits before estimating a timeout */
-#define CBT_DEFAULT_MIN_CIRCUITS_TO_OBSERVE 100
-#define CBT_MIN_MIN_CIRCUITS_TO_OBSERVE 1
-#define CBT_MAX_MIN_CIRCUITS_TO_OBSERVE 10000
-
-/** Cutoff percentile on the CDF for our timeout estimation. */
-#define CBT_DEFAULT_QUANTILE_CUTOFF 80
-#define CBT_MIN_QUANTILE_CUTOFF 10
-#define CBT_MAX_QUANTILE_CUTOFF 99
-double circuit_build_times_quantile_cutoff(void);
-
-/** How often in seconds should we build a test circuit */
-#define CBT_DEFAULT_TEST_FREQUENCY 10
-#define CBT_MIN_TEST_FREQUENCY 1
-#define CBT_MAX_TEST_FREQUENCY INT32_MAX
-
-/** Lowest allowable value for CircuitBuildTimeout in milliseconds */
-#define CBT_DEFAULT_TIMEOUT_MIN_VALUE (1500)
-#define CBT_MIN_TIMEOUT_MIN_VALUE 500
-#define CBT_MAX_TIMEOUT_MIN_VALUE INT32_MAX
-
-/** Initial circuit build timeout in milliseconds */
-#define CBT_DEFAULT_TIMEOUT_INITIAL_VALUE (60*1000)
-#define CBT_MIN_TIMEOUT_INITIAL_VALUE CBT_MIN_TIMEOUT_MIN_VALUE
-#define CBT_MAX_TIMEOUT_INITIAL_VALUE INT32_MAX
-int32_t circuit_build_times_initial_timeout(void);
-
-#if CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT < CBT_MIN_MAX_RECENT_TIMEOUT_COUNT
-#error "RECENT_CIRCUITS is set too low."
-#endif
-
-/** Information about the state of our local network connection */
-typedef struct {
- /** The timestamp we last completed a TLS handshake or received a cell */
- time_t network_last_live;
- /** If the network is not live, how many timeouts has this caused? */
- int nonlive_timeouts;
- /** Circular array of circuits that have made it to the first hop. Slot is
- * 1 if circuit timed out, 0 if circuit succeeded */
- int8_t *timeouts_after_firsthop;
- /** Number of elements allocated for the above array */
- int num_recent_circs;
- /** Index into circular array. */
- int after_firsthop_idx;
-} network_liveness_t;
-
-typedef struct circuit_build_times_s circuit_build_times_t;
-
-/********************************* config.c ***************************/
-
-/** An error from options_trial_assign() or options_init_from_string(). */
-typedef enum setopt_err_t {
- SETOPT_OK = 0,
- SETOPT_ERR_MISC = -1,
- SETOPT_ERR_PARSE = -2,
- SETOPT_ERR_TRANSITION = -3,
- SETOPT_ERR_SETTING = -4,
-} setopt_err_t;
-
-/********************************* connection_edge.c *************************/
-
-/** Enumerates possible origins of a client-side address mapping. */
-typedef enum {
- /** We're remapping this address because the controller told us to. */
- ADDRMAPSRC_CONTROLLER,
- /** We're remapping this address because of an AutomapHostsOnResolve
- * configuration. */
- ADDRMAPSRC_AUTOMAP,
- /** We're remapping this address because our configuration (via torrc, the
- * command line, or a SETCONF command) told us to. */
- ADDRMAPSRC_TORRC,
- /** We're remapping this address because we have TrackHostExit configured,
- * and we want to remember to use the same exit next time. */
- ADDRMAPSRC_TRACKEXIT,
- /** We're remapping this address because we got a DNS resolution from a
- * Tor server that told us what its value was. */
- ADDRMAPSRC_DNS,
-
- /** No remapping has occurred. This isn't a possible value for an
- * addrmap_entry_t; it's used as a null value when we need to answer "Why
- * did this remapping happen." */
- ADDRMAPSRC_NONE
-} addressmap_entry_source_t;
-#define addressmap_entry_source_bitfield_t ENUM_BF(addressmap_entry_source_t)
-
-/********************************* control.c ***************************/
-
-/** Used to indicate the type of a circuit event passed to the controller.
- * The various types are defined in control-spec.txt */
-typedef enum circuit_status_event_t {
- CIRC_EVENT_LAUNCHED = 0,
- CIRC_EVENT_BUILT = 1,
- CIRC_EVENT_EXTENDED = 2,
- CIRC_EVENT_FAILED = 3,
- CIRC_EVENT_CLOSED = 4,
-} circuit_status_event_t;
-
-/** Used to indicate the type of a CIRC_MINOR event passed to the controller.
- * The various types are defined in control-spec.txt . */
-typedef enum circuit_status_minor_event_t {
- CIRC_MINOR_EVENT_PURPOSE_CHANGED,
- CIRC_MINOR_EVENT_CANNIBALIZED,
-} circuit_status_minor_event_t;
-
-/** Used to indicate the type of a stream event passed to the controller.
- * The various types are defined in control-spec.txt */
-typedef enum stream_status_event_t {
- STREAM_EVENT_SENT_CONNECT = 0,
- STREAM_EVENT_SENT_RESOLVE = 1,
- STREAM_EVENT_SUCCEEDED = 2,
- STREAM_EVENT_FAILED = 3,
- STREAM_EVENT_CLOSED = 4,
- STREAM_EVENT_NEW = 5,
- STREAM_EVENT_NEW_RESOLVE = 6,
- STREAM_EVENT_FAILED_RETRIABLE = 7,
- STREAM_EVENT_REMAP = 8
-} stream_status_event_t;
-
-/** Used to indicate the type of an OR connection event passed to the
- * controller. The various types are defined in control-spec.txt */
-typedef enum or_conn_status_event_t {
- OR_CONN_EVENT_LAUNCHED = 0,
- OR_CONN_EVENT_CONNECTED = 1,
- OR_CONN_EVENT_FAILED = 2,
- OR_CONN_EVENT_CLOSED = 3,
- OR_CONN_EVENT_NEW = 4,
-} or_conn_status_event_t;
-
-/** Used to indicate the type of a buildtime event */
-typedef enum buildtimeout_set_event_t {
- BUILDTIMEOUT_SET_EVENT_COMPUTED = 0,
- BUILDTIMEOUT_SET_EVENT_RESET = 1,
- BUILDTIMEOUT_SET_EVENT_SUSPENDED = 2,
- BUILDTIMEOUT_SET_EVENT_DISCARD = 3,
- BUILDTIMEOUT_SET_EVENT_RESUME = 4
-} buildtimeout_set_event_t;
-
-/** Execute the statement <b>stmt</b>, which may log events concerning the
- * connection <b>conn</b>. To prevent infinite loops, disable log messages
- * being sent to controllers if <b>conn</b> is a control connection.
- *
- * Stmt must not contain any return or goto statements.
- */
-#define CONN_LOG_PROTECT(conn, stmt) \
- STMT_BEGIN \
- int _log_conn_is_control; \
- tor_assert(conn); \
- _log_conn_is_control = (conn->type == CONN_TYPE_CONTROL); \
- if (_log_conn_is_control) \
- disable_control_logging(); \
- STMT_BEGIN stmt; STMT_END; \
- if (_log_conn_is_control) \
- enable_control_logging(); \
- STMT_END
-
-/** Enum describing various stages of bootstrapping, for use with controller
- * bootstrap status events. The values range from 0 to 100. */
-typedef enum {
- BOOTSTRAP_STATUS_UNDEF=-1,
- BOOTSTRAP_STATUS_STARTING=0,
- BOOTSTRAP_STATUS_CONN_DIR=5,
- BOOTSTRAP_STATUS_HANDSHAKE=-2,
- BOOTSTRAP_STATUS_HANDSHAKE_DIR=10,
- BOOTSTRAP_STATUS_ONEHOP_CREATE=15,
- BOOTSTRAP_STATUS_REQUESTING_STATUS=20,
- BOOTSTRAP_STATUS_LOADING_STATUS=25,
- BOOTSTRAP_STATUS_LOADING_KEYS=40,
- BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS=45,
- BOOTSTRAP_STATUS_LOADING_DESCRIPTORS=50,
- BOOTSTRAP_STATUS_CONN_OR=80,
- BOOTSTRAP_STATUS_HANDSHAKE_OR=85,
- BOOTSTRAP_STATUS_CIRCUIT_CREATE=90,
- BOOTSTRAP_STATUS_DONE=100
-} bootstrap_status_t;
-
-/********************************* directory.c ***************************/
-
-/** A pair of digests created by dir_split_resource_info_fingerprint_pairs() */
-typedef struct {
- char first[DIGEST_LEN];
- char second[DIGEST_LEN];
-} fp_pair_t;
-
-/********************************* dirserv.c ***************************/
-
-/** An enum to describe what format we're generating a routerstatus line in.
- */
-typedef enum {
- /** For use in a v2 opinion */
- NS_V2,
- /** For use in a consensus networkstatus document (ns flavor) */
- NS_V3_CONSENSUS,
- /** For use in a vote networkstatus document */
- NS_V3_VOTE,
- /** For passing to the controlport in response to a GETINFO request */
- NS_CONTROL_PORT,
- /** For use in a consensus networkstatus document (microdesc flavor) */
- NS_V3_CONSENSUS_MICRODESC
-} routerstatus_format_type_t;
-
-#ifdef DIRSERV_PRIVATE
-typedef struct measured_bw_line_t {
- char node_id[DIGEST_LEN];
- char node_hex[MAX_HEX_NICKNAME_LEN+1];
- long int bw_kb;
-} measured_bw_line_t;
-
-#endif /* defined(DIRSERV_PRIVATE) */
-
-/********************************* dirvote.c ************************/
-
-/** Describes the schedule by which votes should be generated. */
-typedef struct vote_timing_t {
- /** Length in seconds between one consensus becoming valid and the next
- * becoming valid. */
- int vote_interval;
- /** For how many intervals is a consensus valid? */
- int n_intervals_valid;
- /** Time in seconds allowed to propagate votes */
- int vote_delay;
- /** Time in seconds allowed to propagate signatures */
- int dist_delay;
-} vote_timing_t;
-
-/********************************* geoip.c **************************/
-
-/** Indicates an action that we might be noting geoip statistics on.
- * Note that if we're noticing CONNECT, we're a bridge, and if we're noticing
- * the others, we're not.
- */
-typedef enum {
- /** We've noticed a connection as a bridge relay or entry guard. */
- GEOIP_CLIENT_CONNECT = 0,
- /** We've served a networkstatus consensus as a directory server. */
- GEOIP_CLIENT_NETWORKSTATUS = 1,
-} geoip_client_action_t;
-/** Indicates either a positive reply or a reason for rejectng a network
- * status request that will be included in geoip statistics. */
-typedef enum {
- /** Request is answered successfully. */
- GEOIP_SUCCESS = 0,
- /** V3 network status is not signed by a sufficient number of requested
- * authorities. */
- GEOIP_REJECT_NOT_ENOUGH_SIGS = 1,
- /** Requested network status object is unavailable. */
- GEOIP_REJECT_UNAVAILABLE = 2,
- /** Requested network status not found. */
- GEOIP_REJECT_NOT_FOUND = 3,
- /** Network status has not been modified since If-Modified-Since time. */
- GEOIP_REJECT_NOT_MODIFIED = 4,
- /** Directory is busy. */
- GEOIP_REJECT_BUSY = 5,
-} geoip_ns_response_t;
-#define GEOIP_NS_RESPONSE_NUM 6
-
-/** Directory requests that we are measuring can be either direct or
- * tunneled. */
-typedef enum {
- DIRREQ_DIRECT = 0,
- DIRREQ_TUNNELED = 1,
-} dirreq_type_t;
-
-/** Possible states for either direct or tunneled directory requests that
- * are relevant for determining network status download times. */
-typedef enum {
- /** Found that the client requests a network status; applies to both
- * direct and tunneled requests; initial state of a request that we are
- * measuring. */
- DIRREQ_IS_FOR_NETWORK_STATUS = 0,
- /** Finished writing a network status to the directory connection;
- * applies to both direct and tunneled requests; completes a direct
- * request. */
- DIRREQ_FLUSHING_DIR_CONN_FINISHED = 1,
- /** END cell sent to circuit that initiated a tunneled request. */
- DIRREQ_END_CELL_SENT = 2,
- /** Flushed last cell from queue of the circuit that initiated a
- * tunneled request to the outbuf of the OR connection. */
- DIRREQ_CIRC_QUEUE_FLUSHED = 3,
- /** Flushed last byte from buffer of the channel belonging to the
- * circuit that initiated a tunneled request; completes a tunneled
- * request. */
- DIRREQ_CHANNEL_BUFFER_FLUSHED = 4
-} dirreq_state_t;
-
-#define WRITE_STATS_INTERVAL (24*60*60)
-
-/********************************* microdesc.c *************************/
-
-typedef struct microdesc_cache_t microdesc_cache_t;
-
-/********************************* networkstatus.c *********************/
-
-/** Possible statuses of a version of Tor, given opinions from the directory
- * servers. */
-typedef enum version_status_t {
- VS_RECOMMENDED=0, /**< This version is listed as recommended. */
- VS_OLD=1, /**< This version is older than any recommended version. */
- VS_NEW=2, /**< This version is newer than any recommended version. */
- VS_NEW_IN_SERIES=3, /**< This version is newer than any recommended version
- * in its series, but later recommended versions exist.
- */
- VS_UNRECOMMENDED=4, /**< This version is not recommended (general case). */
- VS_EMPTY=5, /**< The version list was empty; no agreed-on versions. */
- VS_UNKNOWN, /**< We have no idea. */
-} version_status_t;
-
-/********************************* policies.c ************************/
-
-/** Outcome of applying an address policy to an address. */
-typedef enum {
- /** The address was accepted */
- ADDR_POLICY_ACCEPTED=0,
- /** The address was rejected */
- ADDR_POLICY_REJECTED=-1,
- /** Part of the address was unknown, but as far as we can tell, it was
- * accepted. */
- ADDR_POLICY_PROBABLY_ACCEPTED=1,
- /** Part of the address was unknown, but as far as we can tell, it was
- * rejected. */
- ADDR_POLICY_PROBABLY_REJECTED=2,
-} addr_policy_result_t;
-
-/********************************* rephist.c ***************************/
-
-/** Possible public/private key operations in Tor: used to keep track of where
- * we're spending our time. */
-typedef enum {
- SIGN_DIR, SIGN_RTR,
- VERIFY_DIR, VERIFY_RTR,
- ENC_ONIONSKIN, DEC_ONIONSKIN,
- TLS_HANDSHAKE_C, TLS_HANDSHAKE_S,
- REND_CLIENT, REND_MID, REND_SERVER,
-} pk_op_t;
-
-/********************************* rendcommon.c ***************************/
-
-/** Hidden-service side configuration of client authorization. */
-typedef struct rend_authorized_client_t {
- char *client_name;
- uint8_t descriptor_cookie[REND_DESC_COOKIE_LEN];
- crypto_pk_t *client_key;
-} rend_authorized_client_t;
-
-/** ASCII-encoded v2 hidden service descriptor. */
-typedef struct rend_encoded_v2_service_descriptor_t {
- char desc_id[DIGEST_LEN]; /**< Descriptor ID. */
- char *desc_str; /**< Descriptor string. */
-} rend_encoded_v2_service_descriptor_t;
-
-/** The maximum number of non-circuit-build-timeout failures a hidden
- * service client will tolerate while trying to build a circuit to an
- * introduction point. See also rend_intro_point_t.unreachable_count. */
-#define MAX_INTRO_POINT_REACHABILITY_FAILURES 5
-
-/** The minimum and maximum number of distinct INTRODUCE2 cells which a
- * hidden service's introduction point will receive before it begins to
- * expire. */
-#define INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS 16384
-/* Double the minimum value so the interval is [min, min * 2]. */
-#define INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS \
- (INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS * 2)
-
-/** The minimum number of seconds that an introduction point will last
- * before expiring due to old age. (If it receives
- * INTRO_POINT_LIFETIME_INTRODUCTIONS INTRODUCE2 cells, it may expire
- * sooner.)
- *
- * XXX Should this be configurable? */
-#define INTRO_POINT_LIFETIME_MIN_SECONDS (18*60*60)
-/** The maximum number of seconds that an introduction point will last
- * before expiring due to old age.
- *
- * XXX Should this be configurable? */
-#define INTRO_POINT_LIFETIME_MAX_SECONDS (24*60*60)
-
-/** The maximum number of circuit creation retry we do to an intro point
- * before giving up. We try to reuse intro point that fails during their
- * lifetime so this is a hard limit on the amount of time we do that. */
-#define MAX_INTRO_POINT_CIRCUIT_RETRIES 3
-
-/** Introduction point information. Used both in rend_service_t (on
- * the service side) and in rend_service_descriptor_t (on both the
- * client and service side). */
-typedef struct rend_intro_point_t {
- extend_info_t *extend_info; /**< Extend info for connecting to this
- * introduction point via a multi-hop path. */
- crypto_pk_t *intro_key; /**< Introduction key that replaces the service
- * key, if this descriptor is V2. */
-
- /** (Client side only) Flag indicating that a timeout has occurred
- * after sending an INTRODUCE cell to this intro point. After a
- * timeout, an intro point should not be tried again during the same
- * hidden service connection attempt, but it may be tried again
- * during a future connection attempt. */
- unsigned int timed_out : 1;
-
- /** (Client side only) The number of times we have failed to build a
- * circuit to this intro point for some reason other than our
- * circuit-build timeout. See also MAX_INTRO_POINT_REACHABILITY_FAILURES. */
- unsigned int unreachable_count : 3;
-
- /** (Service side only) Flag indicating that this intro point was
- * included in the last HS descriptor we generated. */
- unsigned int listed_in_last_desc : 1;
-
- /** (Service side only) A replay cache recording the RSA-encrypted parts
- * of INTRODUCE2 cells this intro point's circuit has received. This is
- * used to prevent replay attacks. */
- replaycache_t *accepted_intro_rsa_parts;
-
- /** (Service side only) Count of INTRODUCE2 cells accepted from this
- * intro point.
- */
- int accepted_introduce2_count;
-
- /** (Service side only) Maximum number of INTRODUCE2 cells that this IP
- * will accept. This is a random value between
- * INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS and
- * INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS. */
- int max_introductions;
-
- /** (Service side only) The time at which this intro point was first
- * published, or -1 if this intro point has not yet been
- * published. */
- time_t time_published;
-
- /** (Service side only) The time at which this intro point should
- * (start to) expire, or -1 if we haven't decided when this intro
- * point should expire. */
- time_t time_to_expire;
-
- /** (Service side only) The amount of circuit creation we've made to this
- * intro point. This is incremented every time we do a circuit relaunch on
- * this object which is triggered when the circuit dies but the node is
- * still in the consensus. After MAX_INTRO_POINT_CIRCUIT_RETRIES, we give
- * up on it. */
- unsigned int circuit_retries;
-
- /** (Service side only) Set if this intro point has an established circuit
- * and unset if it doesn't. */
- unsigned int circuit_established:1;
-} rend_intro_point_t;
-
-#define REND_PROTOCOL_VERSION_BITMASK_WIDTH 16
-
-/** Information used to connect to a hidden service. Used on both the
- * service side and the client side. */
-typedef struct rend_service_descriptor_t {
- crypto_pk_t *pk; /**< This service's public key. */
- int version; /**< Version of the descriptor format: 0 or 2. */
- time_t timestamp; /**< Time when the descriptor was generated. */
- /** Bitmask: which introduce/rendezvous protocols are supported?
- * (We allow bits '0', '1', '2' and '3' to be set.) */
- unsigned protocols : REND_PROTOCOL_VERSION_BITMASK_WIDTH;
- /** List of the service's introduction points. Elements are removed if
- * introduction attempts fail. */
- smartlist_t *intro_nodes;
- /** Has descriptor been uploaded to all hidden service directories? */
- int all_uploads_performed;
- /** List of hidden service directories to which an upload request for
- * this descriptor could be sent. Smartlist exists only when at least one
- * of the previous upload requests failed (otherwise it's not important
- * to know which uploads succeeded and which not). */
- smartlist_t *successful_uploads;
-} rend_service_descriptor_t;
-
-/********************************* routerlist.c ***************************/
-
-/** Represents information about a single trusted or fallback directory
- * server. */
-typedef struct dir_server_t {
- char *description;
- char *nickname;
- 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 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. */
- char v3_identity_digest[DIGEST_LEN]; /**< Digest of v3 (authority only,
- * high-security) identity key. */
-
- unsigned int is_running:1; /**< True iff we think this server is running. */
- unsigned int is_authority:1; /**< True iff this is a directory authority
- * of some kind. */
-
- /** True iff this server has accepted the most recent server descriptor
- * we tried to upload to it. */
- unsigned int has_accepted_serverdesc:1;
-
- /** What kind of authority is this? (Bitfield.) */
- dirinfo_type_t type;
-
- time_t addr_current_at; /**< When was the document that we derived the
- * address information from published? */
-
- routerstatus_t fake_status; /**< Used when we need to pass this trusted
- * dir_server_t to
- * directory_request_set_routerstatus.
- * as a routerstatus_t. Not updated by the
- * router-status management code!
- **/
-} dir_server_t;
-
-#define RELAY_REQUIRED_MIN_BANDWIDTH (75*1024)
-#define BRIDGE_REQUIRED_MIN_BANDWIDTH (50*1024)
-
-#define ROUTER_MAX_DECLARED_BANDWIDTH INT32_MAX
-
-/* Flags for pick_directory_server() and pick_trusteddirserver(). */
-/** Flag to indicate that we should not automatically be willing to use
- * ourself to answer a directory request.
- * Passed to router_pick_directory_server (et al).*/
-#define PDS_ALLOW_SELF (1<<0)
-/** Flag to indicate that if no servers seem to be up, we should mark all
- * directory servers as up and try again.
- * Passed to router_pick_directory_server (et al).*/
-#define PDS_RETRY_IF_NO_SERVERS (1<<1)
-/** Flag to indicate that we should not exclude directory servers that
- * our ReachableAddress settings would exclude. This usually means that
- * we're going to connect to the server over Tor, and so we don't need to
- * worry about our firewall telling us we can't.
- * Passed to router_pick_directory_server (et al).*/
-#define PDS_IGNORE_FASCISTFIREWALL (1<<2)
-/** Flag to indicate that we should not use any directory authority to which
- * we have an existing directory connection for downloading server descriptors
- * or extrainfo documents.
- *
- * Passed to router_pick_directory_server (et al)
- */
-#define PDS_NO_EXISTING_SERVERDESC_FETCH (1<<3)
-/** Flag to indicate that we should not use any directory authority to which
- * we have an existing directory connection for downloading microdescs.
- *
- * Passed to router_pick_directory_server (et al)
- */
-#define PDS_NO_EXISTING_MICRODESC_FETCH (1<<4)
-
-/** Possible ways to weight routers when choosing one randomly. See
- * routerlist_sl_choose_by_bandwidth() for more information.*/
-typedef enum bandwidth_weight_rule_t {
- NO_WEIGHTING, WEIGHT_FOR_EXIT, WEIGHT_FOR_MID, WEIGHT_FOR_GUARD,
- WEIGHT_FOR_DIR
-} bandwidth_weight_rule_t;
-
-/** Flags to be passed to control router_choose_random_node() to indicate what
- * kind of nodes to pick according to what algorithm. */
-typedef enum {
- CRN_NEED_UPTIME = 1<<0,
- 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,
- /* 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,
-} router_crn_flags_t;
-
-/** Return value for router_add_to_routerlist() and dirserv_add_descriptor() */
-typedef enum was_router_added_t {
- /* Router was added successfully. */
- ROUTER_ADDED_SUCCESSFULLY = 1,
- /* Extrainfo document was rejected because no corresponding router
- * descriptor was found OR router descriptor was rejected because
- * it was incompatible with its extrainfo document. */
- ROUTER_BAD_EI = -1,
- /* Router descriptor was rejected because it is already known. */
- ROUTER_IS_ALREADY_KNOWN = -2,
- /* General purpose router was rejected, because it was not listed
- * in consensus. */
- ROUTER_NOT_IN_CONSENSUS = -3,
- /* Router was neither in directory consensus nor in any of
- * networkstatus documents. Caching it to access later.
- * (Applies to fetched descriptors only.) */
- ROUTER_NOT_IN_CONSENSUS_OR_NETWORKSTATUS = -4,
- /* Router was rejected by directory authority. */
- ROUTER_AUTHDIR_REJECTS = -5,
- /* Bridge descriptor was rejected because such bridge was not one
- * of the bridges we have listed in our configuration. */
- ROUTER_WAS_NOT_WANTED = -6,
- /* Router descriptor was rejected because it was older than
- * OLD_ROUTER_DESC_MAX_AGE. */
- ROUTER_WAS_TOO_OLD = -7, /* note contrast with 'NOT_NEW' */
- /* DOCDOC */
- ROUTER_CERTS_EXPIRED = -8
-} was_router_added_t;
-
-/********************************* routerparse.c ************************/
-
-#define MAX_STATUS_TAG_LEN 32
-/** Structure to hold parsed Tor versions. This is a little messier
- * than we would like it to be, because we changed version schemes with 0.1.0.
- *
- * See version-spec.txt for the whole business.
- */
-typedef struct tor_version_t {
- int major;
- int minor;
- int micro;
- /** Release status. For version in the post-0.1 format, this is always
- * VER_RELEASE. */
- enum { VER_PRE=0, VER_RC=1, VER_RELEASE=2, } status;
- int patchlevel;
- char status_tag[MAX_STATUS_TAG_LEN];
- int svn_revision;
-
- int git_tag_len;
- char git_tag[DIGEST_LEN];
-} tor_version_t;
-
-#endif /* !defined(TOR_OR_H) */
-
diff --git a/src/rust/build.rs b/src/rust/build.rs
index b943aa5535..2cf85b404a 100644
--- a/src/rust/build.rs
+++ b/src/rust/build.rs
@@ -138,8 +138,7 @@ pub fn main() {
cfg.from_cflags("TOR_LDFLAGS_openssl");
cfg.from_cflags("TOR_LDFLAGS_libevent");
- cfg.link_relpath("src/common");
- cfg.link_relpath("src/ext/keccak-tiny");
+ cfg.link_relpath("src/lib");
cfg.link_relpath("src/ext/keccak-tiny");
cfg.link_relpath("src/ext/ed25519/ref10");
cfg.link_relpath("src/ext/ed25519/donna");
@@ -149,11 +148,23 @@ pub fn main() {
// will have dependencies on all the other rust packages that
// tor uses. We must be careful with factoring and dependencies
// moving forward!
- cfg.component("or-crypto-testing");
- cfg.component("or-ctime-testing");
- cfg.component("or-testing");
- cfg.component("or-event-testing");
- cfg.component("or-ctime-testing");
+ cfg.component("tor-crypt-ops-testing");
+ cfg.component("tor-sandbox");
+ cfg.component("tor-encoding-testing");
+ cfg.component("tor-net");
+ cfg.component("tor-thread-testing");
+ cfg.component("tor-memarea-testing");
+ cfg.component("tor-log");
+ cfg.component("tor-lock");
+ cfg.component("tor-fdio");
+ cfg.component("tor-container-testing");
+ cfg.component("tor-smartlist-core-testing");
+ cfg.component("tor-string-testing");
+ cfg.component("tor-malloc");
+ cfg.component("tor-wallclock");
+ cfg.component("tor-err-testing");
+ cfg.component("tor-intmath-testing");
+ cfg.component("tor-ctime-testing");
cfg.component("curve25519_donna");
cfg.component("keccak-tiny");
cfg.component("ed25519_ref10");
diff --git a/src/rust/external/external.rs b/src/rust/external/external.rs
index b9e17f021d..059fdd0df7 100644
--- a/src/rust/external/external.rs
+++ b/src/rust/external/external.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
use libc::{c_char, c_int};
@@ -11,7 +11,7 @@ extern "C" {
) -> c_int;
}
-/// Wrap calls to tor_version_as_new_as, defined in src/or/routerparse.c
+/// Wrap calls to tor_version_as_new_as, defined in routerparse.c
pub fn c_tor_version_as_new_as(platform: &str, cutoff: &str) -> bool {
// CHK: These functions should log a warning if an error occurs. This
// can be added when integration with tor's logger is added to rust
diff --git a/src/rust/protover/ffi.rs b/src/rust/protover/ffi.rs
index e3e545db75..3055893d43 100644
--- a/src/rust/protover/ffi.rs
+++ b/src/rust/protover/ffi.rs
@@ -1,9 +1,9 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
//! FFI functions, only to be called from C.
//!
-//! Equivalent C versions of this api are in `src/or/protover.c`
+//! Equivalent C versions of this api are in `protover.c`
use libc::{c_char, c_int, uint32_t};
use std::ffi::CStr;
@@ -18,7 +18,7 @@ use protover::*;
/// Translate C enums to Rust Proto enums, using the integer value of the C
/// enum to map to its associated Rust enum.
///
-/// C_RUST_COUPLED: src/or/protover.h `protocol_type_t`
+/// C_RUST_COUPLED: protover.h `protocol_type_t`
fn translate_to_rust(c_proto: uint32_t) -> Result<Protocol, ProtoverError> {
match c_proto {
0 => Ok(Protocol::Link),
diff --git a/src/rust/protover/lib.rs b/src/rust/protover/lib.rs
index ce964196fd..5da562c1e0 100644
--- a/src/rust/protover/lib.rs
+++ b/src/rust/protover/lib.rs
@@ -1,4 +1,4 @@
-//! Copyright (c) 2016-2017, The Tor Project, Inc. */
+//! Copyright (c) 2016-2018, The Tor Project, Inc. */
//! See LICENSE for licensing information */
//! Versioning information for different pieces of the Tor protocol.
diff --git a/src/rust/protover/protover.rs b/src/rust/protover/protover.rs
index d6ed2739fe..299e433722 100644
--- a/src/rust/protover/protover.rs
+++ b/src/rust/protover/protover.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
use std::collections::HashMap;
@@ -19,13 +19,13 @@ use protoset::ProtoSet;
/// Authorities should use this to decide whether to guess proto lines.
///
/// C_RUST_COUPLED:
-/// src/or/protover.h `FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS`
+/// protover.h `FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS`
const FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS: &'static str = "0.2.9.3-alpha";
/// The maximum number of subprotocol version numbers we will attempt to expand
/// before concluding that someone is trying to DoS us
///
-/// C_RUST_COUPLED: src/or/protover.c `MAX_PROTOCOLS_TO_EXPAND`
+/// C_RUST_COUPLED: protover.c `MAX_PROTOCOLS_TO_EXPAND`
const MAX_PROTOCOLS_TO_EXPAND: usize = (1<<16);
/// The maximum size an `UnknownProtocol`'s name may be.
@@ -33,7 +33,7 @@ pub(crate) const MAX_PROTOCOL_NAME_LENGTH: usize = 100;
/// Known subprotocols in Tor. Indicates which subprotocol a relay supports.
///
-/// C_RUST_COUPLED: src/or/protover.h `protocol_type_t`
+/// C_RUST_COUPLED: protover.h `protocol_type_t`
#[derive(Clone, Hash, Eq, PartialEq, Debug)]
pub enum Protocol {
Cons,
@@ -57,7 +57,7 @@ impl fmt::Display for Protocol {
/// Translates a string representation of a protocol into a Proto type.
/// Error if the string is an unrecognized protocol name.
///
-/// C_RUST_COUPLED: src/or/protover.c `PROTOCOL_NAMES`
+/// C_RUST_COUPLED: protover.c `PROTOCOL_NAMES`
impl FromStr for Protocol {
type Err = ProtoverError;
@@ -130,7 +130,7 @@ impl From<Protocol> for UnknownProtocol {
/// Rust code can use the `&'static CStr` as a normal `&'a str` by
/// calling `protover::get_supported_protocols`.
///
-// C_RUST_COUPLED: src/or/protover.c `protover_get_supported_protocols`
+// C_RUST_COUPLED: protover.c `protover_get_supported_protocols`
pub(crate) fn get_supported_protocols_cstr() -> &'static CStr {
cstr!("Cons=1-2 \
Desc=1-2 \
@@ -601,7 +601,7 @@ impl ProtoverVote {
/// let vote = ProtoverVote::compute(protos, &2);
/// assert_eq!("Link=3", vote.to_string());
/// ```
- // C_RUST_COUPLED: /src/or/protover.c protover_compute_vote
+ // C_RUST_COUPLED: protover.c protover_compute_vote
pub fn compute(proto_entries: &[UnvalidatedProtoEntry], threshold: &usize) -> UnvalidatedProtoEntry {
let mut all_count: ProtoverVote = ProtoverVote::default();
let mut final_output: UnvalidatedProtoEntry = UnvalidatedProtoEntry::default();
diff --git a/src/rust/protover/tests/protover.rs b/src/rust/protover/tests/protover.rs
index 2db01a1634..ac78d34b7a 100644
--- a/src/rust/protover/tests/protover.rs
+++ b/src/rust/protover/tests/protover.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
extern crate protover;
diff --git a/src/rust/smartlist/lib.rs b/src/rust/smartlist/lib.rs
index 14a8148315..2716842af2 100644
--- a/src/rust/smartlist/lib.rs
+++ b/src/rust/smartlist/lib.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
extern crate libc;
diff --git a/src/rust/smartlist/smartlist.rs b/src/rust/smartlist/smartlist.rs
index 2a822d89f4..747d22f78c 100644
--- a/src/rust/smartlist/smartlist.rs
+++ b/src/rust/smartlist/smartlist.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
use std::slice;
diff --git a/src/rust/tor_allocate/lib.rs b/src/rust/tor_allocate/lib.rs
index 937a5dcf63..5a355bc8d6 100644
--- a/src/rust/tor_allocate/lib.rs
+++ b/src/rust/tor_allocate/lib.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
//! Allocation helper functions that allow data to be allocated in Rust
diff --git a/src/rust/tor_allocate/tor_allocate.rs b/src/rust/tor_allocate/tor_allocate.rs
index 3c0037f139..47fa5fc593 100644
--- a/src/rust/tor_allocate/tor_allocate.rs
+++ b/src/rust/tor_allocate/tor_allocate.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
// No-op defined purely for testing at the module level
use libc::c_char;
diff --git a/src/rust/tor_log/lib.rs b/src/rust/tor_log/lib.rs
index 72f9e38339..21855ae73b 100644
--- a/src/rust/tor_log/lib.rs
+++ b/src/rust/tor_log/lib.rs
@@ -1,4 +1,4 @@
-//! Copyright (c) 2016-2017, The Tor Project, Inc. */
+//! Copyright (c) 2016-2018, The Tor Project, Inc. */
//! See LICENSE for licensing information */
//! Logging wrapper for Rust to utilize Tor's logger, found at
diff --git a/src/rust/tor_log/tor_log.rs b/src/rust/tor_log/tor_log.rs
index ad6725f0f2..49a1e7b158 100644
--- a/src/rust/tor_log/tor_log.rs
+++ b/src/rust/tor_log/tor_log.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
// Note that these functions are untested due to the fact that there are no
@@ -129,7 +129,7 @@ pub mod log {
}
/// The main entry point into Tor's logger. When in non-test mode, this
- /// will link directly with `tor_log_string` in /src/or/log.c
+ /// will link directly with `tor_log_string` in torlog.c
extern "C" {
pub fn tor_log_string(
severity: c_int,
diff --git a/src/rust/tor_rust/include.am b/src/rust/tor_rust/include.am
index bcf94193f4..ecc821a887 100644
--- a/src/rust/tor_rust/include.am
+++ b/src/rust/tor_rust/include.am
@@ -9,16 +9,16 @@ EXTRA_CARGO_OPTIONS=
CARGO_TARGET_DIR="$(abs_top_builddir)/src/rust/target" \
CARGO_HOME="$(abs_top_builddir)/src/rust" \
$(CARGO) build --release $(EXTRA_CARGO_OPTIONS) \
- $(CARGO_ONLINE) \
- --manifest-path "$(abs_top_srcdir)/src/rust/tor_rust/Cargo.toml" )
+ $(CARGO_ONLINE) \
+ --manifest-path "$(abs_top_srcdir)/src/rust/tor_rust/Cargo.toml" )
distclean-rust:
( cd "$(abs_top_builddir)/src/rust" ; \
CARGO_TARGET_DIR="$(abs_top_builddir)/src/rust/target" \
CARGO_HOME="$(abs_top_builddir)/src/rust" \
$(CARGO) clean $(EXTRA_CARGO_OPTIONS) \
- $(CARGO_ONLINE) \
- --manifest-path "$(abs_top_srcdir)/src/rust/tor_rust/Cargo.toml" )
+ $(CARGO_ONLINE) \
+ --manifest-path "$(abs_top_srcdir)/src/rust/tor_rust/Cargo.toml" )
rm -rf "$(abs_top_builddir)/src/rust/registry"
if USE_RUST
diff --git a/src/rust/tor_util/ffi.rs b/src/rust/tor_util/ffi.rs
index 32779ed476..4be154ff1e 100644
--- a/src/rust/tor_util/ffi.rs
+++ b/src/rust/tor_util/ffi.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
//! FFI functions to announce Rust support during tor startup, only to be
diff --git a/src/rust/tor_util/lib.rs b/src/rust/tor_util/lib.rs
index 94697b6069..4ce5fc9374 100644
--- a/src/rust/tor_util/lib.rs
+++ b/src/rust/tor_util/lib.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
//! Small module to announce Rust support during startup for demonstration
diff --git a/src/rust/tor_util/strings.rs b/src/rust/tor_util/strings.rs
index 505191d913..c365564e97 100644
--- a/src/rust/tor_util/strings.rs
+++ b/src/rust/tor_util/strings.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
//! Utilities for working with static strings.
diff --git a/src/test/bench.c b/src/test/bench.c
index 9ab23c9921..7919a4224f 100644
--- a/src/test/bench.c
+++ b/src/test/bench.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,21 +10,29 @@
#include "orconfig.h"
-#include "or.h"
-#include "onion_tap.h"
-#include "relay_crypto.h"
+#include "core/or/or.h"
+#include "core/crypto/onion_tap.h"
+#include "core/crypto/relay_crypto.h"
#include <openssl/opensslv.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/obj_mac.h>
-#include "config.h"
-#include "crypto_curve25519.h"
-#include "onion_ntor.h"
-#include "crypto_ed25519.h"
-#include "crypto_rand.h"
-#include "consdiff.h"
+#include "core/or/circuitlist.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "core/crypto/onion_ntor.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/dircommon/consdiff.h"
+#include "lib/compress/compress.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/or_circuit_st.h"
+
+#include "lib/crypt_ops/digestset.h"
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
static uint64_t nanostart;
@@ -371,7 +379,7 @@ bench_dmap(void)
crypto_rand(d, 20);
smartlist_add(sl2, tor_memdup(d, 20));
}
- printf("nbits=%d\n", ds->mask+1);
+ //printf("nbits=%d\n", ds->mask+1);
reset_perftime();
@@ -399,18 +407,20 @@ bench_dmap(void)
NANOCOUNT(pt3, pt4, iters*elts));
for (i = 0; i < iters; ++i) {
- SMARTLIST_FOREACH(sl, const char *, cp, n += digestset_contains(ds, cp));
- SMARTLIST_FOREACH(sl2, const char *, cp, n += digestset_contains(ds, cp));
+ SMARTLIST_FOREACH(sl, const char *, cp,
+ n += digestset_probably_contains(ds, cp));
+ SMARTLIST_FOREACH(sl2, const char *, cp,
+ n += digestset_probably_contains(ds, cp));
}
end = perftime();
- printf("digestset_contains: %.2f ns per element.\n",
+ printf("digestset_probably_contains: %.2f ns per element.\n",
NANOCOUNT(pt4, end, iters*elts*2));
/* We need to use this, or else the whole loop gets optimized out. */
printf("Hits == %d\n", n);
for (i = 0; i < fpostests; ++i) {
crypto_rand(d, 20);
- if (digestset_contains(ds, d)) ++fp;
+ if (digestset_probably_contains(ds, d)) ++fp;
}
printf("False positive rate on digestset: %.2f%%\n",
(fp/(double)fpostests)*100);
@@ -544,8 +554,8 @@ bench_dh(void)
reset_perftime();
start = perftime();
for (i = 0; i < iters; ++i) {
- char dh_pubkey_a[DH_BYTES], dh_pubkey_b[DH_BYTES];
- char secret_a[DH_BYTES], secret_b[DH_BYTES];
+ char dh_pubkey_a[DH1024_KEY_LEN], dh_pubkey_b[DH1024_KEY_LEN];
+ char secret_a[DH1024_KEY_LEN], secret_b[DH1024_KEY_LEN];
ssize_t slen_a, slen_b;
crypto_dh_t *dh_a = crypto_dh_new(DH_TYPE_TLS);
crypto_dh_t *dh_b = crypto_dh_new(DH_TYPE_TLS);
@@ -579,7 +589,7 @@ bench_ecdh_impl(int nid, const char *name)
reset_perftime();
start = perftime();
for (i = 0; i < iters; ++i) {
- char secret_a[DH_BYTES], secret_b[DH_BYTES];
+ char secret_a[DH1024_KEY_LEN], secret_b[DH1024_KEY_LEN];
ssize_t slen_a, slen_b;
EC_KEY *dh_a = EC_KEY_new_by_curve_name(nid);
EC_KEY *dh_b = EC_KEY_new_by_curve_name(nid);
@@ -590,10 +600,10 @@ bench_ecdh_impl(int nid, const char *name)
EC_KEY_generate_key(dh_a);
EC_KEY_generate_key(dh_b);
- slen_a = ECDH_compute_key(secret_a, DH_BYTES,
+ slen_a = ECDH_compute_key(secret_a, DH1024_KEY_LEN,
EC_KEY_get0_public_key(dh_b), dh_a,
NULL);
- slen_b = ECDH_compute_key(secret_b, DH_BYTES,
+ slen_b = ECDH_compute_key(secret_b, DH1024_KEY_LEN,
EC_KEY_get0_public_key(dh_a), dh_b,
NULL);
@@ -738,4 +748,3 @@ main(int argc, const char **argv)
return 0;
}
-
diff --git a/src/test/bt_test.py b/src/test/bt_test.py
index 4cb3326042..0eeb58c16c 100755
--- a/src/test/bt_test.py
+++ b/src/test/bt_test.py
@@ -1,4 +1,4 @@
-# Copyright 2013-2017, The Tor Project, Inc
+# Copyright 2013-2018, The Tor Project, Inc
# See LICENSE for licensing information
"""
diff --git a/src/test/ed25519_exts_ref.py b/src/test/ed25519_exts_ref.py
index f84d3002d3..a9090c9ed2 100644
--- a/src/test/ed25519_exts_ref.py
+++ b/src/test/ed25519_exts_ref.py
@@ -1,5 +1,5 @@
#!/usr/bin/python
-# Copyright 2014-2017, The Tor Project, Inc
+# Copyright 2014-2018, The Tor Project, Inc
# See LICENSE for licensing information
"""
diff --git a/src/test/fakechans.h b/src/test/fakechans.h
index ab5d8461b6..0770be8e04 100644
--- a/src/test/fakechans.h
+++ b/src/test/fakechans.h
@@ -1,4 +1,4 @@
- /* Copyright (c) 2014-2017, The Tor Project, Inc. */
+ /* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_FAKECHANS_H
diff --git a/src/test/fuzz/dict/http b/src/test/fuzz/dict/http
index 3b0531579d..63627ac380 100644
--- a/src/test/fuzz/dict/http
+++ b/src/test/fuzz/dict/http
@@ -4,7 +4,7 @@
#
# Extracted from directory_handle_command() in the tor source code
#
-# Copyright (c) 2016-2017, The Tor Project, Inc.
+# Copyright (c) 2016-2018, The Tor Project, Inc.
# See LICENSE for licensing information
#
# Usage:
diff --git a/src/test/fuzz/fuzz_consensus.c b/src/test/fuzz/fuzz_consensus.c
index 6610ade7ad..b170fd33d8 100644
--- a/src/test/fuzz/fuzz_consensus.c
+++ b/src/test/fuzz/fuzz_consensus.c
@@ -1,10 +1,12 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERPARSE_PRIVATE
-#include "or.h"
-#include "routerparse.h"
-#include "networkstatus.h"
-#include "fuzzing.h"
+#include "core/or/or.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/networkstatus.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "test/fuzz/fuzzing.h"
static void
mock_dump_desc__nodump(const char *desc, const char *type)
@@ -75,4 +77,3 @@ fuzz_main(const uint8_t *data, size_t sz)
tor_free(str);
return 0;
}
-
diff --git a/src/test/fuzz/fuzz_descriptor.c b/src/test/fuzz/fuzz_descriptor.c
index 1a50beae17..5a56f4081a 100644
--- a/src/test/fuzz/fuzz_descriptor.c
+++ b/src/test/fuzz/fuzz_descriptor.c
@@ -1,11 +1,11 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERPARSE_PRIVATE
-#include "or.h"
-#include "routerparse.h"
-#include "routerlist.h"
-#include "routerkeys.h"
-#include "fuzzing.h"
+#include "core/or/or.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/relay/routerkeys.h"
+#include "test/fuzz/fuzzing.h"
static int
mock_check_tap_onion_key_crosscert__nocheck(const uint8_t *crosscert,
diff --git a/src/test/fuzz/fuzz_diff.c b/src/test/fuzz/fuzz_diff.c
index 642380b512..1079856fdb 100644
--- a/src/test/fuzz/fuzz_diff.c
+++ b/src/test/fuzz/fuzz_diff.c
@@ -1,13 +1,13 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONSDIFF_PRIVATE
#include "orconfig.h"
-#include "or.h"
-#include "consdiff.h"
+#include "core/or/or.h"
+#include "feature/dircommon/consdiff.h"
-#include "fuzzing.h"
+#include "test/fuzz/fuzzing.h"
static int
mock_consensus_compute_digest_(const char *c, consensus_digest_t *d)
diff --git a/src/test/fuzz/fuzz_diff_apply.c b/src/test/fuzz/fuzz_diff_apply.c
index 8d7bf751bf..165d0e6126 100644
--- a/src/test/fuzz/fuzz_diff_apply.c
+++ b/src/test/fuzz/fuzz_diff_apply.c
@@ -1,13 +1,13 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONSDIFF_PRIVATE
#include "orconfig.h"
-#include "or.h"
-#include "consdiff.h"
+#include "core/or/or.h"
+#include "feature/dircommon/consdiff.h"
-#include "fuzzing.h"
+#include "test/fuzz/fuzzing.h"
static int
mock_consensus_compute_digest_(const char *c, consensus_digest_t *d)
diff --git a/src/test/fuzz/fuzz_extrainfo.c b/src/test/fuzz/fuzz_extrainfo.c
index 2a3de7ecf7..6c88f80122 100644
--- a/src/test/fuzz/fuzz_extrainfo.c
+++ b/src/test/fuzz/fuzz_extrainfo.c
@@ -1,11 +1,11 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERPARSE_PRIVATE
-#include "or.h"
-#include "routerparse.h"
-#include "routerlist.h"
-#include "routerkeys.h"
-#include "fuzzing.h"
+#include "core/or/or.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/relay/routerkeys.h"
+#include "test/fuzz/fuzzing.h"
static void
mock_dump_desc__nodump(const char *desc, const char *type)
diff --git a/src/test/fuzz/fuzz_hsdescv2.c b/src/test/fuzz/fuzz_hsdescv2.c
index 19db265716..fd5da41635 100644
--- a/src/test/fuzz/fuzz_hsdescv2.c
+++ b/src/test/fuzz/fuzz_hsdescv2.c
@@ -1,10 +1,11 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERPARSE_PRIVATE
-#include "or.h"
-#include "routerparse.h"
-#include "rendcommon.h"
-#include "fuzzing.h"
+#include "core/or/or.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/rend/rendcommon.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "test/fuzz/fuzzing.h"
static void
mock_dump_desc__nodump(const char *desc, const char *type)
@@ -49,4 +50,3 @@ fuzz_main(const uint8_t *data, size_t sz)
tor_free(str);
return 0;
}
-
diff --git a/src/test/fuzz/fuzz_hsdescv3.c b/src/test/fuzz/fuzz_hsdescv3.c
index 428774e330..4ec8db0a87 100644
--- a/src/test/fuzz/fuzz_hsdescv3.c
+++ b/src/test/fuzz/fuzz_hsdescv3.c
@@ -1,17 +1,16 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERPARSE_PRIVATE
#define HS_DESCRIPTOR_PRIVATE
-#include "or.h"
-#include "ed25519_cert.h" /* Trunnel interface. */
-#include "crypto_ed25519.h"
-#include "hs_descriptor.h"
-#include "routerparse.h"
-#include "util.h"
+#include "core/or/or.h"
+#include "trunnel/ed25519_cert.h" /* Trunnel interface. */
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "feature/hs/hs_descriptor.h"
+#include "feature/nodelist/routerparse.h"
-#include "fuzzing.h"
+#include "test/fuzz/fuzzing.h"
static void
mock_dump_desc__nodump(const char *desc, const char *type)
diff --git a/src/test/fuzz/fuzz_http.c b/src/test/fuzz/fuzz_http.c
index 2ffeb60244..61dc2144b4 100644
--- a/src/test/fuzz/fuzz_http.c
+++ b/src/test/fuzz/fuzz_http.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -6,15 +6,17 @@
#define BUFFERS_PRIVATE
#define DIRECTORY_PRIVATE
-#include "or.h"
-#include "backtrace.h"
-#include "buffers.h"
-#include "config.h"
-#include "connection.h"
-#include "directory.h"
-#include "torlog.h"
+#include "core/or/or.h"
+#include "lib/err/backtrace.h"
+#include "lib/container/buffers.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "feature/dircache/directory.h"
+#include "lib/log/torlog.h"
-#include "fuzzing.h"
+#include "feature/dircommon/dir_connection_st.h"
+
+#include "test/fuzz/fuzzing.h"
static void
mock_connection_write_to_buf_impl_(const char *string, size_t len,
diff --git a/src/test/fuzz/fuzz_http_connect.c b/src/test/fuzz/fuzz_http_connect.c
index dc674070b2..184bb52ee2 100644
--- a/src/test/fuzz/fuzz_http_connect.c
+++ b/src/test/fuzz/fuzz_http_connect.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -6,16 +6,19 @@
#define BUFFERS_PRIVATE
#define CONNECTION_EDGE_PRIVATE
-#include "or.h"
-#include "backtrace.h"
-#include "buffers.h"
-#include "config.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "proto_socks.h"
-#include "torlog.h"
+#include "core/or/or.h"
+#include "lib/err/backtrace.h"
+#include "lib/container/buffers.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "core/proto/proto_socks.h"
+#include "lib/log/torlog.h"
-#include "fuzzing.h"
+#include "core/or/entry_connection_st.h"
+#include "core/or/socks_request_st.h"
+
+#include "test/fuzz/fuzzing.h"
static void
mock_connection_write_to_buf_impl_(const char *string, size_t len,
diff --git a/src/test/fuzz/fuzz_iptsv2.c b/src/test/fuzz/fuzz_iptsv2.c
index 4abde0c16d..a3082f4d0e 100644
--- a/src/test/fuzz/fuzz_iptsv2.c
+++ b/src/test/fuzz/fuzz_iptsv2.c
@@ -1,10 +1,14 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERPARSE_PRIVATE
-#include "or.h"
-#include "routerparse.h"
-#include "rendcommon.h"
-#include "fuzzing.h"
+#include "core/or/or.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/rend/rendcommon.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+
+#include "feature/rend/rend_service_descriptor_st.h"
+
+#include "test/fuzz/fuzzing.h"
static void
mock_dump_desc__nodump(const char *desc, const char *type)
@@ -43,4 +47,3 @@ fuzz_main(const uint8_t *data, size_t sz)
rend_service_descriptor_free(desc);
return 0;
}
-
diff --git a/src/test/fuzz/fuzz_microdesc.c b/src/test/fuzz/fuzz_microdesc.c
index 396115026e..fa9676372d 100644
--- a/src/test/fuzz/fuzz_microdesc.c
+++ b/src/test/fuzz/fuzz_microdesc.c
@@ -1,10 +1,12 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERPARSE_PRIVATE
-#include "or.h"
-#include "routerparse.h"
-#include "microdesc.h"
-#include "fuzzing.h"
+#include "core/or/or.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/microdesc.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+
+#include "test/fuzz/fuzzing.h"
static void
mock_dump_desc__nodump(const char *desc, const char *type)
@@ -44,4 +46,3 @@ fuzz_main(const uint8_t *data, size_t sz)
}
return 0;
}
-
diff --git a/src/test/fuzz/fuzz_vrs.c b/src/test/fuzz/fuzz_vrs.c
index baf0610a0b..8c96851b1f 100644
--- a/src/test/fuzz/fuzz_vrs.c
+++ b/src/test/fuzz/fuzz_vrs.c
@@ -1,13 +1,18 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERPARSE_PRIVATE
#define NETWORKSTATUS_PRIVATE
-#include "or.h"
-#include "routerparse.h"
-#include "memarea.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "fuzzing.h"
+#include "core/or/or.h"
+#include "feature/nodelist/routerparse.h"
+#include "lib/memarea/memarea.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/vote_routerstatus_st.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+
+#include "test/fuzz/fuzzing.h"
static void
mock_dump_desc__nodump(const char *desc, const char *type)
@@ -79,4 +84,3 @@ fuzz_main(const uint8_t *data, size_t sz)
tor_free(str);
return 0;
}
-
diff --git a/src/test/fuzz/fuzzing.h b/src/test/fuzz/fuzzing.h
index aecdbb4e52..e90e5d58e0 100644
--- a/src/test/fuzz/fuzzing.h
+++ b/src/test/fuzz/fuzzing.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef FUZZING_H
#define FUZZING_H
diff --git a/src/test/fuzz/fuzzing_common.c b/src/test/fuzz/fuzzing_common.c
index a96552f0fc..0b3483bf66 100644
--- a/src/test/fuzz/fuzzing_common.c
+++ b/src/test/fuzz/fuzzing_common.c
@@ -1,13 +1,14 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CRYPTO_ED25519_PRIVATE
#include "orconfig.h"
-#include "or.h"
-#include "backtrace.h"
-#include "config.h"
-#include "fuzzing.h"
-#include "crypto.h"
-#include "crypto_ed25519.h"
+#include "core/or/or.h"
+#include "lib/err/backtrace.h"
+#include "app/config/config.h"
+#include "test/fuzz/fuzzing.h"
+#include "lib/compress/compress.h"
+#include "lib/crypt_ops/crypto.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
static or_options_t *mock_options = NULL;
static const or_options_t *
@@ -189,4 +190,3 @@ main(int argc, char **argv)
}
#endif
-
diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am
index cd16dc05be..87dfe91675 100644
--- a/src/test/fuzz/include.am
+++ b/src/test/fuzz/include.am
@@ -7,31 +7,17 @@ FUZZING_CFLAGS = \
FUZZING_LDFLAG = \
@TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@
FUZZING_LIBS = \
- src/or/libtor-testing.a \
- src/common/libor-crypto-testing.a \
- $(LIBKECCAK_TINY) \
- $(LIBDONNA) \
- src/common/libor-testing.a \
- src/common/libor-ctime-testing.a \
- src/common/libor-event-testing.a \
- src/trunnel/libor-trunnel-testing.a \
+ $(TOR_INTERNAL_TESTING_LIBS) \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \
@TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
- @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@ \
+ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@ \
@TOR_SYSTEMD_LIBS@ \
@TOR_LZMA_LIBS@ \
@TOR_ZSTD_LIBS@
oss-fuzz-prereqs: \
- src/or/libtor-testing.a \
- src/common/libor-crypto-testing.a \
- $(LIBKECCAK_TINY) \
- $(LIBDONNA) \
- src/common/libor-testing.a \
- src/common/libor-ctime-testing.a \
- src/common/libor-event-testing.a \
- src/trunnel/libor-trunnel-testing.a
+ $(TOR_INTERNAL_TESTING_LIBS)
noinst_HEADERS += \
src/test/fuzz/fuzzing.h
diff --git a/src/test/fuzz_static_testcases.sh b/src/test/fuzz_static_testcases.sh
index 3cb45ad5e6..138f85b106 100755
--- a/src/test/fuzz_static_testcases.sh
+++ b/src/test/fuzz_static_testcases.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-# Copyright (c) 2016-2017, The Tor Project, Inc.
+# Copyright (c) 2016-2018, The Tor Project, Inc.
# See LICENSE for licensing information
set -e
diff --git a/src/test/hs_ntor_ref.py b/src/test/hs_ntor_ref.py
index 542b02d2e0..0c5756ad73 100644
--- a/src/test/hs_ntor_ref.py
+++ b/src/test/hs_ntor_ref.py
@@ -1,5 +1,5 @@
#!/usr/bin/python
-# Copyright 2017, The Tor Project, Inc
+# Copyright 2017-2018, The Tor Project, Inc
# See LICENSE for licensing information
"""
diff --git a/src/test/hs_test_helpers.c b/src/test/hs_test_helpers.c
index 5c1b9123d8..afe3eafa2f 100644
--- a/src/test/hs_test_helpers.c
+++ b/src/test/hs_test_helpers.c
@@ -1,13 +1,13 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "crypto_ed25519.h"
-#include "test.h"
-#include "torcert.h"
+#include "core/or/or.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "test/test.h"
+#include "feature/nodelist/torcert.h"
-#include "hs_common.h"
-#include "hs_test_helpers.h"
+#include "feature/hs/hs_common.h"
+#include "test/hs_test_helpers.h"
hs_desc_intro_point_t *
hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now,
diff --git a/src/test/hs_test_helpers.h b/src/test/hs_test_helpers.h
index b1b0490f05..b7c2714769 100644
--- a/src/test/hs_test_helpers.h
+++ b/src/test/hs_test_helpers.h
@@ -1,11 +1,11 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_HS_TEST_HELPERS_H
#define TOR_HS_TEST_HELPERS_H
-#include "ed25519_cert.h"
-#include "hs_descriptor.h"
+#include "trunnel/ed25519_cert.h"
+#include "feature/hs/hs_descriptor.h"
/* Set of functions to help build and test descriptors. */
hs_desc_intro_point_t *hs_helper_build_intro_point(
diff --git a/src/test/include.am b/src/test/include.am
index 6b35c248e6..a749ff1436 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -11,9 +11,9 @@ TESTS_ENVIRONMENT = \
export CARGO="$(CARGO)"; \
export EXTRA_CARGO_OPTIONS="$(EXTRA_CARGO_OPTIONS)"; \
export CARGO_ONLINE="$(CARGO_ONLINE)"; \
- export CCLD="$(CCLD)"; \
- chmod +x "$(abs_top_builddir)/link_rust.sh"; \
- export RUSTFLAGS="-C linker=$(abs_top_builddir)/link_rust.sh";
+ export CCLD="$(CCLD)"; \
+ chmod +x "$(abs_top_builddir)/link_rust.sh"; \
+ export RUSTFLAGS="-C linker=$(abs_top_builddir)/link_rust.sh";
TESTSCRIPTS = \
src/test/fuzz_static_testcases.sh \
@@ -72,12 +72,10 @@ noinst_PROGRAMS+= \
endif
src_test_AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
- -DLOCALSTATEDIR="\"$(localstatedir)\"" \
- -DBINDIR="\"$(bindir)\"" \
- -I"$(top_srcdir)/src/or" -I"$(top_srcdir)/src/ext" \
- -I"$(top_srcdir)/src/trunnel" \
- -I"$(top_srcdir)/src/ext/trunnel" \
- -DTOR_UNIT_TESTS
+ -DLOCALSTATEDIR="\"$(localstatedir)\"" \
+ -DBINDIR="\"$(bindir)\"" \
+ -DTOR_UNIT_TESTS \
+ $(AM_CPPFLAGS)
# -L flags need to go in LDFLAGS. -l flags need to go in LDADD.
# This seems to matter nowhere but on Windows, but I assure you that it
@@ -159,7 +157,6 @@ src_test_test_SOURCES += \
src/test/test_proto_misc.c \
src/test/test_protover.c \
src/test/test_pt.c \
- src/test/test_pubsub.c \
src/test/test_relay.c \
src/test/test_relaycell.c \
src/test/test_relaycrypt.c \
@@ -222,27 +219,19 @@ src_test_test_switch_id_CPPFLAGS= $(src_test_AM_CPPFLAGS)
src_test_test_switch_id_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
src_test_test_switch_id_LDFLAGS = @TOR_LDFLAGS_zlib@
src_test_test_switch_id_LDADD = \
- src/common/libor-testing.a \
- src/common/libor-ctime-testing.a \
+ $(TOR_UTIL_TESTING_LIBS) \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \
- @TOR_LIB_WS32@ @TOR_LIB_USERENV@ \
+ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_USERENV@ \
@TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
src_test_test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
- @TOR_LDFLAGS_libevent@
-src_test_test_LDADD = src/or/libtor-testing.a \
- src/common/libor-crypto-testing.a \
- $(LIBKECCAK_TINY) \
- $(LIBDONNA) \
- src/common/libor-testing.a \
- src/common/libor-ctime-testing.a \
- src/common/libor-event-testing.a \
- src/trunnel/libor-trunnel-testing.a \
- src/trace/libor-trace.a \
+ @TOR_LDFLAGS_libevent@
+src_test_test_LDADD = \
+ $(TOR_INTERNAL_TESTING_LIBS) \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
- @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
+ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
@CURVE25519_LIBS@ \
@TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
@@ -260,42 +249,34 @@ src_test_test_memwipe_LDADD = $(src_test_test_LDADD)
src_test_test_memwipe_LDFLAGS = $(src_test_test_LDFLAGS) @CFLAGS_BUGTRAP@
src_test_bench_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
- @TOR_LDFLAGS_libevent@
-src_test_bench_LDADD = src/or/libtor.a src/common/libor.a \
- src/common/libor-ctime.a \
- src/common/libor-crypto.a $(LIBKECCAK_TINY) $(LIBDONNA) \
- src/common/libor-event.a src/trunnel/libor-trunnel.a \
- src/trace/libor-trace.a \
+ @TOR_LDFLAGS_libevent@
+src_test_bench_LDADD = \
+ $(TOR_INTERNAL_LIBS) \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
- @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
+ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
@CURVE25519_LIBS@ \
@TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
src_test_test_workqueue_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
- @TOR_LDFLAGS_libevent@
-src_test_test_workqueue_LDADD = src/or/libtor-testing.a \
- src/common/libor-testing.a \
- src/common/libor-ctime-testing.a \
- src/common/libor-crypto-testing.a $(LIBKECCAK_TINY) $(LIBDONNA) \
- src/common/libor-event-testing.a \
- src/trace/libor-trace.a \
+ @TOR_LDFLAGS_libevent@
+src_test_test_workqueue_LDADD = \
+ $(TOR_INTERNAL_TESTING_LIBS) \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
- @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
+ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
@CURVE25519_LIBS@ \
@TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
src_test_test_timers_CPPFLAGS = $(src_test_test_CPPFLAGS)
src_test_test_timers_CFLAGS = $(src_test_test_CFLAGS)
src_test_test_timers_LDADD = \
- src/common/libor-testing.a \
- src/common/libor-ctime-testing.a \
- src/common/libor-event-testing.a \
- src/common/libor-crypto-testing.a $(LIBKECCAK_TINY) $(LIBDONNA) \
+ src/lib/libtor-evloop-testing.a \
+ $(TOR_CRYPTO_TESTING_LIBS) \
+ $(TOR_UTIL_TESTING_LIBS) \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
- @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
+ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
@CURVE25519_LIBS@ \
@TOR_LZMA_LIBS@
src_test_test_timers_LDFLAGS = $(src_test_test_LDFLAGS)
@@ -321,36 +302,32 @@ noinst_PROGRAMS+= src/test/test-ntor-cl
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_openssl@
-src_test_test_ntor_cl_LDADD = src/or/libtor.a src/common/libor.a \
- src/common/libor-ctime.a \
- src/common/libor-crypto.a $(LIBKECCAK_TINY) $(LIBDONNA) \
- src/trace/libor-trace.a \
+src_test_test_ntor_cl_LDADD = \
+ $(TOR_INTERNAL_LIBS) \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \
- @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
+ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
@CURVE25519_LIBS@ @TOR_LZMA_LIBS@
src_test_test_ntor_cl_AM_CPPFLAGS = \
- -I"$(top_srcdir)/src/or"
+ $(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_openssl@
-src_test_test_hs_ntor_cl_LDADD = src/or/libtor.a src/common/libor.a \
- src/common/libor-ctime.a \
- src/common/libor-crypto.a $(LIBKECCAK_TINY) $(LIBDONNA) \
+src_test_test_hs_ntor_cl_LDADD = \
+ $(TOR_INTERNAL_LIBS) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \
- @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@
+ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @CURVE25519_LIBS@
src_test_test_hs_ntor_cl_AM_CPPFLAGS = \
- -I"$(top_srcdir)/src/or"
+ $(AM_CPPFLAGS)
noinst_PROGRAMS += src/test/test-bt-cl
src_test_test_bt_cl_SOURCES = src/test/test_bt_cl.c
-src_test_test_bt_cl_LDADD = src/common/libor-testing.a \
- src/common/libor-ctime-testing.a \
- src/trace/libor-trace.a \
+src_test_test_bt_cl_LDADD = \
+ $(TOR_UTIL_TESTING_LIBS) \
$(rust_ldadd) \
@TOR_LIB_MATH@ \
- @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@
+ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@
src_test_test_bt_cl_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS)
@@ -363,7 +340,7 @@ EXTRA_DIST += \
src/test/fuzz_static_testcases.sh \
src/test/slownacl_curve25519.py \
src/test/zero_length_keys.sh \
- src/test/rust_supp.txt \
+ src/test/rust_supp.txt \
src/test/test_keygen.sh \
src/test/test_key_expiration.sh \
src/test/test_zero_length_keys.sh \
diff --git a/src/test/log_test_helpers.c b/src/test/log_test_helpers.c
index d5a39cfeee..e814555ba1 100644
--- a/src/test/log_test_helpers.c
+++ b/src/test/log_test_helpers.c
@@ -1,8 +1,8 @@
-/* Copyright (c) 2015-2017, The Tor Project, Inc. */
+/* Copyright (c) 2015-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define LOG_PRIVATE
-#include "torlog.h"
-#include "log_test_helpers.h"
+#include "lib/log/torlog.h"
+#include "test/log_test_helpers.h"
/**
* \file log_test_helpers.c
diff --git a/src/test/log_test_helpers.h b/src/test/log_test_helpers.h
index f5bbfcf3ff..fc9768c125 100644
--- a/src/test/log_test_helpers.h
+++ b/src/test/log_test_helpers.h
@@ -1,7 +1,7 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
+#include "core/or/or.h"
#ifndef TOR_LOG_TEST_HELPERS_H
#define TOR_LOG_TEST_HELPERS_H
diff --git a/src/test/ntor_ref.py b/src/test/ntor_ref.py
index 51f218f512..56e97ece36 100755
--- a/src/test/ntor_ref.py
+++ b/src/test/ntor_ref.py
@@ -1,5 +1,5 @@
#!/usr/bin/python
-# Copyright 2012-2017, The Tor Project, Inc
+# Copyright 2012-2018, The Tor Project, Inc
# See LICENSE for licensing information
"""
diff --git a/src/test/rend_test_helpers.c b/src/test/rend_test_helpers.c
index 9ac3894b0b..85a679a967 100644
--- a/src/test/rend_test_helpers.c
+++ b/src/test/rend_test_helpers.c
@@ -1,11 +1,15 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "crypto_rand.h"
-#include "test.h"
-#include "rendcommon.h"
-#include "rend_test_helpers.h"
+#include "core/or/or.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "test/test.h"
+#include "feature/rend/rendcommon.h"
+#include "test/rend_test_helpers.h"
+
+#include "core/or/extend_info_st.h"
+#include "feature/rend/rend_intro_point_st.h"
+#include "feature/rend/rend_service_descriptor_st.h"
void
generate_desc(int time_diff, rend_encoded_v2_service_descriptor_t **desc,
diff --git a/src/test/rend_test_helpers.h b/src/test/rend_test_helpers.h
index abf4324988..103e143ec6 100644
--- a/src/test/rend_test_helpers.h
+++ b/src/test/rend_test_helpers.h
@@ -1,7 +1,7 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
+#include "core/or/or.h"
#ifndef TOR_REND_TEST_HELPERS_H
#define TOR_REND_TEST_HELPERS_H
diff --git a/src/test/test-child.c b/src/test/test-child.c
index f78a829107..14df1a9b76 100644
--- a/src/test/test-child.c
+++ b/src/test/test-child.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Tor Project, Inc. */
+/* Copyright (c) 2011-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test-memwipe.c b/src/test/test-memwipe.c
index aaaf2e7f68..8a4610e904 100644
--- a/src/test/test-memwipe.c
+++ b/src/test/test-memwipe.c
@@ -1,16 +1,17 @@
-/* Copyright (c) 2015-2017, The Tor Project, Inc. */
+/* Copyright (c) 2015-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
+#include "lib/crypt_ops/crypto_util.h"
+
+#include "lib/intmath/cmp.h"
+#include "lib/malloc/util_malloc.h"
+
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
-#include "crypto_util.h"
-#include "compat.h"
-#include "util.h"
-
static unsigned fill_a_buffer_memset(void) __attribute__((noinline));
static unsigned fill_a_buffer_memwipe(void) __attribute__((noinline));
static unsigned fill_a_buffer_nothing(void) __attribute__((noinline));
@@ -215,4 +216,3 @@ main(int argc, char **argv)
return 0;
}
}
-
diff --git a/src/test/test-network.sh b/src/test/test-network.sh
index 6e0f286573..b7a9f1b3c0 100755
--- a/src/test/test-network.sh
+++ b/src/test/test-network.sh
@@ -52,12 +52,12 @@ done
# - if $PWD looks like a tor build directory, set it to $PWD, or
# - unset $TOR_DIR, and let chutney fall back to finding tor binaries in $PATH
if [ ! -d "$TOR_DIR" ]; then
- if [ -d "$BUILDDIR/src/or" -a -d "$BUILDDIR/src/tools" ]; then
+ if [ -d "$BUILDDIR/src/core/or" -a -d "$BUILDDIR/src/tools" ]; then
# Choose the build directory
# But only if it looks like one
$ECHO "$myname: \$TOR_DIR not set, trying \$BUILDDIR"
TOR_DIR="$BUILDDIR"
- elif [ -d "$PWD/src/or" -a -d "$PWD/src/tools" ]; then
+ elif [ -d "$PWD/src/core/or" -a -d "$PWD/src/tools" ]; then
# Guess the tor directory is the current directory
# But only if it looks like one
$ECHO "$myname: \$TOR_DIR not set, trying \$PWD"
diff --git a/src/test/test-timers.c b/src/test/test-timers.c
index f20f29578b..f9276c25d6 100644
--- a/src/test/test-timers.c
+++ b/src/test/test-timers.c
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017, The Tor Project, Inc. */
+/* Copyright 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -7,11 +7,12 @@
#include <stdio.h>
#include <string.h>
-#include "compat.h"
-#include "compat_libevent.h"
-#include "crypto_rand.h"
-#include "timers.h"
-#include "util.h"
+#include "lib/evloop/compat_libevent.h"
+#include "lib/evloop/timers.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/log/util_bug.h"
+#include "lib/time/compat_time.h"
+#include "lib/wallclock/timeval.h"
#define N_TIMERS 1000
#define MAX_DURATION 30
@@ -105,8 +106,8 @@ main(int argc, char **argv)
total_square_difference += diff*diff;
}
const int64_t mean_diff = total_difference / n_active_timers;
- printf("mean difference: "I64_FORMAT" usec\n",
- I64_PRINTF_ARG(mean_diff));
+ printf("mean difference: %"PRId64" usec\n",
+ (mean_diff));
const double mean_sq = ((double)total_square_difference)/ n_active_timers;
const double sq_mean = mean_diff * mean_diff;
@@ -139,4 +140,3 @@ main(int argc, char **argv)
timers_shutdown();
return ret;
}
-
diff --git a/src/test/test.c b/src/test/test.c
index f0e8b9b728..2addeec968 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,7 +9,10 @@
**/
#include "orconfig.h"
-#include "crypto_rand.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "lib/crypt_ops/crypto_rand.h"
+
+#include "app/config/or_state_st.h"
#include <stdio.h>
#ifdef HAVE_FCNTL_H
@@ -39,28 +42,34 @@
long int lround(double x);
double fabs(double x);
-#include "or.h"
-#include "backtrace.h"
-#include "buffers.h"
-#include "circuitlist.h"
-#include "circuitstats.h"
-#include "compress.h"
-#include "config.h"
-#include "connection_edge.h"
-#include "rendcommon.h"
-#include "rendcache.h"
-#include "test.h"
-#include "main.h"
-#include "memarea.h"
-#include "onion.h"
-#include "onion_ntor.h"
-#include "onion_fast.h"
-#include "onion_tap.h"
-#include "policies.h"
-#include "rephist.h"
-#include "routerparse.h"
-#include "statefile.h"
-#include "crypto_curve25519.h"
+#include "core/or/or.h"
+#include "lib/err/backtrace.h"
+#include "lib/container/buffers.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuitstats.h"
+#include "lib/compress/compress.h"
+#include "app/config/config.h"
+#include "core/or/connection_edge.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/rend/rendcache.h"
+#include "test/test.h"
+#include "core/mainloop/main.h"
+#include "lib/memarea/memarea.h"
+#include "core/crypto/onion.h"
+#include "core/crypto/onion_ntor.h"
+#include "core/crypto/onion_fast.h"
+#include "core/crypto/onion_tap.h"
+#include "core/or/policies.h"
+#include "feature/stats/rephist.h"
+#include "feature/nodelist/routerparse.h"
+#include "app/config/statefile.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+
+#include "core/or/extend_info_st.h"
+#include "core/or/or_circuit_st.h"
+#include "feature/rend/rend_encoded_v2_service_descriptor_st.h"
+#include "feature/rend/rend_intro_point_st.h"
+#include "feature/rend/rend_service_descriptor_st.h"
/** Run unit tests for the onion handshake code. */
static void
@@ -142,7 +151,8 @@ test_bad_onion_handshake(void *arg)
memset(junk_buf, 0, sizeof(junk_buf));
crypto_pk_obsolete_public_hybrid_encrypt(pk,
junk_buf2, TAP_ONIONSKIN_CHALLENGE_LEN,
- junk_buf, DH_KEY_LEN, PK_PKCS1_OAEP_PADDING, 1);
+ junk_buf, DH1024_KEY_LEN,
+ PK_PKCS1_OAEP_PADDING, 1);
tt_int_op(-1, OP_EQ,
onion_skin_TAP_server_handshake(junk_buf2, pk, NULL,
s_buf, s_keys, 40));
@@ -911,10 +921,8 @@ struct testgroup_t testgroups[] = {
{ "util/format/", util_format_tests },
{ "util/logging/", logging_tests },
{ "util/process/", util_process_tests },
- { "util/pubsub/", pubsub_tests },
{ "util/thread/", thread_tests },
{ "util/handle/", handle_tests },
{ "dns/", dns_tests },
END_OF_GROUPS
};
-
diff --git a/src/test/test.h b/src/test/test.h
index 63b2b30746..602acca1cd 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TEST_H
@@ -13,7 +13,6 @@
#define DEBUG_SMARTLIST 1
-#include "compat.h"
#include "tinytest.h"
#define TT_EXIT_TEST_FUNCTION STMT_BEGIN goto done; STMT_END
#include "tinytest_macros.h"
@@ -51,28 +50,20 @@
tt_double_op((a), OP_LE, (b)); \
STMT_END
-#ifdef _MSC_VER
-#define U64_PRINTF_TYPE uint64_t
-#define I64_PRINTF_TYPE int64_t
-#else
-#define U64_PRINTF_TYPE unsigned long long
-#define I64_PRINTF_TYPE long long
-#endif /* defined(_MSC_VER) */
-
#define tt_size_op(a,op,b) \
tt_assert_test_fmt_type(a,b,#a" "#op" "#b,size_t,(val1_ op val2_), \
- U64_PRINTF_TYPE, U64_FORMAT, \
- {print_ = (U64_PRINTF_TYPE) value_;}, {}, TT_EXIT_TEST_FUNCTION)
+ size_t, "%"TOR_PRIuSZ, \
+ {print_ = (size_t) value_;}, {}, TT_EXIT_TEST_FUNCTION)
#define tt_u64_op(a,op,b) \
tt_assert_test_fmt_type(a,b,#a" "#op" "#b,uint64_t,(val1_ op val2_), \
- U64_PRINTF_TYPE, U64_FORMAT, \
- {print_ = (U64_PRINTF_TYPE) value_;}, {}, TT_EXIT_TEST_FUNCTION)
+ uint64_t, "%"PRIu64, \
+ {print_ = (uint64_t) value_;}, {}, TT_EXIT_TEST_FUNCTION)
#define tt_i64_op(a,op,b) \
- tt_assert_test_fmt_type(a,b,#a" "#op" "#b,int64_t,(val1_ op val2_), \
- I64_PRINTF_TYPE, I64_FORMAT, \
- {print_ = (I64_PRINTF_TYPE) value_;}, {}, TT_EXIT_TEST_FUNCTION)
+ tt_assert_test_fmt_type(a,b,#a" "#op" "#b,int64_t,(val1_ op val2_), \
+ int64_t, "%"PRId64, \
+ {print_ = (int64_t) value_;}, {}, TT_EXIT_TEST_FUNCTION)
/**
* Declare that the test is done, even though no tt___op() calls were made.
@@ -248,7 +239,6 @@ extern struct testcase_t procmon_tests[];
extern struct testcase_t proto_http_tests[];
extern struct testcase_t proto_misc_tests[];
extern struct testcase_t protover_tests[];
-extern struct testcase_t pubsub_tests[];
extern struct testcase_t pt_tests[];
extern struct testcase_t relay_tests[];
extern struct testcase_t relaycell_tests[];
@@ -292,4 +282,3 @@ extern const char AUTHORITY_SIGNKEY_C_DIGEST[];
extern const char AUTHORITY_SIGNKEY_C_DIGEST256[];
#endif /* !defined(TOR_TEST_H) */
-
diff --git a/src/test/test_accounting.c b/src/test/test_accounting.c
index b0d37b2989..7721a9eb99 100644
--- a/src/test/test_accounting.c
+++ b/src/test/test_accounting.c
@@ -1,13 +1,15 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "test/test.h"
#define HIBERNATE_PRIVATE
-#include "hibernate.h"
-#include "config.h"
+#include "feature/hibernate/hibernate.h"
+#include "app/config/config.h"
#define STATEFILE_PRIVATE
-#include "statefile.h"
+#include "app/config/statefile.h"
+
+#include "app/config/or_state_st.h"
#define NS_MODULE accounting
@@ -102,4 +104,3 @@ struct testcase_t accounting_tests[] = {
{ "bwlimits", test_accounting_limits, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_addr.c b/src/test/test_addr.c
index 40db31320f..9ab921c5b6 100644
--- a/src/test/test_addr.c
+++ b/src/test/test_addr.c
@@ -1,15 +1,19 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ADDRESSMAP_PRIVATE
#include "orconfig.h"
-#include "or.h"
-#include "crypto_rand.h"
-#include "test.h"
-#include "addressmap.h"
-#include "log_test_helpers.h"
+#include "core/or/or.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "test/test.h"
+#include "feature/client/addressmap.h"
+#include "test/log_test_helpers.h"
+
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
/** Mocking replacement: only handles localhost. */
static int
@@ -1257,4 +1261,3 @@ struct testcase_t addr_tests[] = {
{ "make_null", test_addr_make_null, 0, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_address.c b/src/test/test_address.c
index 9c88d37a41..abe7c2c0ad 100644
--- a/src/test/test_address.c
+++ b/src/test/test_address.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ADDRESS_PRIVATE
@@ -23,10 +23,10 @@
#include <net/if.h>
#endif /* defined(HAVE_IFCONF_TO_SMARTLIST) */
-#include "or.h"
-#include "address.h"
-#include "test.h"
-#include "log_test_helpers.h"
+#include "core/or/or.h"
+#include "lib/net/address.h"
+#include "test/test.h"
+#include "test/log_test_helpers.h"
/** Return 1 iff <b>sockaddr1</b> and <b>sockaddr2</b> represent
* the same IP address and port combination. Otherwise, return 0.
diff --git a/src/test/test_address_set.c b/src/test/test_address_set.c
index f7441a6491..f231740011 100644
--- a/src/test/test_address_set.c
+++ b/src/test/test_address_set.c
@@ -1,16 +1,21 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "crypto_rand.h"
-#include "address_set.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "routerlist.h"
-#include "torcert.h"
-
-#include "test.h"
+#include "core/or/or.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "core/or/address_set.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/torcert.h"
+
+#include "feature/nodelist/microdesc_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerstatus_st.h"
+
+#include "test/test.h"
static networkstatus_t *dummy_ns = NULL;
static networkstatus_t *
diff --git a/src/test/test_bridges.c b/src/test/test_bridges.c
index c44f791e0d..07d6b88ed9 100644
--- a/src/test/test_bridges.c
+++ b/src/test/test_bridges.c
@@ -3,7 +3,7 @@
/**
* \file test_bridges.c
- * \brief Unittests for code in src/or/bridges.c
+ * \brief Unittests for code in bridges.c
**/
#define TOR_BRIDGES_PRIVATE
@@ -11,16 +11,14 @@
#include <stdbool.h>
-#include "or.h"
-#include "address.h"
-#include "bridges.h"
-#include "config.h"
-#include "container.h"
-#include "transports.h"
-#include "util.h"
+#include "core/or/or.h"
+#include "lib/net/address.h"
+#include "feature/client/bridges.h"
+#include "app/config/config.h"
+#include "feature/client/transports.h"
/* Test suite stuff */
-#include "test.h"
+#include "test/test.h"
/**
* A mocked transport_t, constructed via mock_transport_get_by_name().
@@ -611,4 +609,3 @@ struct testcase_t bridges_tests[] = {
B_TEST(transport_is_needed, 0),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_bt_cl.c b/src/test/test_bt_cl.c
index b5c8d7cf9e..716cff36e0 100644
--- a/src/test/test_bt_cl.c
+++ b/src/test/test_bt_cl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -7,10 +7,13 @@
/* To prevent 'assert' from going away. */
#undef TOR_COVERAGE
-#include "or.h"
-#include "util.h"
-#include "backtrace.h"
-#include "torlog.h"
+#include "core/or/or.h"
+#include "lib/err/backtrace.h"
+#include "lib/log/torlog.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
/* -1: no crash.
* 0: crash with a segmentation fault.
@@ -118,4 +121,3 @@ main(int argc, char **argv)
return 0;
}
-
diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c
index 868f6a8ba4..477066f699 100644
--- a/src/test/test_buffers.c
+++ b/src/test/test_buffers.c
@@ -1,17 +1,19 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define BUFFERS_PRIVATE
#define PROTO_HTTP_PRIVATE
-#include "or.h"
-#include "buffers.h"
-#include "buffers_tls.h"
-#include "crypto_rand.h"
-#include "proto_http.h"
-#include "proto_socks.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "lib/container/buffers.h"
+#include "lib/tls/buffers_tls.h"
+#include "lib/tls/tortls.h"
+#include "lib/compress/compress.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "core/proto/proto_http.h"
+#include "core/proto/proto_socks.h"
+#include "test/test.h"
/** Run unit tests for buffers.c */
static void
@@ -819,4 +821,3 @@ struct testcase_t buffer_tests[] = {
END_OF_TESTCASES
};
-
diff --git a/src/test/test_bwmgt.c b/src/test/test_bwmgt.c
index 268917005e..7aa053f6c3 100644
--- a/src/test/test_bwmgt.c
+++ b/src/test/test_bwmgt.c
@@ -8,15 +8,15 @@
#define TOKEN_BUCKET_PRIVATE
-#include "or.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "test/test.h"
-#include "token_bucket.h"
+#include "lib/evloop/token_bucket.h"
// an imaginary time, in timestamp units. Chosen so it will roll over.
static const uint32_t START_TS = UINT32_MAX-10;
static const int32_t KB = 1024;
-static const uint32_t GB = (U64_LITERAL(1) << 30);
+static const uint32_t GB = (UINT64_C(1) << 30);
static void
test_bwmgt_token_buf_init(void *arg)
diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c
index 54d9716780..2753c42191 100644
--- a/src/test/test_cell_formats.c
+++ b/src/test/test_cell_formats.c
@@ -1,24 +1,29 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#define CONNECTION_EDGE_PRIVATE
#define RELAY_PRIVATE
-#include "or.h"
-#include "channel.h"
-#include "connection_edge.h"
-#include "connection_or.h"
-#include "config.h"
-#include "crypto_rand.h"
-#include "onion.h"
-#include "onion_tap.h"
-#include "onion_fast.h"
-#include "onion_ntor.h"
-#include "relay.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "core/or/connection_edge.h"
+#include "core/or/connection_or.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "core/crypto/onion.h"
+#include "core/crypto/onion_tap.h"
+#include "core/crypto/onion_fast.h"
+#include "core/crypto/onion_ntor.h"
+#include "core/or/relay.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/cell_queue_st.h"
+#include "core/or/var_cell_st.h"
+
+#include "test/test.h"
#include <stdlib.h>
#include <string.h>
@@ -1297,4 +1302,3 @@ struct testcase_t cell_format_tests[] = {
TEST(is_destroy, 0),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_cell_queue.c b/src/test/test_cell_queue.c
index df987f82ce..d74bb9c622 100644
--- a/src/test/test_cell_queue.c
+++ b/src/test/test_cell_queue.c
@@ -1,12 +1,17 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
+/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CIRCUITLIST_PRIVATE
#define RELAY_PRIVATE
-#include "or.h"
-#include "circuitlist.h"
-#include "relay.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "core/or/circuitlist.h"
+#include "core/or/relay.h"
+#include "test/test.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/cell_queue_st.h"
+#include "core/or/or_circuit_st.h"
+#include "core/or/origin_circuit_st.h"
static void
test_cq_manip(void *arg)
diff --git a/src/test/test_channel.c b/src/test/test_channel.c
index 76124a6e75..26af8de917 100644
--- a/src/test/test_channel.c
+++ b/src/test/test_channel.c
@@ -1,29 +1,35 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
+/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define TOR_CHANNEL_INTERNAL_
#define CHANNEL_PRIVATE_
-#include "or.h"
-#include "channel.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
/* For channel_note_destroy_not_pending */
#define CIRCUITLIST_PRIVATE
-#include "circuitlist.h"
-#include "circuitmux.h"
-#include "circuitmux_ewma.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuitmux.h"
+#include "core/or/circuitmux_ewma.h"
/* For var_cell_free */
-#include "connection_or.h"
-#include "crypto_rand.h"
+#include "core/or/connection_or.h"
+#include "lib/crypt_ops/crypto_rand.h"
/* For packed_cell stuff */
#define RELAY_PRIVATE
-#include "relay.h"
+#include "core/or/relay.h"
/* For init/free stuff */
-#include "scheduler.h"
-#include "networkstatus.h"
+#include "core/or/scheduler.h"
+#include "feature/nodelist/networkstatus.h"
+
+#include "core/or/cell_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "feature/nodelist/routerstatus_st.h"
+#include "core/or/var_cell_st.h"
/* Test suite stuff */
-#include "log_test_helpers.h"
-#include "test.h"
-#include "fakechans.h"
+#include "test/log_test_helpers.h"
+#include "test/test.h"
+#include "test/fakechans.h"
static int test_chan_accept_cells = 0;
static int test_chan_fixed_cells_recved = 0;
@@ -548,7 +554,7 @@ test_channel_outbound_cell(void *arg)
/* Set the test time to be mocked, since this test assumes that no
* time will pass, ewma values will not need to be re-scaled, and so on */
monotime_enable_test_mocking();
- monotime_set_mock_time_nsec(U64_LITERAL(1000000000) * 12345);
+ monotime_set_mock_time_nsec(UINT64_C(1000000000) * 12345);
cmux_ewma_set_options(NULL,NULL);
diff --git a/src/test/test_channelpadding.c b/src/test/test_channelpadding.c
index 4261bc1b67..5d696b8b80 100644
--- a/src/test/test_channelpadding.c
+++ b/src/test/test_channelpadding.c
@@ -1,24 +1,32 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define TOR_CHANNEL_INTERNAL_
#define MAIN_PRIVATE
#define NETWORKSTATUS_PRIVATE
#define TOR_TIMERS_PRIVATE
-#include "or.h"
-#include "test.h"
-#include "testsupport.h"
-#include "connection.h"
-#include "connection_or.h"
-#include "channel.h"
-#include "channeltls.h"
-#include "channelpadding.h"
-#include "compat_libevent.h"
-#include "config.h"
-#include "compat_time.h"
-#include "main.h"
-#include "networkstatus.h"
-#include "log_test_helpers.h"
+#include "core/or/or.h"
+#include "test/test.h"
+#include "lib/testsupport/testsupport.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_or.h"
+#include "core/or/channel.h"
+#include "core/or/channeltls.h"
+#include "core/or/channelpadding.h"
+#include "lib/evloop/compat_libevent.h"
+#include "app/config/config.h"
+#include "lib/time/compat_time.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/networkstatus.h"
+#include "test/log_test_helpers.h"
+#include "lib/tls/tortls.h"
+#include "lib/evloop/timers.h"
+#include "lib/container/buffers.h"
+
+#include "core/or/cell_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "core/or/or_connection_st.h"
+#include "feature/nodelist/routerstatus_st.h"
int channelpadding_get_netflow_inactive_timeout_ms(channel_t *chan);
int64_t channelpadding_compute_time_until_pad_for_netflow(channel_t *chan);
@@ -1163,4 +1171,3 @@ struct testcase_t channelpadding_tests[] = {
TEST_CHANNELPADDING(channelpadding_timers, TT_FORK),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_channeltls.c b/src/test/test_channeltls.c
index 94f1893cae..787a30a85d 100644
--- a/src/test/test_channeltls.c
+++ b/src/test/test_channeltls.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -6,20 +6,23 @@
#include <math.h>
#define TOR_CHANNEL_INTERNAL_
-#include "or.h"
-#include "address.h"
-#include "buffers.h"
-#include "channel.h"
-#include "channeltls.h"
-#include "connection_or.h"
-#include "config.h"
+#include "core/or/or.h"
+#include "lib/net/address.h"
+#include "lib/container/buffers.h"
+#include "core/or/channel.h"
+#include "core/or/channeltls.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_or.h"
+#include "app/config/config.h"
/* For init/free stuff */
-#include "scheduler.h"
-#include "tortls.h"
+#include "core/or/scheduler.h"
+#include "lib/tls/tortls.h"
+
+#include "core/or/or_connection_st.h"
/* Test suite stuff */
-#include "test.h"
-#include "fakechans.h"
+#include "test/test.h"
+#include "test/fakechans.h"
/* The channeltls unit tests */
static void test_channeltls_create(void *arg);
@@ -334,4 +337,3 @@ struct testcase_t channeltls_tests[] = {
TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_checkdir.c b/src/test/test_checkdir.c
index bf6a8376b3..652e308ed8 100644
--- a/src/test/test_checkdir.c
+++ b/src/test/test_checkdir.c
@@ -1,8 +1,8 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
-#include "or.h"
+#include "core/or/or.h"
#ifdef _WIN32
#include <direct.h>
@@ -10,9 +10,12 @@
#include <dirent.h>
#endif
-#include "config.h"
-#include "test.h"
-#include "util.h"
+#include "app/config/config.h"
+#include "test/test.h"
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
#ifdef _WIN32
#define mkdir(a,b) mkdir(a)
@@ -146,4 +149,3 @@ struct testcase_t checkdir_tests[] = {
CHECKDIR(perms, TT_FORK),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_circuitbuild.c b/src/test/test_circuitbuild.c
index a5282df69d..02eadecd98 100644
--- a/src/test/test_circuitbuild.c
+++ b/src/test/test_circuitbuild.c
@@ -1,16 +1,19 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CIRCUITBUILD_PRIVATE
-#include "or.h"
-#include "test.h"
-#include "test_helpers.h"
-#include "log_test_helpers.h"
-#include "config.h"
-#include "circuitbuild.h"
+#include "core/or/or.h"
+#include "test/test.h"
+#include "test/test_helpers.h"
+#include "test/log_test_helpers.h"
+#include "app/config/config.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+
+#include "core/or/extend_info_st.h"
/* Dummy nodes smartlist for testing */
static smartlist_t dummy_nodes;
@@ -130,4 +133,3 @@ struct testcase_t circuitbuild_tests[] = {
{ "unhandled_exit", test_new_route_len_unhandled_exit, 0, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_circuitlist.c b/src/test/test_circuitlist.c
index 3794ffc2c6..8dd7f5f5a9 100644
--- a/src/test/test_circuitlist.c
+++ b/src/test/test_circuitlist.c
@@ -1,18 +1,23 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
+/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define TOR_CHANNEL_INTERNAL_
#define CIRCUITBUILD_PRIVATE
#define CIRCUITLIST_PRIVATE
#define HS_CIRCUITMAP_PRIVATE
-#include "or.h"
-#include "channel.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuitmux_ewma.h"
-#include "hs_circuitmap.h"
-#include "test.h"
-#include "log_test_helpers.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuitmux_ewma.h"
+#include "feature/hs/hs_circuitmap.h"
+#include "test/test.h"
+#include "test/log_test_helpers.h"
+
+#include "core/or/or_circuit_st.h"
+#include "core/or/origin_circuit_st.h"
+
+#include "lib/container/bitarray.h"
static channel_t *
new_fake_channel(void)
@@ -467,4 +472,3 @@ struct testcase_t circuitlist_tests[] = {
TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_circuitmux.c b/src/test/test_circuitmux.c
index 14c7598703..1d46f8de0d 100644
--- a/src/test/test_circuitmux.c
+++ b/src/test/test_circuitmux.c
@@ -1,17 +1,19 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
+/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define TOR_CHANNEL_INTERNAL_
#define CIRCUITMUX_PRIVATE
#define CIRCUITMUX_EWMA_PRIVATE
#define RELAY_PRIVATE
-#include "or.h"
-#include "channel.h"
-#include "circuitmux.h"
-#include "circuitmux_ewma.h"
-#include "relay.h"
-#include "scheduler.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "core/or/circuitmux.h"
+#include "core/or/circuitmux_ewma.h"
+#include "core/or/relay.h"
+#include "core/or/scheduler.h"
+#include "test/test.h"
+
+#include "core/or/destroy_cell_queue_st.h"
/* XXXX duplicated function from test_circuitlist.c */
static channel_t *
@@ -84,7 +86,7 @@ static void
test_cmux_compute_ticks(void *arg)
{
const int64_t NS_PER_S = 1000 * 1000 * 1000;
- const int64_t START_NS = U64_LITERAL(1217709000)*NS_PER_S;
+ const int64_t START_NS = UINT64_C(1217709000)*NS_PER_S;
int64_t now;
double rem;
unsigned tick;
diff --git a/src/test/test_circuitstats.c b/src/test/test_circuitstats.c
index 8ebef659ca..c3cfad88da 100644
--- a/src/test/test_circuitstats.c
+++ b/src/test/test_circuitstats.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CIRCUITBUILD_PRIVATE
@@ -6,16 +6,21 @@
#define CIRCUITLIST_PRIVATE
#define CHANNEL_PRIVATE_
-#include "or.h"
-#include "test.h"
-#include "test_helpers.h"
-#include "log_test_helpers.h"
-#include "config.h"
-#include "circuitlist.h"
-#include "circuitbuild.h"
-#include "circuitstats.h"
-#include "circuituse.h"
-#include "channel.h"
+#include "core/or/or.h"
+#include "test/test.h"
+#include "test/test_helpers.h"
+#include "test/log_test_helpers.h"
+#include "app/config/config.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitstats.h"
+#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);
diff --git a/src/test/test_circuituse.c b/src/test/test_circuituse.c
index df1b43807f..720adeac84 100644
--- a/src/test/test_circuituse.c
+++ b/src/test/test_circuituse.c
@@ -1,18 +1,21 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CIRCUITLIST_PRIVATE
-#include "or.h"
-#include "test.h"
-#include "test_helpers.h"
-#include "config.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "circuitbuild.h"
-#include "nodelist.h"
+#include "core/or/or.h"
+#include "test/test.h"
+#include "test/test_helpers.h"
+#include "app/config/config.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "core/or/circuitbuild.h"
+#include "feature/nodelist/nodelist.h"
+
+#include "core/or/cpath_build_state_st.h"
+#include "core/or/origin_circuit_st.h"
static void
test_circuit_is_available_for_use_ret_false_when_marked_for_close(void *arg)
diff --git a/src/test/test_compat_libevent.c b/src/test/test_compat_libevent.c
index 85f69bd626..3f505d013b 100644
--- a/src/test/test_compat_libevent.c
+++ b/src/test/test_compat_libevent.c
@@ -1,17 +1,17 @@
-/* Copyright (c) 2010-2017, The Tor Project, Inc. */
+/* Copyright (c) 2010-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define COMPAT_LIBEVENT_PRIVATE
#include "orconfig.h"
-#include "or.h"
+#include "core/or/or.h"
-#include "test.h"
+#include "test/test.h"
-#include "compat_libevent.h"
+#include "lib/evloop/compat_libevent.h"
#include <event2/event.h>
-#include "log_test_helpers.h"
+#include "test/log_test_helpers.h"
#define NS_MODULE compat_libevent
diff --git a/src/test/test_config.c b/src/test/test_config.c
index 461aa646d6..af3a8a7cfe 100644
--- a/src/test/test_config.c
+++ b/src/test/test_config.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -8,41 +8,56 @@
#define CONFIG_PRIVATE
#define PT_PRIVATE
#define ROUTERSET_PRIVATE
-#include "or.h"
-#include "address.h"
-#include "addressmap.h"
-#include "bridges.h"
-#include "circuitmux_ewma.h"
-#include "circuitbuild.h"
-#include "config.h"
-#include "confparse.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "test.h"
-#include "util.h"
-#include "connection_or.h"
-#include "control.h"
-#include "cpuworker.h"
-#include "dirserv.h"
-#include "dirauth/dirvote.h"
-#include "dns.h"
-#include "entrynodes.h"
-#include "transports.h"
-#include "ext_orport.h"
-#include "geoip.h"
-#include "hibernate.h"
-#include "main.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "policies.h"
-#include "rendclient.h"
-#include "rendservice.h"
-#include "router.h"
-#include "routerlist.h"
-#include "routerset.h"
-#include "statefile.h"
-
-#include "test_helpers.h"
+#include "core/or/or.h"
+#include "lib/net/address.h"
+#include "feature/client/addressmap.h"
+#include "feature/client/bridges.h"
+#include "core/or/circuitmux_ewma.h"
+#include "core/or/circuitbuild.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "test/test.h"
+#include "core/or/connection_or.h"
+#include "feature/control/control.h"
+#include "core/mainloop/cpuworker.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/relay/dns.h"
+#include "feature/client/entrynodes.h"
+#include "feature/client/transports.h"
+#include "feature/relay/ext_orport.h"
+#include "feature/stats/geoip.h"
+#include "feature/hibernate/hibernate.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "feature/rend/rendclient.h"
+#include "feature/rend/rendservice.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerset.h"
+#include "app/config/statefile.h"
+
+#include "test/test_helpers.h"
+
+#include "feature/dirclient/dir_server_st.h"
+#include "core/or/port_cfg_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+
+#include "lib/fs/conffile.h"
+#include "lib/meminfo/meminfo.h"
+#include "lib/net/gethostname.h"
+#include "lib/encoding/confline.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
static void
test_config_addressmap(void *arg)
@@ -1619,6 +1634,40 @@ test_config_parsing_trusted_dir_server(void *arg)
#undef TEST_DIR_AUTH_LINE_END
#undef TEST_DIR_AUTH_IPV6_FLAG
+#define TEST_DIR_AUTH_LINE_START \
+ "foobar orport=12345 " \
+ "v3ident=14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4 "
+#define TEST_DIR_AUTH_LINE_END_BAD_IP \
+ "0.256.3.4:54321 " \
+ "FDB2 FBD2 AAA5 25FA 2999 E617 5091 5A32 C777 3B17"
+#define TEST_DIR_AUTH_LINE_END_WITH_DNS_ADDR \
+ "torproject.org:54321 " \
+ "FDB2 FBD2 AAA5 25FA 2999 E617 5091 5A32 C777 3B17"
+
+static void
+test_config_parsing_invalid_dir_address(void *arg)
+{
+ (void)arg;
+ int rv;
+
+ rv = parse_dir_authority_line(TEST_DIR_AUTH_LINE_START
+ TEST_DIR_AUTH_LINE_END_BAD_IP,
+ V3_DIRINFO, 1);
+ tt_int_op(rv, OP_EQ, -1);
+
+ rv = parse_dir_authority_line(TEST_DIR_AUTH_LINE_START
+ TEST_DIR_AUTH_LINE_END_WITH_DNS_ADDR,
+ V3_DIRINFO, 1);
+ tt_int_op(rv, OP_EQ, -1);
+
+ done:
+ return;
+}
+
+#undef TEST_DIR_AUTH_LINE_START
+#undef TEST_DIR_AUTH_LINE_END_BAD_IP
+#undef TEST_DIR_AUTH_LINE_END_WITH_DNS_ADDR
+
/* No secrets here:
* id is `echo "syn-propanethial-S-oxide" | shasum | cut -d" " -f1`
*/
@@ -3724,7 +3773,7 @@ static void
test_config_default_fallback_dirs(void *arg)
{
const char *fallback[] = {
-#include "../or/fallback_dirs.inc"
+#include "app/config/fallback_dirs.inc"
NULL
};
@@ -5611,8 +5660,8 @@ test_config_include_opened_file_list(void *data)
static void
test_config_compute_max_mem_in_queues(void *data)
{
-#define GIGABYTE(x) (U64_LITERAL(x) << 30)
-#define MEGABYTE(x) (U64_LITERAL(x) << 20)
+#define GIGABYTE(x) (UINT64_C(x) << 30)
+#define MEGABYTE(x) (UINT64_C(x) << 20)
(void)data;
MOCK(get_total_system_memory, get_total_system_memory_mock);
@@ -5683,6 +5732,7 @@ struct testcase_t config_tests[] = {
CONFIG_TEST(adding_trusted_dir_server, TT_FORK),
CONFIG_TEST(adding_fallback_dir_server, TT_FORK),
CONFIG_TEST(parsing_trusted_dir_server, 0),
+ CONFIG_TEST(parsing_invalid_dir_address, 0),
CONFIG_TEST(parsing_fallback_dir_server, 0),
CONFIG_TEST(adding_default_trusted_dir_servers, TT_FORK),
CONFIG_TEST(adding_dir_servers, TT_FORK),
@@ -5727,4 +5777,3 @@ struct testcase_t config_tests[] = {
CONFIG_TEST(compute_max_mem_in_queues, 0),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_connection.c b/src/test/test_connection.c
index dc0f6860d9..c423c6573f 100644
--- a/src/test/test_connection.c
+++ b/src/test/test_connection.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Tor Project, Inc. */
+/* Copyright (c) 2015-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -7,21 +7,29 @@
#define MAIN_PRIVATE
#define CONNECTION_OR_PRIVATE
-#include "or.h"
-#include "test.h"
-
-#include "connection.h"
-#include "hs_common.h"
-#include "main.h"
-#include "microdesc.h"
-#include "nodelist.h"
-#include "networkstatus.h"
-#include "rendcache.h"
-#include "directory.h"
-#include "connection_or.h"
-
-#include "test_connection.h"
-#include "test_helpers.h"
+#include "core/or/or.h"
+#include "test/test.h"
+
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "feature/hs/hs_common.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/rend/rendcache.h"
+#include "feature/dircache/directory.h"
+#include "core/or/connection_or.h"
+
+#include "test/test_connection.h"
+#include "test/test_helpers.h"
+
+#include "feature/dircommon/dir_connection_st.h"
+#include "core/or/entry_connection_st.h"
+#include "feature/nodelist/node_st.h"
+#include "core/or/or_connection_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "core/or/socks_request_st.h"
static void * test_conn_get_basic_setup(const struct testcase_t *tc);
static int test_conn_get_basic_teardown(const struct testcase_t *tc,
diff --git a/src/test/test_connection.h b/src/test/test_connection.h
index 392783b53b..27c296504a 100644
--- a/src/test/test_connection.h
+++ b/src/test/test_connection.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/** Some constants used by test_connection and helpers */
diff --git a/src/test/test_conscache.c b/src/test/test_conscache.c
index ffec3149b0..b5cbd72515 100644
--- a/src/test/test_conscache.c
+++ b/src/test/test_conscache.c
@@ -1,10 +1,11 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "config.h"
-#include "conscache.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "feature/dircache/conscache.h"
+#include "lib/encoding/confline.h"
+#include "test/test.h"
#ifdef HAVE_UTIME_H
#include <utime.h>
@@ -337,4 +338,3 @@ struct testcase_t conscache_tests[] = {
ENT(filter),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_consdiff.c b/src/test/test_consdiff.c
index fda3a7f186..b836befd22 100644
--- a/src/test/test_consdiff.c
+++ b/src/test/test_consdiff.c
@@ -1,15 +1,15 @@
/* Copyright (c) 2014, Daniel Martí
- * Copyright (c) 2014, The Tor Project, Inc. */
+ * Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONSDIFF_PRIVATE
-#include "or.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "test/test.h"
-#include "consdiff.h"
-#include "memarea.h"
-#include "log_test_helpers.h"
+#include "feature/dircommon/consdiff.h"
+#include "lib/memarea/memarea.h"
+#include "test/log_test_helpers.h"
#define tt_str_eq_line(a,b) \
tt_assert(line_str_eq((b),(a)))
diff --git a/src/test/test_consdiffmgr.c b/src/test/test_consdiffmgr.c
index 3b91baca39..6c0601b504 100644
--- a/src/test/test_consdiffmgr.c
+++ b/src/test/test_consdiffmgr.c
@@ -1,21 +1,25 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONSDIFFMGR_PRIVATE
-#include "or.h"
-#include "config.h"
-#include "conscache.h"
-#include "consdiff.h"
-#include "consdiffmgr.h"
-#include "cpuworker.h"
-#include "crypto_rand.h"
-#include "networkstatus.h"
-#include "routerparse.h"
-#include "workqueue.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "feature/dircache/conscache.h"
+#include "feature/dircommon/consdiff.h"
+#include "feature/dircache/consdiffmgr.h"
+#include "core/mainloop/cpuworker.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/routerparse.h"
+#include "lib/evloop/workqueue.h"
+#include "lib/compress/compress.h"
+#include "lib/encoding/confline.h"
-#include "test.h"
-#include "log_test_helpers.h"
+#include "feature/nodelist/networkstatus_st.h"
+
+#include "test/test.h"
+#include "test/log_test_helpers.h"
// ============================== Setup/teardown the consdiffmgr
// These functions get run before/after each test in this module
@@ -894,4 +898,3 @@ struct testcase_t consdiffmgr_tests[] = {
END_OF_TESTCASES
};
-
diff --git a/src/test/test_containers.c b/src/test/test_containers.c
index 3fc3523af4..717eb0892a 100644
--- a/src/test/test_containers.c
+++ b/src/test/test_containers.c
@@ -1,13 +1,17 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
-#include "or.h"
-#include "crypto_rand.h"
-#include "fp_pair.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/dircommon/fp_pair.h"
+#include "test/test.h"
+
+#include "lib/container/bitarray.h"
+#include "lib/container/order.h"
+#include "lib/crypt_ops/digestset.h"
/** Helper: return a tristate based on comparing the strings in *<b>a</b> and
* *<b>b</b>. */
@@ -640,18 +644,18 @@ test_container_digestset(void *arg)
}
set = digestset_new(1000);
SMARTLIST_FOREACH(included, const char *, cp,
- if (digestset_contains(set, cp))
+ if (digestset_probably_contains(set, cp))
ok = 0);
tt_assert(ok);
SMARTLIST_FOREACH(included, const char *, cp,
digestset_add(set, cp));
SMARTLIST_FOREACH(included, const char *, cp,
- if (!digestset_contains(set, cp))
+ if (!digestset_probably_contains(set, cp))
ok = 0);
tt_assert(ok);
for (i = 0; i < 1000; ++i) {
crypto_rand(d, DIGEST_LEN);
- if (digestset_contains(set, d))
+ if (digestset_probably_contains(set, d))
++false_positives;
}
tt_int_op(50, OP_GT, false_positives); /* Should be far lower. */
@@ -1295,4 +1299,3 @@ struct testcase_t container_tests[] = {
CONTAINER(smartlist_strings_eq, 0),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_controller.c b/src/test/test_controller.c
index 1a350f66c0..2ded04619c 100644
--- a/src/test/test_controller.c
+++ b/src/test/test_controller.c
@@ -1,17 +1,24 @@
-/* Copyright (c) 2015-2017, The Tor Project, Inc. */
+/* Copyright (c) 2015-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONTROL_PRIVATE
-#include "or.h"
-#include "bridges.h"
-#include "control.h"
-#include "entrynodes.h"
-#include "hs_common.h"
-#include "networkstatus.h"
-#include "rendservice.h"
-#include "routerlist.h"
-#include "test.h"
-#include "test_helpers.h"
+#include "core/or/or.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "feature/client/bridges.h"
+#include "feature/control/control.h"
+#include "feature/client/entrynodes.h"
+#include "feature/hs/hs_common.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/rend/rendservice.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/nodelist.h"
+#include "test/test.h"
+#include "test/test_helpers.h"
+
+#include "feature/control/control_connection_st.h"
+#include "feature/dirclient/download_status_st.h"
+#include "feature/nodelist/microdesc_st.h"
+#include "feature/nodelist/node_st.h"
static void
test_add_onion_helper_keyarg_v3(void *arg)
@@ -1525,6 +1532,80 @@ test_current_time(void *arg)
return;
}
+static size_t n_nodelist_get_list = 0;
+static smartlist_t *nodes = NULL;
+
+static smartlist_t *
+mock_nodelist_get_list(void)
+{
+ n_nodelist_get_list++;
+ tor_assert(nodes);
+
+ return nodes;
+}
+
+static void
+test_getinfo_md_all(void *arg)
+{
+ char *answer = NULL;
+ const char *errmsg = NULL;
+ int retval = 0;
+
+ (void)arg;
+
+ node_t *node1 = tor_malloc(sizeof(node_t));
+ memset(node1, 0, sizeof(node_t));
+ node1->md = tor_malloc(sizeof(microdesc_t));
+ memset(node1->md, 0, sizeof(microdesc_t));
+ node1->md->body = tor_strdup("md1\n");
+ node1->md->bodylen = 4;
+
+ node_t *node2 = tor_malloc(sizeof(node_t));
+ memset(node2, 0, sizeof(node_t));
+ node2->md = tor_malloc(sizeof(microdesc_t));
+ memset(node2->md, 0, sizeof(microdesc_t));
+ node2->md->body = tor_strdup("md2\n");
+ node2->md->bodylen = 4;
+
+ MOCK(nodelist_get_list, mock_nodelist_get_list);
+
+ nodes = smartlist_new();
+
+ retval = getinfo_helper_dir(NULL, "md/all", &answer, &errmsg);
+
+ tt_int_op(n_nodelist_get_list, OP_EQ, 1);
+ tt_int_op(retval, OP_EQ, 0);
+ tt_assert(answer != NULL);
+ tt_assert(errmsg == NULL);
+ tt_str_op(answer, OP_EQ, "");
+
+ tor_free(answer);
+
+ smartlist_add(nodes, node1);
+ smartlist_add(nodes, node2);
+
+ retval = getinfo_helper_dir(NULL, "md/all", &answer, &errmsg);
+
+ tt_int_op(n_nodelist_get_list, OP_EQ, 2);
+ tt_int_op(retval, OP_EQ, 0);
+ tt_assert(answer != NULL);
+ tt_assert(errmsg == NULL);
+
+ tt_str_op(answer, OP_EQ, "md1\nmd2\n");
+
+ done:
+ UNMOCK(nodelist_get_list);
+ tor_free(node1->md->body);
+ tor_free(node1->md);
+ tor_free(node1);
+ tor_free(node2->md->body);
+ tor_free(node2->md);
+ tor_free(node2);
+ tor_free(answer);
+ smartlist_free(nodes);
+ return;
+}
+
struct testcase_t controller_tests[] = {
{ "add_onion_helper_keyarg_v2", test_add_onion_helper_keyarg_v2, 0,
NULL, NULL },
@@ -1542,6 +1623,6 @@ struct testcase_t controller_tests[] = {
{ "download_status_desc", test_download_status_desc, 0, NULL, NULL },
{ "download_status_bridge", test_download_status_bridge, 0, NULL, NULL },
{ "current_time", test_current_time, 0, NULL, NULL },
+ { "getinfo_md_all", test_getinfo_md_all, 0, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_controller_events.c b/src/test/test_controller_events.c
index e81aea8d66..e935b70428 100644
--- a/src/test/test_controller_events.c
+++ b/src/test/test_controller_events.c
@@ -1,15 +1,19 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
+/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONNECTION_PRIVATE
#define TOR_CHANNEL_INTERNAL_
#define CONTROL_PRIVATE
-#include "or.h"
-#include "channel.h"
-#include "channeltls.h"
-#include "connection.h"
-#include "control.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "core/or/channeltls.h"
+#include "core/or/circuitlist.h"
+#include "core/mainloop/connection.h"
+#include "feature/control/control.h"
+#include "test/test.h"
+
+#include "core/or/or_circuit_st.h"
+#include "core/or/origin_circuit_st.h"
static void
add_testing_cell_stats_entry(circuit_t *circ, uint8_t command,
@@ -328,4 +332,3 @@ struct testcase_t controller_event_tests[] = {
TEST(event_mask, TT_FORK),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index bb2e340dd2..2124e22196 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -1,21 +1,30 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#define CRYPTO_CURVE25519_PRIVATE
#define CRYPTO_RAND_PRIVATE
-#include "or.h"
-#include "test.h"
-#include "aes.h"
-#include "util.h"
+#include "core/or/or.h"
+#include "test/test.h"
+#include "lib/crypt_ops/aes.h"
#include "siphash.h"
-#include "crypto_curve25519.h"
-#include "crypto_ed25519.h"
-#include "crypto_rand.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_hkdf.h"
+#include "lib/crypt_ops/crypto_rand.h"
#include "ed25519_vectors.inc"
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
/** Run unit tests for Diffie-Hellman functionality. */
static void
test_crypto_dh(void *arg)
@@ -23,38 +32,39 @@ test_crypto_dh(void *arg)
crypto_dh_t *dh1 = crypto_dh_new(DH_TYPE_CIRCUIT);
crypto_dh_t *dh1_dup = NULL;
crypto_dh_t *dh2 = crypto_dh_new(DH_TYPE_CIRCUIT);
- char p1[DH_BYTES];
- char p2[DH_BYTES];
- char s1[DH_BYTES];
- char s2[DH_BYTES];
+ char p1[DH1024_KEY_LEN];
+ char p2[DH1024_KEY_LEN];
+ char s1[DH1024_KEY_LEN];
+ char s2[DH1024_KEY_LEN];
ssize_t s1len, s2len;
(void)arg;
- tt_int_op(crypto_dh_get_bytes(dh1),OP_EQ, DH_BYTES);
- tt_int_op(crypto_dh_get_bytes(dh2),OP_EQ, DH_BYTES);
+ tt_int_op(crypto_dh_get_bytes(dh1),OP_EQ, DH1024_KEY_LEN);
+ tt_int_op(crypto_dh_get_bytes(dh2),OP_EQ, DH1024_KEY_LEN);
- memset(p1, 0, DH_BYTES);
- memset(p2, 0, DH_BYTES);
- tt_mem_op(p1,OP_EQ, p2, DH_BYTES);
+ memset(p1, 0, DH1024_KEY_LEN);
+ memset(p2, 0, DH1024_KEY_LEN);
+ tt_mem_op(p1,OP_EQ, p2, DH1024_KEY_LEN);
tt_int_op(-1, OP_EQ, crypto_dh_get_public(dh1, p1, 6)); /* too short */
- tt_assert(! crypto_dh_get_public(dh1, p1, DH_BYTES));
- tt_mem_op(p1,OP_NE, p2, DH_BYTES);
- tt_assert(! crypto_dh_get_public(dh2, p2, DH_BYTES));
- tt_mem_op(p1,OP_NE, p2, DH_BYTES);
+ tt_assert(! crypto_dh_get_public(dh1, p1, DH1024_KEY_LEN));
+ tt_mem_op(p1,OP_NE, p2, DH1024_KEY_LEN);
+ tt_assert(! crypto_dh_get_public(dh2, p2, DH1024_KEY_LEN));
+ tt_mem_op(p1,OP_NE, p2, DH1024_KEY_LEN);
- memset(s1, 0, DH_BYTES);
- memset(s2, 0xFF, DH_BYTES);
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p2, DH_BYTES, s1, 50);
- s2len = crypto_dh_compute_secret(LOG_WARN, dh2, p1, DH_BYTES, s2, 50);
+ memset(s1, 0, DH1024_KEY_LEN);
+ memset(s2, 0xFF, DH1024_KEY_LEN);
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p2, DH1024_KEY_LEN, s1, 50);
+ s2len = crypto_dh_compute_secret(LOG_WARN, dh2, p1, DH1024_KEY_LEN, s2, 50);
tt_assert(s1len > 0);
tt_int_op(s1len,OP_EQ, s2len);
tt_mem_op(s1,OP_EQ, s2, s1len);
/* test dh_dup; make sure it works the same. */
dh1_dup = crypto_dh_dup(dh1);
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1_dup, p2, DH_BYTES, s1, 50);
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1_dup, p2, DH1024_KEY_LEN,
+ s1, 50);
tt_mem_op(s1,OP_EQ, s2, s1len);
{
@@ -67,12 +77,14 @@ test_crypto_dh(void *arg)
s1len = crypto_dh_compute_secret(LOG_WARN, dh1, "\x00", 1, s1, 50);
tt_int_op(-1, OP_EQ, s1len);
- memset(p1, 0, DH_BYTES); /* 0 with padding. */
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ memset(p1, 0, DH1024_KEY_LEN); /* 0 with padding. */
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(-1, OP_EQ, s1len);
- p1[DH_BYTES-1] = 1; /* 1 with padding*/
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ p1[DH1024_KEY_LEN-1] = 1; /* 1 with padding*/
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(-1, OP_EQ, s1len);
/* 2 is okay, though weird. */
@@ -89,15 +101,18 @@ test_crypto_dh(void *arg)
/* p-1, p, and so on are not okay. */
base16_decode(p1, sizeof(p1), P, strlen(P));
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(-1, OP_EQ, s1len);
- p1[DH_BYTES-1] = 0xFE; /* p-1 */
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ p1[DH1024_KEY_LEN-1] = 0xFE; /* p-1 */
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(-1, OP_EQ, s1len);
- p1[DH_BYTES-1] = 0xFD; /* p-2 works fine */
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ p1[DH1024_KEY_LEN-1] = 0xFD; /* p-2 works fine */
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(50, OP_EQ, s1len);
const char P_plus_one[] =
@@ -109,31 +124,35 @@ test_crypto_dh(void *arg)
base16_decode(p1, sizeof(p1), P_plus_one, strlen(P_plus_one));
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(-1, OP_EQ, s1len);
- p1[DH_BYTES-1] = 0x01; /* p+2 */
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ p1[DH1024_KEY_LEN-1] = 0x01; /* p+2 */
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(-1, OP_EQ, s1len);
- p1[DH_BYTES-1] = 0xff; /* p+256 */
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ p1[DH1024_KEY_LEN-1] = 0xff; /* p+256 */
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(-1, OP_EQ, s1len);
- memset(p1, 0xff, DH_BYTES), /* 2^1024-1 */
- s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50);
+ memset(p1, 0xff, DH1024_KEY_LEN), /* 2^1024-1 */
+ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN,
+ s1, 50);
tt_int_op(-1, OP_EQ, s1len);
}
{
/* provoke an error in the openssl DH_compute_key function; make sure we
* survive. */
- tt_assert(! crypto_dh_get_public(dh1, p1, DH_BYTES));
+ tt_assert(! crypto_dh_get_public(dh1, p1, DH1024_KEY_LEN));
crypto_dh_free(dh2);
dh2= crypto_dh_new(DH_TYPE_CIRCUIT); /* no private key set */
s1len = crypto_dh_compute_secret(LOG_WARN, dh2,
- p1, DH_BYTES,
+ p1, DH1024_KEY_LEN,
s1, 50);
tt_int_op(s1len, OP_EQ, -1);
}
@@ -152,8 +171,13 @@ test_crypto_openssl_version(void *arg)
const char *h_version = crypto_openssl_get_header_version_str();
tt_assert(version);
tt_assert(h_version);
- tt_assert(!strcmpstart(version, h_version)); /* "-fips" suffix, etc */
- tt_assert(!strstr(version, "OpenSSL"));
+ if (strcmpstart(version, h_version)) { /* "-fips" suffix, etc */
+ TT_DIE(("OpenSSL library version %s did not begin with header version %s.",
+ version, h_version));
+ }
+ if (strstr(version, "OpenSSL")) {
+ TT_DIE(("assertion failed: !strstr(\"%s\", \"OpenSSL\")", version));
+ }
int a=-1,b=-1,c=-1;
if (!strcmpstart(version, "LibreSSL") || !strcmpstart(version, "BoringSSL"))
return;
@@ -190,10 +214,10 @@ test_crypto_rng(void *arg)
j = crypto_rand_int(100);
if (j < 0 || j >= 100)
allok = 0;
- big = crypto_rand_uint64(U64_LITERAL(1)<<40);
- if (big >= (U64_LITERAL(1)<<40))
+ big = crypto_rand_uint64(UINT64_C(1)<<40);
+ if (big >= (UINT64_C(1)<<40))
allok = 0;
- big = crypto_rand_uint64(U64_LITERAL(5));
+ big = crypto_rand_uint64(UINT64_C(5));
if (big >= 5)
allok = 0;
d = crypto_rand_double();
@@ -1817,15 +1841,6 @@ test_crypto_hkdf_sha256(void *arg)
key_material, 100)
/* Test vectors generated with ntor_ref.py */
- memset(key_material, 0, sizeof(key_material));
- EXPAND("");
- tt_int_op(r, OP_EQ, 0);
- test_memeq_hex(key_material,
- "d3490ed48b12a48f9547861583573fe3f19aafe3f81dc7fc75"
- "eeed96d741b3290f941576c1f9f0b2d463d1ec7ab2c6bf71cd"
- "d7f826c6298c00dbfe6711635d7005f0269493edf6046cc7e7"
- "dcf6abe0d20c77cf363e8ffe358927817a3d3e73712cee28d8");
-
EXPAND("Tor");
tt_int_op(r, OP_EQ, 0);
test_memeq_hex(key_material,
@@ -2810,8 +2825,8 @@ test_crypto_siphash(void *arg)
{ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, }
};
- const struct sipkey K = { U64_LITERAL(0x0706050403020100),
- U64_LITERAL(0x0f0e0d0c0b0a0908) };
+ const struct sipkey K = { UINT64_C(0x0706050403020100),
+ UINT64_C(0x0f0e0d0c0b0a0908) };
uint8_t input[64];
int i, j;
@@ -2866,12 +2881,12 @@ crypto_rand_check_failure_mode_identical(void)
{
/* just in case the buffer size isn't a multiple of sizeof(int64_t) */
#define FAILURE_MODE_BUFFER_SIZE_I64 \
- (FAILURE_MODE_BUFFER_SIZE/SIZEOF_INT64_T)
+ (FAILURE_MODE_BUFFER_SIZE/8)
#define FAILURE_MODE_BUFFER_SIZE_I64_BYTES \
- (FAILURE_MODE_BUFFER_SIZE_I64*SIZEOF_INT64_T)
+ (FAILURE_MODE_BUFFER_SIZE_I64*8)
#if FAILURE_MODE_BUFFER_SIZE_I64 < 2
-#error FAILURE_MODE_BUFFER_SIZE needs to be at least 2*SIZEOF_INT64_T
+#error FAILURE_MODE_BUFFER_SIZE needs to be at least 2*8
#endif
int64_t buf[FAILURE_MODE_BUFFER_SIZE_I64];
@@ -3067,4 +3082,3 @@ struct testcase_t crypto_tests[] = {
{ "failure_modes", test_crypto_failure_modes, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_crypto_openssl.c b/src/test/test_crypto_openssl.c
index a016277508..b1a5613eaf 100644
--- a/src/test/test_crypto_openssl.c
+++ b/src/test/test_crypto_openssl.c
@@ -1,21 +1,21 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#define CRYPTO_RAND_PRIVATE
-#include "crypto_rand.h"
-#include "util.h"
-#include "util_format.h"
-#include "compat.h"
-#include "test.h"
+#include "lib/crypt_ops/compat_openssl.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/encoding/binascii.h"
+#include "lib/malloc/util_malloc.h"
+#include "test/test.h"
#include <openssl/evp.h>
#include <openssl/rand.h>
-#include "compat_openssl.h"
+#include <string.h>
/* Test for rectifying openssl RAND engine. */
static void
@@ -104,4 +104,3 @@ struct testcase_t crypto_openssl_tests[] = {
TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_crypto_slow.c b/src/test/test_crypto_slow.c
index 0e1f5bd227..88b31ad9af 100644
--- a/src/test/test_crypto_slow.c
+++ b/src/test/test_crypto_slow.c
@@ -1,15 +1,17 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#define CRYPTO_S2K_PRIVATE
-#include "or.h"
-#include "test.h"
-#include "crypto_s2k.h"
-#include "crypto_pwbox.h"
-#include "crypto_rand.h"
+#include "core/or/or.h"
+#include "test/test.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_s2k.h"
+#include "lib/crypt_ops/crypto_pwbox.h"
+#include "lib/crypt_ops/crypto_rand.h"
#if defined(HAVE_LIBSCRYPT_H) && defined(HAVE_LIBSCRYPT_SCRYPT)
#define HAVE_LIBSCRYPT
@@ -615,4 +617,3 @@ struct testcase_t slow_crypto_tests[] = {
ED25519_TEST(fuzz_donna, TT_FORK),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_data.c b/src/test/test_data.c
index ce6c3394f6..be8153258b 100644
--- a/src/test/test_data.c
+++ b/src/test/test_data.c
@@ -1,9 +1,9 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "test.h"
+#include "test/test.h"
/* Our unit test expect that the AUTHORITY_CERT_* public keys will sort
* in this order. */
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index b42755e351..bda56b3a8e 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -17,32 +17,55 @@
#define NETWORKSTATUS_PRIVATE
#define RELAY_PRIVATE
-#include "or.h"
-#include "bridges.h"
-#include "confparse.h"
-#include "config.h"
-#include "control.h"
-#include "crypto_ed25519.h"
-#include "crypto_rand.h"
-#include "directory.h"
-#include "dirserv.h"
-#include "dirauth/dirvote.h"
-#include "entrynodes.h"
-#include "hibernate.h"
-#include "memarea.h"
-#include "networkstatus.h"
-#include "router.h"
-#include "routerkeys.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "routerset.h"
-#include "dirauth/shared_random_state.h"
-#include "test.h"
-#include "test_dir_common.h"
-#include "torcert.h"
-#include "relay.h"
-#include "log_test_helpers.h"
-#include "voting_schedule.h"
+#include "core/or/or.h"
+#include "feature/client/bridges.h"
+#include "core/mainloop/connection.h"
+#include "app/config/confparse.h"
+#include "app/config/config.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/dircache/directory.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/client/entrynodes.h"
+#include "feature/dircommon/fp_pair.h"
+#include "feature/hibernate/hibernate.h"
+#include "lib/memarea/memarea.h"
+#include "lib/osinfo/uname.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routerkeys.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/routerset.h"
+#include "feature/dirauth/shared_random_state.h"
+#include "test/test.h"
+#include "test/test_dir_common.h"
+#include "feature/nodelist/torcert.h"
+#include "core/or/relay.h"
+#include "test/log_test_helpers.h"
+#include "feature/dircommon/voting_schedule.h"
+#include "lib/compress/compress.h"
+
+#include "core/or/addr_policy_st.h"
+#include "feature/nodelist/authority_cert_st.h"
+#include "feature/nodelist/document_signature_st.h"
+#include "feature/nodelist/extrainfo_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/networkstatus_voter_info_st.h"
+#include "feature/dirauth/ns_detached_signatures_st.h"
+#include "core/or/port_cfg_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerlist_st.h"
+#include "core/or/tor_version_st.h"
+#include "feature/dirauth/vote_microdesc_hash_st.h"
+#include "feature/nodelist/vote_routerstatus_st.h"
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
#define NS_MODULE dir
@@ -2087,7 +2110,7 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now)
tt_int_op(rs->or_port,OP_EQ, 443);
tt_int_op(rs->dir_port,OP_EQ, 8000);
/* no flags except "running" (16) and "v2dir" (64) and "valid" (128) */
- tt_u64_op(vrs->flags, OP_EQ, U64_LITERAL(0xd0));
+ tt_u64_op(vrs->flags, OP_EQ, UINT64_C(0xd0));
} else if (tor_memeq(rs->identity_digest,
"\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5"
"\x5\x5\x5\x5",
@@ -2113,10 +2136,10 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now)
tt_int_op(rs->ipv6_orport,OP_EQ, 4711);
if (voter == 1) {
/* all except "authority" (1) */
- tt_u64_op(vrs->flags, OP_EQ, U64_LITERAL(254));
+ tt_u64_op(vrs->flags, OP_EQ, UINT64_C(254));
} else {
/* 1023 - authority(1) - madeofcheese(16) - madeoftin(32) */
- tt_u64_op(vrs->flags, OP_EQ, U64_LITERAL(974));
+ tt_u64_op(vrs->flags, OP_EQ, UINT64_C(974));
}
} else if (tor_memeq(rs->identity_digest,
"\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33"
@@ -2926,8 +2949,8 @@ test_dir_scale_bw(void *testdata)
for (i=0; i<8; ++i) {
total += vals_u64[i];
}
- tt_assert(total >= (U64_LITERAL(1)<<60));
- tt_assert(total <= (U64_LITERAL(1)<<62));
+ tt_assert(total >= (UINT64_C(1)<<60));
+ tt_assert(total <= (UINT64_C(1)<<62));
for (i=0; i<8; ++i) {
/* vals[2].u64 is the scaled value of 1.0 */
@@ -6028,4 +6051,3 @@ struct testcase_t dir_tests[] = {
DIR(networkstatus_consensus_has_ipv6, TT_FORK),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_dir_common.c b/src/test/test_dir_common.c
index 230410f7fa..e65e2b0111 100644
--- a/src/test/test_dir_common.c
+++ b/src/test/test_dir_common.c
@@ -1,18 +1,24 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#define DIRVOTE_PRIVATE
-#include "test.h"
-#include "container.h"
-#include "or.h"
-#include "dirauth/dirvote.h"
-#include "nodelist.h"
-#include "routerlist.h"
-#include "test_dir_common.h"
-#include "voting_schedule.h"
+#include "test/test.h"
+#include "core/or/or.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerlist.h"
+#include "test/test_dir_common.h"
+#include "feature/dircommon/voting_schedule.h"
+
+#include "feature/nodelist/authority_cert_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/networkstatus_voter_info_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/dirauth/vote_microdesc_hash_st.h"
+#include "feature/nodelist/vote_routerstatus_st.h"
void dir_common_setup_vote(networkstatus_t **vote, time_t now);
networkstatus_t * dir_common_add_rs_and_parse(networkstatus_t *vote,
diff --git a/src/test/test_dir_common.h b/src/test/test_dir_common.h
index 65b9cf6436..1e90228edb 100644
--- a/src/test/test_dir_common.h
+++ b/src/test/test_dir_common.h
@@ -1,11 +1,11 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "networkstatus.h"
-#include "routerparse.h"
+#include "core/or/or.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/routerparse.h"
#define TEST_DIR_ROUTER_ID_1 3
#define TEST_DIR_ROUTER_ID_2 5
diff --git a/src/test/test_dir_handle_get.c b/src/test/test_dir_handle_get.c
index 688d26bdc1..571b0386e2 100644
--- a/src/test/test_dir_handle_get.c
+++ b/src/test/test_dir_handle_get.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define RENDCOMMON_PRIVATE
@@ -9,30 +9,37 @@
#define CONFIG_PRIVATE
#define RENDCACHE_PRIVATE
-#include "or.h"
-#include "config.h"
-#include "connection.h"
-#include "consdiffmgr.h"
-#include "directory.h"
-#include "test.h"
-#include "compress.h"
-#include "rendcommon.h"
-#include "rendcache.h"
-#include "router.h"
-#include "routerlist.h"
-#include "rend_test_helpers.h"
-#include "microdesc.h"
-#include "test_helpers.h"
-#include "nodelist.h"
-#include "entrynodes.h"
-#include "routerparse.h"
-#include "networkstatus.h"
-#include "proto_http.h"
-#include "geoip.h"
-#include "dirserv.h"
-#include "dirauth/dirvote.h"
-#include "log_test_helpers.h"
-#include "voting_schedule.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "feature/dircache/consdiffmgr.h"
+#include "feature/dircache/directory.h"
+#include "test/test.h"
+#include "lib/compress/compress.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/rend/rendcache.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "test/rend_test_helpers.h"
+#include "feature/nodelist/microdesc.h"
+#include "test/test_helpers.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/client/entrynodes.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/networkstatus.h"
+#include "core/proto/proto_http.h"
+#include "feature/stats/geoip.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/dirauth/dirvote.h"
+#include "test/log_test_helpers.h"
+#include "feature/dircommon/voting_schedule.h"
+
+#include "feature/dircommon/dir_connection_st.h"
+#include "feature/dirclient/dir_server_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/rend/rend_encoded_v2_service_descriptor_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerlist_st.h"
#ifdef _WIN32
/* For mkdir() */
diff --git a/src/test/test_dns.c b/src/test/test_dns.c
index 1fee01d2c0..8369f844f6 100644
--- a/src/test/test_dns.c
+++ b/src/test/test_dns.c
@@ -1,14 +1,18 @@
-/* Copyright (c) 2015-2017, The Tor Project, Inc. */
+/* Copyright (c) 2015-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "test/test.h"
#define DNS_PRIVATE
-#include "dns.h"
-#include "connection.h"
-#include "router.h"
+#include "feature/relay/dns.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "feature/relay/router.h"
+
+#include "core/or/edge_connection_st.h"
+#include "core/or/or_circuit_st.h"
#define NS_MODULE dns
@@ -745,4 +749,3 @@ struct testcase_t dns_tests[] = {
};
#undef NS_MODULE
-
diff --git a/src/test/test_dos.c b/src/test/test_dos.c
index 8ae967f3ae..b411e7b38a 100644
--- a/src/test/test_dos.c
+++ b/src/test/test_dos.c
@@ -5,18 +5,23 @@
#define TOR_CHANNEL_INTERNAL_
#define CIRCUITLIST_PRIVATE
-#include "or.h"
-#include "dos.h"
-#include "circuitlist.h"
-#include "crypto_rand.h"
-#include "geoip.h"
-#include "channel.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "routerlist.h"
-#include "test.h"
-#include "log_test_helpers.h"
+#include "core/or/or.h"
+#include "core/or/dos.h"
+#include "core/or/circuitlist.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/stats/geoip.h"
+#include "core/or/channel.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerlist.h"
+
+#include "feature/nodelist/networkstatus_st.h"
+#include "core/or/or_connection_st.h"
+#include "feature/nodelist/routerstatus_st.h"
+
+#include "test/test.h"
+#include "test/log_test_helpers.h"
static networkstatus_t *dummy_ns = NULL;
static networkstatus_t *
diff --git a/src/test/test_entryconn.c b/src/test/test_entryconn.c
index 9d8a072c77..bec70090e6 100644
--- a/src/test/test_entryconn.c
+++ b/src/test/test_entryconn.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -6,18 +6,23 @@
#define CONNECTION_PRIVATE
#define CONNECTION_EDGE_PRIVATE
-#include "or.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "test/test.h"
-#include "addressmap.h"
-#include "config.h"
-#include "confparse.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "nodelist.h"
+#include "feature/client/addressmap.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "feature/nodelist/nodelist.h"
-#include "hs_cache.h"
-#include "rendcache.h"
+#include "feature/hs/hs_cache.h"
+#include "feature/rend/rendcache.h"
+
+#include "core/or/entry_connection_st.h"
+#include "core/or/socks_request_st.h"
+
+#include "lib/encoding/confline.h"
static void *
entryconn_rewrite_setup(const struct testcase_t *tc)
@@ -830,4 +835,3 @@ struct testcase_t entryconn_tests[] = {
END_OF_TESTCASES
};
-
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index d8bd8e328b..cb694106c4 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -10,28 +10,41 @@
#define ROUTERLIST_PRIVATE
#define DIRECTORY_PRIVATE
-#include "or.h"
-#include "test.h"
-
-#include "bridges.h"
-#include "circuitlist.h"
-#include "circuitbuild.h"
-#include "config.h"
-#include "confparse.h"
-#include "crypto_rand.h"
-#include "directory.h"
-#include "entrynodes.h"
-#include "nodelist.h"
-#include "networkstatus.h"
-#include "policies.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "routerset.h"
-#include "statefile.h"
-#include "util.h"
-
-#include "test_helpers.h"
-#include "log_test_helpers.h"
+#include "core/or/or.h"
+#include "test/test.h"
+
+#include "feature/client/bridges.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuitbuild.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/dircache/directory.h"
+#include "feature/client/entrynodes.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/networkstatus.h"
+#include "core/or/policies.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/routerset.h"
+#include "app/config/statefile.h"
+
+#include "core/or/cpath_build_state_st.h"
+#include "core/or/crypt_path_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "feature/nodelist/microdesc_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/node_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "app/config/or_state_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerstatus_st.h"
+
+#include "test/test_helpers.h"
+#include "test/log_test_helpers.h"
+
+#include "lib/container/bloomfilt.h"
+#include "lib/encoding/confline.h"
/* TODO:
* choose_random_entry() test with state set.
@@ -3070,4 +3083,3 @@ struct testcase_t entrynodes_tests[] = {
END_OF_TESTCASES
};
-
diff --git a/src/test/test_extorport.c b/src/test/test_extorport.c
index e05342cb8a..ff987563c6 100644
--- a/src/test/test_extorport.c
+++ b/src/test/test_extorport.c
@@ -1,19 +1,26 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
+/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONNECTION_PRIVATE
#define EXT_ORPORT_PRIVATE
#define MAIN_PRIVATE
-#include "or.h"
-#include "buffers.h"
-#include "connection.h"
-#include "connection_or.h"
-#include "config.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "ext_orport.h"
-#include "main.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "lib/container/buffers.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_or.h"
+#include "app/config/config.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/relay/ext_orport.h"
+#include "core/mainloop/main.h"
+
+#include "core/or/or_connection_st.h"
+
+#include "test/test.h"
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
/* Test connection_or_remove_from_ext_or_id_map and
* connection_or_set_ext_or_identifier */
@@ -607,4 +614,3 @@ struct testcase_t extorport_tests[] = {
{ "handshake", test_ext_or_handshake, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_geoip.c b/src/test/test_geoip.c
index 6f849f436b..9df8ea7988 100644
--- a/src/test/test_geoip.c
+++ b/src/test/test_geoip.c
@@ -8,10 +8,10 @@
/* These macros pull in declarations for some functions and structures that
* are typically file-private. */
#define GEOIP_PRIVATE
-#include "or.h"
-#include "config.h"
-#include "geoip.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "feature/stats/geoip.h"
+#include "test/test.h"
/* Record odd numbered fake-IPs using ipv6, even numbered fake-IPs
* using ipv4. Since our fake geoip database is the same between
@@ -575,4 +575,3 @@ struct testcase_t geoip_tests[] = {
END_OF_TESTCASES
};
-
diff --git a/src/test/test_guardfraction.c b/src/test/test_guardfraction.c
index 51ca8f08ec..f45a723295 100644
--- a/src/test/test_guardfraction.c
+++ b/src/test/test_guardfraction.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define DIRSERV_PRIVATE
@@ -6,18 +6,20 @@
#define NETWORKSTATUS_PRIVATE
#include "orconfig.h"
-#include "or.h"
-#include "config.h"
-#include "dirserv.h"
-#include "container.h"
-#include "entrynodes.h"
-#include "util.h"
-#include "routerparse.h"
-#include "networkstatus.h"
-
-#include "test.h"
-#include "test_helpers.h"
-#include "log_test_helpers.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/client/entrynodes.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/networkstatus.h"
+
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/dirauth/vote_microdesc_hash_st.h"
+#include "feature/nodelist/vote_routerstatus_st.h"
+
+#include "test/test.h"
+#include "test/test_helpers.h"
+#include "test/log_test_helpers.h"
/** Generate a vote_routerstatus_t for a router with identity digest
* <b>digest_in_hex</b>. */
diff --git a/src/test/test_handles.c b/src/test/test_handles.c
index eb1e1f1bbe..2910d7e18f 100644
--- a/src/test/test_handles.c
+++ b/src/test/test_handles.c
@@ -1,11 +1,13 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
-#include "test.h"
+#include "test/test.h"
-#include "util.h"
-#include "handles.h"
+#include "lib/container/handles.h"
+#include "lib/log/util_bug.h"
+
+#include <stdio.h>
typedef struct demo_t {
HANDLE_ENTRY(demo, demo_t);
@@ -94,4 +96,3 @@ struct testcase_t handle_tests[] = {
HANDLE_TEST(basic, 0),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c
index 1db5e9064f..c666bca59a 100644
--- a/src/test/test_helpers.c
+++ b/src/test/test_helpers.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,21 +12,28 @@
#define MAIN_PRIVATE
#include "orconfig.h"
-#include "or.h"
-
-#include "buffers.h"
-#include "config.h"
-#include "confparse.h"
-#include "connection.h"
-#include "crypto_rand.h"
-#include "main.h"
-#include "nodelist.h"
-#include "relay.h"
-#include "routerlist.h"
-
-#include "test.h"
-#include "test_helpers.h"
-#include "test_connection.h"
+#include "core/or/or.h"
+
+#include "lib/container/buffers.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "core/mainloop/connection.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/relay.h"
+#include "feature/nodelist/routerlist.h"
+#include "lib/encoding/confline.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/connection_st.h"
+#include "feature/nodelist/node_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "feature/nodelist/routerlist_st.h"
+
+#include "test/test.h"
+#include "test/test_helpers.h"
+#include "test/test_connection.h"
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
DISABLE_GCC_WARNING(overlength-strings)
@@ -34,7 +41,7 @@ DISABLE_GCC_WARNING(overlength-strings)
* at large. */
#endif
#include "test_descriptors.inc"
-#include "circuitlist.h"
+#include "core/or/circuitlist.h"
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
ENABLE_GCC_WARNING(overlength-strings)
#endif
@@ -276,4 +283,3 @@ helper_parse_options(const char *conf)
}
return opt;
}
-
diff --git a/src/test/test_helpers.h b/src/test/test_helpers.h
index 9bc8553257..3196c93e6b 100644
--- a/src/test/test_helpers.h
+++ b/src/test/test_helpers.h
@@ -1,10 +1,10 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TEST_HELPERS_H
#define TOR_TEST_HELPERS_H
-#include "or.h"
+#include "core/or/or.h"
const char *get_yesterday_date_str(void);
diff --git a/src/test/test_hs.c b/src/test/test_hs.c
index 07daebc164..135df8e9f3 100644
--- a/src/test/test_hs.c
+++ b/src/test/test_hs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2017, The Tor Project, Inc. */
+/* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,16 +12,27 @@
#define RENDSERVICE_PRIVATE
#define HS_SERVICE_PRIVATE
-#include "or.h"
-#include "test.h"
-#include "control.h"
-#include "config.h"
-#include "hs_common.h"
-#include "rendcommon.h"
-#include "rendservice.h"
-#include "routerset.h"
-#include "circuitbuild.h"
-#include "test_helpers.h"
+#include "core/or/or.h"
+#include "test/test.h"
+#include "feature/control/control.h"
+#include "app/config/config.h"
+#include "feature/hs/hs_common.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/rend/rendservice.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerset.h"
+#include "core/or/circuitbuild.h"
+
+#include "feature/nodelist/node_st.h"
+#include "feature/rend/rend_encoded_v2_service_descriptor_st.h"
+#include "feature/rend/rend_intro_point_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+
+#include "test/test_helpers.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
/* mock ID digest and longname for node that's in nodelist */
#define HSDIR_EXIST_ID "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" \
@@ -1055,4 +1066,3 @@ struct testcase_t hs_tests[] = {
END_OF_TESTCASES
};
-
diff --git a/src/test/test_hs_cache.c b/src/test/test_hs_cache.c
index 458ce1a92e..c1a69af829 100644
--- a/src/test/test_hs_cache.c
+++ b/src/test/test_hs_cache.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,17 +10,21 @@
#define DIRECTORY_PRIVATE
#define HS_CACHE_PRIVATE
-#include "ed25519_cert.h"
-#include "hs_cache.h"
-#include "rendcache.h"
-#include "directory.h"
-#include "networkstatus.h"
-#include "connection.h"
-#include "proto_http.h"
+#include "trunnel/ed25519_cert.h"
+#include "feature/hs/hs_cache.h"
+#include "feature/rend/rendcache.h"
+#include "feature/dircache/directory.h"
+#include "feature/nodelist/networkstatus.h"
+#include "core/mainloop/connection.h"
+#include "core/proto/proto_http.h"
+#include "lib/crypt_ops/crypto_format.h"
-#include "hs_test_helpers.h"
-#include "test_helpers.h"
-#include "test.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+
+#include "test/hs_test_helpers.h"
+#include "test/test_helpers.h"
+#include "test/test.h"
/* Static variable used to encoded the HSDir query. */
static char query_b64[256];
@@ -558,4 +562,3 @@ struct testcase_t hs_cache[] = {
END_OF_TESTCASES
};
-
diff --git a/src/test/test_hs_cell.c b/src/test/test_hs_cell.c
index 5c5236b391..b47929e8eb 100644
--- a/src/test/test_hs_cell.c
+++ b/src/test/test_hs_cell.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,18 +9,18 @@
#define HS_INTROPOINT_PRIVATE
#define HS_SERVICE_PRIVATE
-#include "test.h"
-#include "test_helpers.h"
-#include "log_test_helpers.h"
+#include "test/test.h"
+#include "test/test_helpers.h"
+#include "test/log_test_helpers.h"
-#include "crypto_ed25519.h"
-#include "crypto_rand.h"
-#include "hs_cell.h"
-#include "hs_intropoint.h"
-#include "hs_service.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/hs/hs_cell.h"
+#include "feature/hs/hs_intropoint.h"
+#include "feature/hs/hs_service.h"
/* Trunnel. */
-#include "hs/cell_establish_intro.h"
+#include "trunnel/hs/cell_establish_intro.h"
/** We simulate the creation of an outgoing ESTABLISH_INTRO cell, and then we
* parse it from the receiver side. */
diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c
index 50dca588ed..57da03ca28 100644
--- a/src/test/test_hs_client.c
+++ b/src/test/test_hs_client.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,28 +14,40 @@
#define CIRCUITLIST_PRIVATE
#define CONNECTION_PRIVATE
-#include "test.h"
-#include "test_helpers.h"
-#include "log_test_helpers.h"
-#include "rend_test_helpers.h"
-#include "hs_test_helpers.h"
-
-#include "config.h"
-#include "crypto.h"
-#include "channeltls.h"
-#include "main.h"
-#include "nodelist.h"
-#include "routerset.h"
-
-#include "hs_circuit.h"
-#include "hs_client.h"
-#include "hs_ident.h"
-#include "hs_cache.h"
-#include "circuitlist.h"
-#include "circuitbuild.h"
-#include "connection.h"
-#include "connection_edge.h"
-#include "networkstatus.h"
+#include "test/test.h"
+#include "test/test_helpers.h"
+#include "test/log_test_helpers.h"
+#include "test/rend_test_helpers.h"
+#include "test/hs_test_helpers.h"
+
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "core/or/channeltls.h"
+#include "feature/dircache/directory.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerset.h"
+
+#include "feature/hs/hs_circuit.h"
+#include "feature/hs/hs_circuitmap.h"
+#include "feature/hs/hs_client.h"
+#include "feature/hs/hs_ident.h"
+#include "feature/hs/hs_cache.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuitbuild.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "feature/nodelist/networkstatus.h"
+
+#include "core/or/cpath_build_state_st.h"
+#include "core/or/crypt_path_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "core/or/entry_connection_st.h"
+#include "core/or/extend_info_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "core/or/socks_request_st.h"
static int
mock_connection_ap_handshake_send_begin(entry_connection_t *ap_conn)
@@ -188,17 +200,17 @@ test_e2e_rend_circuit_setup_legacy(void *arg)
/* Make a good RENDEZVOUS1 cell body because it needs to pass key exchange
* digest verification... */
- uint8_t rend_cell_body[DH_KEY_LEN+DIGEST_LEN] = {2};
+ uint8_t rend_cell_body[DH1024_KEY_LEN+DIGEST_LEN] = {2};
{
char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN];
crypto_dh_t *dh_state =
or_circ->build_state->pending_final_cpath->rend_dh_handshake_state;
/* compute and overwrite digest of cell body with the right value */
retval = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh_state,
- (char*)rend_cell_body, DH_KEY_LEN,
+ (char*)rend_cell_body, DH1024_KEY_LEN,
keys, DIGEST_LEN+CPATH_KEY_MATERIAL_LEN);
tt_int_op(retval, OP_GT, 0);
- memcpy(rend_cell_body+DH_KEY_LEN, keys, DIGEST_LEN);
+ memcpy(rend_cell_body+DH1024_KEY_LEN, keys, DIGEST_LEN);
}
/* Setup the circuit */
@@ -600,4 +612,3 @@ struct testcase_t hs_client_tests[] = {
TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_hs_common.c b/src/test/test_hs_common.c
index 7348eb746c..f17cc8aeb3 100644
--- a/src/test/test_hs_common.c
+++ b/src/test/test_hs_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -11,27 +11,34 @@
#define HS_SERVICE_PRIVATE
#define NODELIST_PRIVATE
-#include "test.h"
-#include "test_helpers.h"
-#include "log_test_helpers.h"
-#include "hs_test_helpers.h"
-
-#include "connection_edge.h"
-#include "crypto_rand.h"
-#include "hs_common.h"
-#include "hs_client.h"
-#include "hs_service.h"
-#include "config.h"
-#include "networkstatus.h"
-#include "directory.h"
-#include "dirauth/dirvote.h"
-#include "nodelist.h"
-#include "routerlist.h"
-#include "statefile.h"
-#include "circuitlist.h"
-#include "dirauth/shared_random.h"
-#include "util.h"
-#include "voting_schedule.h"
+#include "test/test.h"
+#include "test/test_helpers.h"
+#include "test/log_test_helpers.h"
+#include "test/hs_test_helpers.h"
+
+#include "core/or/connection_edge.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_client.h"
+#include "feature/hs/hs_service.h"
+#include "app/config/config.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/dircache/directory.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerlist.h"
+#include "app/config/statefile.h"
+#include "core/or/circuitlist.h"
+#include "feature/dirauth/shared_random.h"
+#include "feature/dircommon/voting_schedule.h"
+
+#include "feature/nodelist/microdesc_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/node_st.h"
+#include "app/config/or_state_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerstatus_st.h"
/** Test the validation of HS v3 addresses */
static void
@@ -1826,4 +1833,3 @@ struct testcase_t hs_common_tests[] = {
END_OF_TESTCASES
};
-
diff --git a/src/test/test_hs_config.c b/src/test/test_hs_config.c
index a76be301d3..498d2df197 100644
--- a/src/test/test_hs_config.c
+++ b/src/test/test_hs_config.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,15 +9,15 @@
#define CONFIG_PRIVATE
#define HS_SERVICE_PRIVATE
-#include "test.h"
-#include "test_helpers.h"
-#include "log_test_helpers.h"
+#include "test/test.h"
+#include "test/test_helpers.h"
+#include "test/log_test_helpers.h"
-#include "config.h"
-#include "hs_common.h"
-#include "hs_config.h"
-#include "hs_service.h"
-#include "rendservice.h"
+#include "app/config/config.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_config.h"
+#include "feature/hs/hs_service.h"
+#include "feature/rend/rendservice.h"
static int
helper_config_service(const char *conf, int validate_only)
diff --git a/src/test/test_hs_control.c b/src/test/test_hs_control.c
index 308843e9b8..48402030bf 100644
--- a/src/test/test_hs_control.c
+++ b/src/test/test_hs_control.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -7,23 +7,20 @@
**/
#define CONTROL_PRIVATE
-#define CIRCUITBUILD_PRIVATE
-#define RENDCOMMON_PRIVATE
-#define RENDSERVICE_PRIVATE
-#define HS_SERVICE_PRIVATE
-
-#include "or.h"
-#include "test.h"
-#include "control.h"
-#include "config.h"
-#include "hs_common.h"
-#include "hs_control.h"
-#include "nodelist.h"
-//#include "rendcommon.h"
-//#include "rendservice.h"
-//#include "routerset.h"
-//#include "circuitbuild.h"
-#include "test_helpers.h"
+
+#include "core/or/or.h"
+#include "test/test.h"
+#include "feature/control/control.h"
+#include "app/config/config.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_control.h"
+#include "feature/nodelist/nodelist.h"
+
+#include "feature/nodelist/node_st.h"
+#include "feature/nodelist/routerstatus_st.h"
+#include "lib/crypt_ops/crypto_format.h"
+
+#include "test/test_helpers.h"
/* mock ID digest and longname for node that's in nodelist */
#define HSDIR_EXIST_ID \
@@ -195,4 +192,3 @@ struct testcase_t hs_control_tests[] = {
END_OF_TESTCASES
};
-
diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c
index 14f1a664e7..9a7e66eaea 100644
--- a/src/test/test_hs_descriptor.c
+++ b/src/test/test_hs_descriptor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -8,18 +8,19 @@
#define HS_DESCRIPTOR_PRIVATE
-#include "crypto_ed25519.h"
-#include "crypto_digest.h"
-#include "crypto_rand.h"
-#include "ed25519_cert.h"
-#include "or.h"
-#include "hs_descriptor.h"
-#include "test.h"
-#include "torcert.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_digest.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "trunnel/ed25519_cert.h"
+#include "core/or/or.h"
+#include "feature/hs/hs_descriptor.h"
+#include "test/test.h"
+#include "feature/nodelist/torcert.h"
-#include "hs_test_helpers.h"
-#include "test_helpers.h"
-#include "log_test_helpers.h"
+#include "test/hs_test_helpers.h"
+#include "test/test_helpers.h"
+#include "test/log_test_helpers.h"
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
DISABLE_GCC_WARNING(overlength-strings)
@@ -896,4 +897,3 @@ struct testcase_t hs_descriptor[] = {
END_OF_TESTCASES
};
-
diff --git a/src/test/test_hs_intropoint.c b/src/test/test_hs_intropoint.c
index 1671fa9e7a..7da376471b 100644
--- a/src/test/test_hs_intropoint.c
+++ b/src/test/test_hs_intropoint.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -11,27 +11,29 @@
#define RENDSERVICE_PRIVATE
#define CIRCUITLIST_PRIVATE
-#include "test.h"
-#include "log_test_helpers.h"
-#include "crypto_rand.h"
+#include "test/test.h"
+#include "test/log_test_helpers.h"
+#include "lib/crypt_ops/crypto_rand.h"
-#include "or.h"
-#include "circuitlist.h"
-#include "circuituse.h"
+#include "core/or/or.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
#include "ht.h"
-#include "relay.h"
-#include "rendservice.h"
+#include "core/or/relay.h"
+#include "feature/rend/rendservice.h"
-#include "hs_cell.h"
-#include "hs_circuitmap.h"
-#include "hs_common.h"
-#include "hs_intropoint.h"
-#include "hs_service.h"
+#include "feature/hs/hs_cell.h"
+#include "feature/hs/hs_circuitmap.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_intropoint.h"
+#include "feature/hs/hs_service.h"
+
+#include "core/or/or_circuit_st.h"
/* Trunnel. */
-#include "hs/cell_establish_intro.h"
-#include "hs/cell_introduce1.h"
-#include "hs/cell_common.h"
+#include "trunnel/hs/cell_establish_intro.h"
+#include "trunnel/hs/cell_introduce1.h"
+#include "trunnel/hs/cell_common.h"
static size_t
new_establish_intro_cell(const char *circ_nonce,
diff --git a/src/test/test_hs_ntor.c b/src/test/test_hs_ntor.c
index 8eee54d4b4..eeb0491657 100644
--- a/src/test/test_hs_ntor.c
+++ b/src/test/test_hs_ntor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -6,11 +6,13 @@
* \brief Test hidden service ntor functionality.
*/
-#include "test.h"
-#include "test_helpers.h"
-#include "log_test_helpers.h"
+#include "test/test.h"
+#include "test/test_helpers.h"
+#include "test/log_test_helpers.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
-#include "hs_ntor.h"
+#include "core/crypto/hs_ntor.h"
/* Test the HS ntor handshake. Simulate the sending of an encrypted INTRODUCE1
* cell, and verify the proper derivation of decryption keys on the other end.
@@ -111,4 +113,3 @@ struct testcase_t hs_ntor_tests[] = {
END_OF_TESTCASES
};
-
diff --git a/src/test/test_hs_ntor_cl.c b/src/test/test_hs_ntor_cl.c
index ed1eda58ea..03e34968be 100644
--- a/src/test/test_hs_ntor_cl.c
+++ b/src/test/test_hs_ntor_cl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/** This is a wrapper over the little-t-tor HS ntor functions. The wrapper is
@@ -13,13 +13,13 @@
#include <stdlib.h>
#define ONION_NTOR_PRIVATE
-#include "or.h"
-#include "util.h"
-#include "compat.h"
-#include "crypto.h"
-#include "crypto_curve25519.h"
-#include "hs_ntor.h"
-#include "onion_ntor.h"
+#include "core/or/or.h"
+#include "lib/crypt_ops/crypto.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "core/crypto/hs_ntor.h"
+#include "core/crypto/onion_ntor.h"
#define N_ARGS(n) STMT_BEGIN { \
if (argc < (n)) { \
@@ -252,4 +252,3 @@ main(int argc, char **argv)
return 1;
}
}
-
diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c
index 33b5e96070..8074d260a4 100644
--- a/src/test/test_hs_service.c
+++ b/src/test/test_hs_service.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -22,39 +22,48 @@
#define HS_CLIENT_PRIVATE
#define ROUTERPARSE_PRIVATE
-#include "test.h"
-#include "test_helpers.h"
-#include "log_test_helpers.h"
-#include "rend_test_helpers.h"
-#include "hs_test_helpers.h"
-
-#include "or.h"
-#include "config.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "circuituse.h"
-#include "crypto_rand.h"
-#include "dirauth/dirvote.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "relay.h"
-#include "routerparse.h"
-#include "hs_common.h"
-#include "hs_config.h"
-#include "hs_ident.h"
-#include "hs_intropoint.h"
-#include "hs_ntor.h"
-#include "hs_circuit.h"
-#include "hs_service.h"
-#include "hs_client.h"
-#include "main.h"
-#include "rendservice.h"
-#include "statefile.h"
-#include "dirauth/shared_random_state.h"
-#include "voting_schedule.h"
+#include "test/test.h"
+#include "test/test_helpers.h"
+#include "test/log_test_helpers.h"
+#include "test/rend_test_helpers.h"
+#include "test/hs_test_helpers.h"
+
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/relay.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_config.h"
+#include "feature/hs/hs_ident.h"
+#include "feature/hs/hs_intropoint.h"
+#include "core/crypto/hs_ntor.h"
+#include "feature/hs/hs_circuit.h"
+#include "feature/hs/hs_circuitmap.h"
+#include "feature/hs/hs_service.h"
+#include "feature/hs/hs_client.h"
+#include "core/mainloop/main.h"
+#include "feature/rend/rendservice.h"
+#include "app/config/statefile.h"
+#include "feature/dirauth/shared_random_state.h"
+#include "feature/dircommon/voting_schedule.h"
+
+#include "core/or/cpath_build_state_st.h"
+#include "core/or/crypt_path_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/node_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "app/config/or_state_st.h"
+#include "feature/nodelist/routerinfo_st.h"
/* Trunnel */
-#include "hs/cell_establish_intro.h"
+#include "trunnel/hs/cell_establish_intro.h"
static networkstatus_t mock_ns;
@@ -1627,4 +1636,3 @@ struct testcase_t hs_service_tests[] = {
END_OF_TESTCASES
};
-
diff --git a/src/test/test_introduce.c b/src/test/test_introduce.c
index d502bdddb1..cdfb70bdff 100644
--- a/src/test/test_introduce.c
+++ b/src/test/test_introduce.c
@@ -1,13 +1,13 @@
-/* Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
-#include "crypto.h"
-#include "or.h"
-#include "test.h"
+#include "lib/crypt_ops/crypto.h"
+#include "core/or/or.h"
+#include "test/test.h"
#define RENDSERVICE_PRIVATE
-#include "rendservice.h"
+#include "feature/rend/rendservice.h"
static uint8_t v0_test_plaintext[] =
/* 20 bytes of rendezvous point nickname */
diff --git a/src/test/test_keypin.c b/src/test/test_keypin.c
index 79d7bac902..9af12ff548 100644
--- a/src/test/test_keypin.c
+++ b/src/test/test_keypin.c
@@ -1,13 +1,12 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#define KEYPIN_PRIVATE
-#include "or.h"
-#include "keypin.h"
-#include "util.h"
+#include "core/or/or.h"
+#include "feature/dirauth/keypin.h"
-#include "test.h"
+#include "test/test.h"
static void
test_keypin_parse_line(void *arg)
diff --git a/src/test/test_link_handshake.c b/src/test/test_link_handshake.c
index 6840072d76..e0d12fb472 100644
--- a/src/test/test_link_handshake.c
+++ b/src/test/test_link_handshake.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -8,21 +8,26 @@
#define TOR_CHANNEL_INTERNAL_
#define TORTLS_PRIVATE
-#include "compat.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_or.h"
+#include "core/or/channeltls.h"
+#include "trunnel/link_handshake.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routerkeys.h"
+#include "core/or/scheduler.h"
+#include "feature/nodelist/torcert.h"
-#include "or.h"
-#include "config.h"
-#include "connection.h"
-#include "connection_or.h"
-#include "channeltls.h"
-#include "link_handshake.h"
-#include "router.h"
-#include "routerkeys.h"
-#include "scheduler.h"
-#include "torcert.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 "core/or/var_cell_st.h"
-#include "test.h"
-#include "log_test_helpers.h"
+#include "lib/tls/tortls.h"
+
+#include "test/test.h"
+#include "test/log_test_helpers.h"
static var_cell_t *mock_got_var_cell = NULL;
@@ -1576,4 +1581,3 @@ struct testcase_t link_handshake_tests[] = {
END_OF_TESTCASES
};
-
diff --git a/src/test/test_logging.c b/src/test/test_logging.c
index e373158e34..2e3b8800ac 100644
--- a/src/test/test_logging.c
+++ b/src/test/test_logging.c
@@ -1,10 +1,19 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
+/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+#define CONFIG_PRIVATE
+
#include "orconfig.h"
-#include "or.h"
-#include "torlog.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "lib/err/torerr.h"
+#include "lib/log/torlog.h"
+#include "test/test.h"
+#include "lib/process/subprocess.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
static void
dummy_cb_fn(int severity, uint32_t domain, const char *msg)
@@ -89,7 +98,7 @@ test_sigsafe_err(void *arg)
init_logging(1);
mark_logs_temp();
- add_file_log(&include_bug, fn, 0);
+ open_and_add_file_log(&include_bug, fn, 0);
tor_log_update_sigsafe_err_fds();
close_temp_logs();
@@ -170,4 +179,3 @@ struct testcase_t logging_tests[] = {
{ "ratelim", test_ratelim, 0, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_mainloop.c b/src/test/test_mainloop.c
index 9da8a039dd..f85c224ae9 100644
--- a/src/test/test_mainloop.c
+++ b/src/test/test_mainloop.c
@@ -6,11 +6,11 @@
* \brief Tests for functions closely related to the Tor main loop
*/
-#include "test.h"
-#include "log_test_helpers.h"
+#include "test/test.h"
+#include "test/log_test_helpers.h"
-#include "or.h"
-#include "main.h"
+#include "core/or/or.h"
+#include "core/mainloop/main.h"
static const uint64_t BILLION = 1000000000;
@@ -21,7 +21,7 @@ test_mainloop_update_time_normal(void *arg)
monotime_enable_test_mocking();
/* This is arbitrary */
- uint64_t mt_now = U64_LITERAL(7493289274986);
+ uint64_t mt_now = UINT64_C(7493289274986);
/* This time is in the past as of when this test was written. */
time_t now = 1525272090;
monotime_coarse_set_mock_time_nsec(mt_now);
@@ -63,7 +63,7 @@ test_mainloop_update_time_jumps(void *arg)
monotime_enable_test_mocking();
/* This is arbitrary */
- uint64_t mt_now = U64_LITERAL(7493289274986);
+ uint64_t mt_now = UINT64_C(7493289274986);
/* This time is in the past as of when this test was written. */
time_t now = 220897152;
monotime_coarse_set_mock_time_nsec(mt_now);
diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c
index 4b168f49ed..ec4779ead1 100644
--- a/src/test/test_microdesc.c
+++ b/src/test/test_microdesc.c
@@ -1,19 +1,28 @@
-/* Copyright (c) 2010-2017, The Tor Project, Inc. */
+/* Copyright (c) 2010-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
-#include "or.h"
+#include "core/or/or.h"
-#include "config.h"
+#include "app/config/config.h"
#define DIRVOTE_PRIVATE
-#include "dirauth/dirvote.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "torcert.h"
-
-#include "test.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/torcert.h"
+
+#include "feature/nodelist/microdesc_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerstatus_st.h"
+
+#include "test/test.h"
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
#ifdef _WIN32
/* For mkdir() */
@@ -810,4 +819,3 @@ struct testcase_t microdesc_tests[] = {
{ "corrupt_desc", test_md_corrupt_desc, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_nodelist.c b/src/test/test_nodelist.c
index 9499fd0380..cdd5e95cf0 100644
--- a/src/test/test_nodelist.c
+++ b/src/test/test_nodelist.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2017, The Tor Project, Inc. */
+/* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -6,12 +6,19 @@
* \brief Unit tests for nodelist related functions.
**/
-#include "or.h"
-#include "crypto_rand.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "torcert.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/torcert.h"
+
+#include "feature/nodelist/microdesc_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/node_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerstatus_st.h"
+
+#include "test/test.h"
/** Test the case when node_get_by_id() returns NULL,
* node_get_verbose_nickname_by_id should return the base 16 encoding
diff --git a/src/test/test_ntor_cl.c b/src/test/test_ntor_cl.c
index d0eea85d6f..744b42c9d9 100644
--- a/src/test/test_ntor_cl.c
+++ b/src/test/test_ntor_cl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -6,12 +6,10 @@
#include <stdlib.h>
#define ONION_NTOR_PRIVATE
-#include "or.h"
-#include "util.h"
-#include "compat.h"
-#include "crypto.h"
-#include "crypto_curve25519.h"
-#include "onion_ntor.h"
+#include "core/or/or.h"
+#include "lib/crypt_ops/crypto.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "core/crypto/onion_ntor.h"
#define N_ARGS(n) STMT_BEGIN { \
if (argc < (n)) { \
diff --git a/src/test/test_oom.c b/src/test/test_oom.c
index abf8896452..313a6b3114 100644
--- a/src/test/test_oom.c
+++ b/src/test/test_oom.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* Unit tests for OOM handling logic */
@@ -7,16 +7,21 @@
#define BUFFERS_PRIVATE
#define CIRCUITLIST_PRIVATE
#define CONNECTION_PRIVATE
-#include "or.h"
-#include "buffers.h"
-#include "circuitlist.h"
-#include "compat_libevent.h"
-#include "connection.h"
-#include "config.h"
-#include "crypto_rand.h"
-#include "relay.h"
-#include "test.h"
-#include "test_helpers.h"
+#include "core/or/or.h"
+#include "lib/container/buffers.h"
+#include "core/or/circuitlist.h"
+#include "lib/evloop/compat_libevent.h"
+#include "core/mainloop/connection.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "core/or/relay.h"
+#include "test/test.h"
+#include "test/test_helpers.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/entry_connection_st.h"
+#include "core/or/or_circuit_st.h"
+#include "core/or/origin_circuit_st.h"
/* small replacement mock for circuit_mark_for_close_ to avoid doing all
* the other bookkeeping that comes with marking circuits. */
diff --git a/src/test/test_oos.c b/src/test/test_oos.c
index e72fcf5de9..5f9942d8ae 100644
--- a/src/test/test_oos.c
+++ b/src/test/test_oos.c
@@ -1,16 +1,20 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* Unit tests for OOS handler */
#define CONNECTION_PRIVATE
-#include "or.h"
-#include "config.h"
-#include "connection.h"
-#include "connection_or.h"
-#include "main.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_or.h"
+#include "feature/dircache/directory.h"
+#include "core/mainloop/main.h"
+#include "test/test.h"
+
+#include "feature/dircommon/dir_connection_st.h"
+#include "core/or/or_connection_st.h"
static or_options_t mock_options;
@@ -453,4 +457,3 @@ struct testcase_t oos_tests[] = {
{ "pick_oos_victims", test_oos_pick_oos_victims, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_options.c b/src/test/test_options.c
index 65564f324c..396965401e 100644
--- a/src/test/test_options.c
+++ b/src/test/test_options.c
@@ -1,24 +1,26 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONFIG_PRIVATE
-#include "or.h"
-#include "confparse.h"
-#include "config.h"
-#include "test.h"
-#include "geoip.h"
+#include "core/or/or.h"
+#include "app/config/confparse.h"
+#include "app/config/config.h"
+#include "test/test.h"
+#include "feature/stats/geoip.h"
#define ROUTERSET_PRIVATE
-#include "routerset.h"
-#include "main.h"
-#include "log_test_helpers.h"
+#include "feature/nodelist/routerset.h"
+#include "core/mainloop/main.h"
+#include "test/log_test_helpers.h"
-#include "sandbox.h"
-#include "memarea.h"
-#include "policies.h"
-#include "test_helpers.h"
+#include "lib/sandbox/sandbox.h"
+#include "lib/memarea/memarea.h"
+#include "lib/osinfo/uname.h"
+#include "lib/encoding/confline.h"
+#include "core/or/policies.h"
+#include "test/test_helpers.h"
#define NS_MODULE test_options
@@ -274,7 +276,7 @@ test_options_validate(void *arg)
return;
}
-#define MEGABYTEIFY(mb) (U64_LITERAL(mb) << 20)
+#define MEGABYTEIFY(mb) (UINT64_C(mb) << 20)
static void
test_have_enough_mem_for_dircache(void *arg)
{
@@ -4237,4 +4239,3 @@ struct testcase_t options_tests[] = {
LOCAL_VALIDATE_TEST(accel),
END_OF_TESTCASES /* */
};
-
diff --git a/src/test/test_periodic_event.c b/src/test/test_periodic_event.c
index 34689b64f4..03ba3df793 100644
--- a/src/test/test_periodic_event.c
+++ b/src/test/test_periodic_event.c
@@ -11,15 +11,15 @@
#define HS_SERVICE_PRIVATE
#define MAIN_PRIVATE
-#include "test.h"
-#include "test_helpers.h"
-
-#include "or.h"
-#include "config.h"
-#include "hibernate.h"
-#include "hs_service.h"
-#include "main.h"
-#include "periodic.h"
+#include "test/test.h"
+#include "test/test_helpers.h"
+
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "feature/hibernate/hibernate.h"
+#include "feature/hs/hs_service.h"
+#include "core/mainloop/main.h"
+#include "core/mainloop/periodic.h"
/** Helper function: This is replaced in some tests for the event callbacks so
* we don't actually go into the code path of those callbacks. */
diff --git a/src/test/test_policy.c b/src/test/test_policy.c
index e89d49aaf5..4b1adc91f0 100644
--- a/src/test/test_policy.c
+++ b/src/test/test_policy.c
@@ -1,14 +1,21 @@
-/* Copyright (c) 2013-2017, The Tor Project, Inc. */
+/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
+#include "core/or/or.h"
#define CONFIG_PRIVATE
-#include "config.h"
-#include "router.h"
-#include "routerparse.h"
+#include "app/config/config.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerparse.h"
#define POLICIES_PRIVATE
-#include "policies.h"
-#include "test.h"
+#include "core/or/policies.h"
+#include "lib/encoding/confline.h"
+#include "test/test.h"
+
+#include "core/or/addr_policy_st.h"
+#include "feature/nodelist/node_st.h"
+#include "core/or/port_cfg_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerstatus_st.h"
/* Helper: assert that short_policy parses and writes back out as itself,
or as <b>expected</b> if that's provided. */
@@ -2445,4 +2452,3 @@ struct testcase_t policy_tests[] = {
test_policies_fascist_firewall_choose_address, 0, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_procmon.c b/src/test/test_procmon.c
index 5c52af8693..2c7918f580 100644
--- a/src/test/test_procmon.c
+++ b/src/test/test_procmon.c
@@ -1,14 +1,14 @@
-/* Copyright (c) 2010-2017, The Tor Project, Inc. */
+/* Copyright (c) 2010-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define PROCMON_PRIVATE
#include "orconfig.h"
-#include "or.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "test/test.h"
-#include "procmon.h"
+#include "lib/evloop/procmon.h"
-#include "log_test_helpers.h"
+#include "test/log_test_helpers.h"
#define NS_MODULE procmon
diff --git a/src/test/test_proto_http.c b/src/test/test_proto_http.c
index 2f36fbccd7..1cfa0a752c 100644
--- a/src/test/test_proto_http.c
+++ b/src/test/test_proto_http.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -6,11 +6,11 @@
* \brief Tests for our HTTP protocol parser code
*/
-#include "or.h"
-#include "test.h"
-#include "buffers.h"
-#include "proto_http.h"
-#include "log_test_helpers.h"
+#include "core/or/or.h"
+#include "test/test.h"
+#include "lib/container/buffers.h"
+#include "core/proto/proto_http.h"
+#include "test/log_test_helpers.h"
#define S(str) str, sizeof(str)-1
diff --git a/src/test/test_proto_misc.c b/src/test/test_proto_misc.c
index 263ca47447..1fcb763421 100644
--- a/src/test/test_proto_misc.c
+++ b/src/test/test_proto_misc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -6,14 +6,16 @@
* \brief Test our smaller buffer-based protocol functions
*/
-#include "or.h"
-#include "test.h"
-#include "buffers.h"
-#include "connection_or.h"
-#include "ext_orport.h"
-#include "proto_cell.h"
-#include "proto_control0.h"
-#include "proto_ext_or.h"
+#include "core/or/or.h"
+#include "test/test.h"
+#include "lib/container/buffers.h"
+#include "core/or/connection_or.h"
+#include "feature/relay/ext_orport.h"
+#include "core/proto/proto_cell.h"
+#include "core/proto/proto_control0.h"
+#include "core/proto/proto_ext_or.h"
+
+#include "core/or/var_cell_st.h"
static void
test_proto_var_cell(void *arg)
diff --git a/src/test/test_protover.c b/src/test/test_protover.c
index 70b7c9a85f..5bbf997fde 100644
--- a/src/test/test_protover.c
+++ b/src/test/test_protover.c
@@ -1,15 +1,15 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define PROTOVER_PRIVATE
#include "orconfig.h"
-#include "test.h"
+#include "test/test.h"
-#include "protover.h"
+#include "core/or/protover.h"
-#include "or.h"
-#include "connection_or.h"
+#include "core/or/or.h"
+#include "core/or/connection_or.h"
static void
test_protover_parse(void *arg)
diff --git a/src/test/test_pt.c b/src/test/test_pt.c
index 07b6712ff9..dea3791da2 100644
--- a/src/test/test_pt.c
+++ b/src/test/test_pt.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -8,15 +8,19 @@
#define UTIL_PRIVATE
#define STATEFILE_PRIVATE
#define CONTROL_PRIVATE
-#include "or.h"
-#include "config.h"
-#include "confparse.h"
-#include "control.h"
-#include "transports.h"
-#include "circuitbuild.h"
-#include "util.h"
-#include "statefile.h"
-#include "test.h"
+#define SUBPROCESS_PRIVATE
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "feature/control/control.h"
+#include "feature/client/transports.h"
+#include "core/or/circuitbuild.h"
+#include "app/config/statefile.h"
+#include "test/test.h"
+#include "lib/process/subprocess.h"
+#include "lib/encoding/confline.h"
+
+#include "app/config/or_state_st.h"
static void
reset_mp(managed_proxy_t *mp)
@@ -544,4 +548,3 @@ struct testcase_t pt_tests[] = {
NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_pubsub.c b/src/test/test_pubsub.c
deleted file mode 100644
index 2f047d9f2c..0000000000
--- a/src/test/test_pubsub.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file test_pubsub.c
- * \brief Unit tests for publish-subscribe abstraction.
- **/
-
-#include "or.h"
-#include "test.h"
-#include "pubsub.h"
-
-DECLARE_PUBSUB_STRUCT_TYPES(foobar)
-DECLARE_PUBSUB_TOPIC(foobar)
-DECLARE_NOTIFY_PUBSUB_TOPIC(static, foobar)
-IMPLEMENT_PUBSUB_TOPIC(static, foobar)
-
-struct foobar_event_data_t {
- unsigned u;
- const char *s;
-};
-
-struct foobar_subscriber_data_t {
- const char *name;
- long l;
-};
-
-static int
-foobar_sub1(foobar_event_data_t *ev, foobar_subscriber_data_t *mine)
-{
- ev->u += 10;
- mine->l += 100;
- return 0;
-}
-
-static int
-foobar_sub2(foobar_event_data_t *ev, foobar_subscriber_data_t *mine)
-{
- ev->u += 5;
- mine->l += 50;
- return 0;
-}
-
-static void
-test_pubsub_basic(void *arg)
-{
- (void)arg;
- foobar_subscriber_data_t subdata1 = { "hi", 0 };
- foobar_subscriber_data_t subdata2 = { "wow", 0 };
- const foobar_subscriber_t *sub1;
- const foobar_subscriber_t *sub2;
- foobar_event_data_t ed = { 0, "x" };
- foobar_event_data_t ed2 = { 0, "y" };
- sub1 = foobar_subscribe(foobar_sub1, &subdata1, SUBSCRIBE_ATSTART, 100);
- tt_assert(sub1);
-
- foobar_notify(&ed, 0);
- tt_int_op(subdata1.l, OP_EQ, 100);
- tt_int_op(subdata2.l, OP_EQ, 0);
- tt_int_op(ed.u, OP_EQ, 10);
-
- sub2 = foobar_subscribe(foobar_sub2, &subdata2, 0, 5);
- tt_assert(sub2);
-
- foobar_notify(&ed2, 0);
- tt_int_op(subdata1.l, OP_EQ, 200);
- tt_int_op(subdata2.l, OP_EQ, 50);
- tt_int_op(ed2.u, OP_EQ, 15);
-
- foobar_unsubscribe(sub1);
-
- foobar_notify(&ed, 0);
- tt_int_op(subdata1.l, OP_EQ, 200);
- tt_int_op(subdata2.l, OP_EQ, 100);
- tt_int_op(ed.u, OP_EQ, 15);
-
- done:
- foobar_clear();
-}
-
-struct testcase_t pubsub_tests[] = {
- { "pubsub_basic", test_pubsub_basic, TT_FORK, NULL, NULL },
- END_OF_TESTCASES
-};
-
diff --git a/src/test/test_relay.c b/src/test/test_relay.c
index 73c0ed5586..25084fab37 100644
--- a/src/test/test_relay.c
+++ b/src/test/test_relay.c
@@ -1,17 +1,21 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
+#include "core/or/or.h"
#define CIRCUITBUILD_PRIVATE
-#include "circuitbuild.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
#define RELAY_PRIVATE
-#include "relay.h"
+#include "core/or/relay.h"
/* For init/free stuff */
-#include "scheduler.h"
+#include "core/or/scheduler.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/or_circuit_st.h"
/* Test suite stuff */
-#include "test.h"
-#include "fakechans.h"
+#include "test/test.h"
+#include "test/fakechans.h"
static or_circuit_t * new_fake_orcirc(channel_t *nchan, channel_t *pchan);
@@ -127,4 +131,3 @@ struct testcase_t relay_tests[] = {
TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_relaycell.c b/src/test/test_relaycell.c
index 1bd17b73bf..eb30cab0ec 100644
--- a/src/test/test_relaycell.c
+++ b/src/test/test_relaycell.c
@@ -1,20 +1,26 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* Unit tests for handling different kinds of relay cell */
#define RELAY_PRIVATE
#define CIRCUITLIST_PRIVATE
-#include "or.h"
-#include "main.h"
-#include "config.h"
-#include "connection.h"
-#include "crypto.h"
-#include "circuitbuild.h"
-#include "circuitlist.h"
-#include "connection_edge.h"
-#include "relay.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "core/mainloop/main.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "lib/crypt_ops/crypto.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/connection_edge.h"
+#include "core/or/relay.h"
+#include "test/test.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/crypt_path_st.h"
+#include "core/or/entry_connection_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "core/or/socks_request_st.h"
static int srm_ncalls;
static entry_connection_t *srm_conn;
diff --git a/src/test/test_relaycrypt.c b/src/test/test_relaycrypt.c
index 60bd479719..c3cfb7d10b 100644
--- a/src/test/test_relaycrypt.c
+++ b/src/test/test_relaycrypt.c
@@ -3,14 +3,19 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "circuitbuild.h"
+#include "core/or/or.h"
+#include "core/or/circuitbuild.h"
#define CIRCUITLIST_PRIVATE
-#include "circuitlist.h"
-#include "crypto_rand.h"
-#include "relay.h"
-#include "relay_crypto.h"
-#include "test.h"
+#include "core/or/circuitlist.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "core/or/relay.h"
+#include "core/crypto/relay_crypto.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/or_circuit_st.h"
+#include "core/or/origin_circuit_st.h"
+
+#include "test/test.h"
static const char KEY_MATERIAL[3][CPATH_KEY_MATERIAL_LEN] = {
" 'My public key is in this signed x509 object', said Tom assertively.",
diff --git a/src/test/test_rendcache.c b/src/test/test_rendcache.c
index 9f6cfc4a22..394e28d785 100644
--- a/src/test/test_rendcache.c
+++ b/src/test/test_rendcache.c
@@ -1,18 +1,25 @@
-/* Copyright (c) 2010-2017, The Tor Project, Inc. */
+/* Copyright (c) 2010-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
-#include "or.h"
+#include "core/or/or.h"
-#include "test.h"
+#include "test/test.h"
#define RENDCACHE_PRIVATE
-#include "rendcache.h"
-#include "router.h"
-#include "routerlist.h"
-#include "config.h"
-#include "hs_common.h"
-#include "rend_test_helpers.h"
-#include "log_test_helpers.h"
+#include "feature/rend/rendcache.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "app/config/config.h"
+#include "feature/hs/hs_common.h"
+
+#include "core/or/extend_info_st.h"
+#include "feature/rend/rend_encoded_v2_service_descriptor_st.h"
+#include "feature/rend/rend_intro_point_st.h"
+#include "feature/rend/rend_service_descriptor_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+
+#include "test/rend_test_helpers.h"
+#include "test/log_test_helpers.h"
#define NS_MODULE rend_cache
diff --git a/src/test/test_replay.c b/src/test/test_replay.c
index d8dcc7370c..bca3a6660a 100644
--- a/src/test/test_replay.c
+++ b/src/test/test_replay.c
@@ -1,12 +1,12 @@
-/* Copyright (c) 2012-2017, The Tor Project, Inc. */
+/* Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define REPLAYCACHE_PRIVATE
#include "orconfig.h"
-#include "or.h"
-#include "replaycache.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "feature/hs_common/replaycache.h"
+#include "test/test.h"
static const char *test_buffer =
"Lorem ipsum dolor sit amet, consectetur adipisici elit, sed do eiusmod"
diff --git a/src/test/test_router.c b/src/test/test_router.c
index 4e96e24534..c6a2452c8c 100644
--- a/src/test/test_router.c
+++ b/src/test/test_router.c
@@ -1,21 +1,23 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* Copyright (c) 2017, isis agora lovecruft */
/* See LICENSE for licensing information */
/**
* \file test_router.c
- * \brief Unittests for code in src/or/router.c
+ * \brief Unittests for code in router.c
**/
-#include "or.h"
-#include "config.h"
-#include "crypto_curve25519.h"
-#include "crypto_ed25519.h"
-#include "router.h"
-#include "routerlist.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+
+#include "feature/nodelist/routerinfo_st.h"
/* Test suite stuff */
-#include "test.h"
+#include "test/test.h"
NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void));
@@ -109,4 +111,3 @@ struct testcase_t router_tests[] = {
ROUTER_TEST(dump_router_to_string_no_bridge_distribution_method, TT_FORK),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_routerkeys.c b/src/test/test_routerkeys.c
index e4abcdb92d..1a1bf63ba0 100644
--- a/src/test/test_routerkeys.c
+++ b/src/test/test_routerkeys.c
@@ -1,24 +1,31 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#define ROUTER_PRIVATE
-#include "or.h"
-#include "config.h"
-#include "router.h"
-#include "routerkeys.h"
-#include "util.h"
-#include "crypto.h"
-#include "torcert.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routerkeys.h"
+#include "lib/crypt_ops/crypto.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "feature/nodelist/torcert.h"
+#include "test/test.h"
#ifdef _WIN32
/* For mkdir() */
#include <direct.h>
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
static void
test_routerkeys_write_fingerprint(void *arg)
{
@@ -695,4 +702,3 @@ struct testcase_t routerkeys_tests[] = {
TEST(rsa_ed_crosscert, 0),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_routerlist.c b/src/test/test_routerlist.c
index 701227c1c7..89d1f4f90f 100644
--- a/src/test/test_routerlist.c
+++ b/src/test/test_routerlist.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -13,29 +13,39 @@
#define NETWORKSTATUS_PRIVATE
#define ROUTERLIST_PRIVATE
#define TOR_UNIT_TESTING
-#include "or.h"
-#include "config.h"
-#include "connection.h"
-#include "container.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "directory.h"
-#include "dirauth/dirvote.h"
-#include "entrynodes.h"
-#include "hibernate.h"
-#include "microdesc.h"
-#include "networkstatus.h"
-#include "nodelist.h"
-#include "policies.h"
-#include "router.h"
-#include "routerlist.h"
-#include "routerset.h"
-#include "routerparse.h"
-#include "dirauth/shared_random.h"
-#include "statefile.h"
-#include "test.h"
-#include "test_dir_common.h"
-#include "log_test_helpers.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/dircache/directory.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/client/entrynodes.h"
+#include "feature/hibernate/hibernate.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerset.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/dirauth/shared_random.h"
+#include "app/config/statefile.h"
+
+#include "feature/nodelist/authority_cert_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "feature/nodelist/node_st.h"
+#include "app/config/or_state_st.h"
+#include "feature/nodelist/routerstatus_st.h"
+
+#include "lib/encoding/confline.h"
+#include "lib/container/buffers.h"
+
+#include "test/test.h"
+#include "test/test_dir_common.h"
+#include "test/log_test_helpers.h"
void construct_consensus(char **consensus_text_md, time_t now);
@@ -776,4 +786,3 @@ struct testcase_t routerlist_tests[] = {
{ "warn_early_consensus", test_warn_early_consensus, 0, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_routerset.c b/src/test/test_routerset.c
index c541324674..2017ef0050 100644
--- a/src/test/test_routerset.c
+++ b/src/test/test_routerset.c
@@ -1,15 +1,22 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERSET_PRIVATE
-#include "or.h"
-#include "geoip.h"
-#include "routerset.h"
-#include "routerparse.h"
-#include "policies.h"
-#include "nodelist.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "feature/stats/geoip.h"
+#include "feature/nodelist/routerset.h"
+#include "feature/nodelist/routerparse.h"
+#include "core/or/policies.h"
+#include "feature/nodelist/nodelist.h"
+
+#include "core/or/addr_policy_st.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"
+
+#include "test/test.h"
#define NS_MODULE routerset
@@ -2221,4 +2228,3 @@ struct testcase_t routerset_tests[] = {
TEST_CASE(routerset_free),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_scheduler.c b/src/test/test_scheduler.c
index 841fc69456..2d562299ab 100644
--- a/src/test/test_scheduler.c
+++ b/src/test/test_scheduler.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -8,19 +8,19 @@
#define SCHEDULER_KIST_PRIVATE
#define TOR_CHANNEL_INTERNAL_
#define CHANNEL_PRIVATE_
-#include "or.h"
-#include "config.h"
-#include "compat_libevent.h"
-#include "channel.h"
-#include "channeltls.h"
-#include "connection.h"
-#include "networkstatus.h"
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "lib/evloop/compat_libevent.h"
+#include "core/or/channel.h"
+#include "core/or/channeltls.h"
+#include "core/mainloop/connection.h"
+#include "feature/nodelist/networkstatus.h"
#define SCHEDULER_PRIVATE_
-#include "scheduler.h"
+#include "core/or/scheduler.h"
/* Test suite stuff */
-#include "test.h"
-#include "fakechans.h"
+#include "test/test.h"
+#include "test/fakechans.h"
/* Shamelessly stolen from compat_libevent.c */
#define V(major, minor, patch) \
diff --git a/src/test/test_shared_random.c b/src/test/test_shared_random.c
index 2b3c8c93be..ccf051606f 100644
--- a/src/test/test_shared_random.c
+++ b/src/test/test_shared_random.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define SHARED_RANDOM_PRIVATE
@@ -6,21 +6,29 @@
#define CONFIG_PRIVATE
#define DIRVOTE_PRIVATE
-#include "or.h"
-#include "test.h"
-#include "config.h"
-#include "crypto_rand.h"
-#include "dirauth/dirvote.h"
-#include "dirauth/shared_random.h"
-#include "dirauth/shared_random_state.h"
-#include "log_test_helpers.h"
-#include "networkstatus.h"
-#include "router.h"
-#include "routerkeys.h"
-#include "routerlist.h"
-#include "routerparse.h"
-#include "shared_random_client.h"
-#include "voting_schedule.h"
+#include "core/or/or.h"
+#include "test/test.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/dirauth/shared_random.h"
+#include "feature/dirauth/shared_random_state.h"
+#include "test/log_test_helpers.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routerkeys.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/hs_common/shared_random_client.h"
+#include "feature/dircommon/voting_schedule.h"
+
+#include "feature/dirclient/dir_server_st.h"
+#include "feature/nodelist/networkstatus_st.h"
+#include "app/config/or_state_st.h"
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
static authority_cert_t *mock_cert;
@@ -1390,4 +1398,3 @@ struct testcase_t sr_tests[] = {
NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_slow.c b/src/test/test_slow.c
index e640702499..0b665363ab 100644
--- a/src/test/test_slow.c
+++ b/src/test/test_slow.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,8 +15,8 @@
#include <fcntl.h>
#endif
-#include "or.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "test/test.h"
struct testgroup_t testgroups[] = {
{ "slow/crypto/", slow_crypto_tests },
diff --git a/src/test/test_socks.c b/src/test/test_socks.c
index 8da7191e82..e064cc8db1 100644
--- a/src/test/test_socks.c
+++ b/src/test/test_socks.c
@@ -1,14 +1,17 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "buffers.h"
-#include "config.h"
-#include "proto_socks.h"
-#include "test.h"
-#include "log_test_helpers.h"
+#include "core/or/or.h"
+#include "lib/container/buffers.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/proto/proto_socks.h"
+#include "test/test.h"
+#include "test/log_test_helpers.h"
+#include "core/or/socks_request_st.h"
+#include "lib/net/socks5_status.h"
typedef struct socks_test_data_t {
socks_request_t *req;
@@ -1046,4 +1049,3 @@ struct testcase_t socks_tests[] = {
END_OF_TESTCASES
};
-
diff --git a/src/test/test_status.c b/src/test/test_status.c
index b4ca17891b..3cc23955ad 100644
--- a/src/test/test_status.c
+++ b/src/test/test_status.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2014-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define STATUS_PRIVATE
@@ -11,20 +11,26 @@
#include <float.h>
#include <math.h>
-#include "or.h"
-#include "torlog.h"
+#include "core/or/or.h"
+#include "lib/log/torlog.h"
#include "tor_queue.h"
-#include "status.h"
-#include "circuitlist.h"
-#include "config.h"
-#include "hibernate.h"
-#include "rephist.h"
-#include "relay.h"
-#include "router.h"
-#include "main.h"
-#include "nodelist.h"
-#include "statefile.h"
-#include "test.h"
+#include "core/or/status.h"
+#include "core/or/circuitlist.h"
+#include "app/config/config.h"
+#include "feature/hibernate/hibernate.h"
+#include "feature/stats/rephist.h"
+#include "core/or/relay.h"
+#include "feature/relay/router.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/nodelist.h"
+#include "app/config/statefile.h"
+#include "lib/tls/tortls.h"
+
+#include "core/or/origin_circuit_st.h"
+#include "app/config/or_state_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+
+#include "test/test.h"
#define NS_MODULE status
@@ -226,7 +232,7 @@ NS(test_main)(void *arg)
tor_free(actual);
expected = "10.00 GB";
- actual = bytes_to_usage((U64_LITERAL(1) << 30) * 10L);
+ actual = bytes_to_usage((UINT64_C(1) << 30) * 10L);
tt_str_op(actual, OP_EQ, expected);
tor_free(actual);
@@ -1093,4 +1099,3 @@ struct testcase_t status_tests[] = {
TEST_CASE_ASPECT(log_heartbeat, tls_write_overhead),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_storagedir.c b/src/test/test_storagedir.c
index 26606f9b6e..68cee418ad 100644
--- a/src/test/test_storagedir.c
+++ b/src/test/test_storagedir.c
@@ -1,10 +1,11 @@
-/* Copyright (c) 2017, The Tor Project, Inc. */
+/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "crypto_rand.h"
-#include "storagedir.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/fs/storagedir.h"
+#include "lib/encoding/confline.h"
+#include "test/test.h"
#ifdef HAVE_UTIME_H
#include <utime.h>
@@ -373,4 +374,3 @@ struct testcase_t storagedir_tests[] = {
ENT(read_labeled),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_switch_id.c b/src/test/test_switch_id.c
index fe36d8c6e6..d8a1d15e4e 100644
--- a/src/test/test_switch_id.c
+++ b/src/test/test_switch_id.c
@@ -1,11 +1,15 @@
-/* Copyright (c) 2015-2017, The Tor Project, Inc. */
+/* Copyright (c) 2015-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
+#include "core/or/or.h"
+#include "lib/process/setuid.h"
#ifdef HAVE_SYS_CAPABILITY_H
#include <sys/capability.h>
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#define TEST_BUILT_WITH_CAPS 0
#define TEST_HAVE_CAPS 1
@@ -189,4 +193,3 @@ main(int argc, char **argv)
return (okay ? 0 : 1);
#endif /* defined(_WIN32) */
}
-
diff --git a/src/test/test_threads.c b/src/test/test_threads.c
index ed6d8f04aa..f0a4dd2057 100644
--- a/src/test/test_threads.c
+++ b/src/test/test_threads.c
@@ -1,12 +1,12 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
-#include "or.h"
-#include "compat_threads.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "lib/thread/threads.h"
+#include "test/test.h"
/** mutex for thread test to stop the threads hitting data at the same time. */
static tor_mutex_t *thread_test_mutex_ = NULL;
diff --git a/src/test/test_tortls.c b/src/test/test_tortls.c
index 388f6df325..2b40ed72d9 100644
--- a/src/test/test_tortls.c
+++ b/src/test/test_tortls.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2017, The Tor Project, Inc. */
+/* Copyright (c) 2010-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define TORTLS_PRIVATE
@@ -11,7 +11,7 @@
#endif
#include <math.h>
-#include "compat.h"
+#include "lib/cc/compat_compiler.h"
/* Some versions of OpenSSL declare SSL_get_selected_srtp_profile twice in
* srtp.h. Suppress the GCC warning so we can build with -Wredundant-decl. */
@@ -30,13 +30,14 @@ DISABLE_GCC_WARNING(redundant-decls)
ENABLE_GCC_WARNING(redundant-decls)
-#include "or.h"
-#include "torlog.h"
-#include "config.h"
-#include "tortls.h"
+#include "core/or/or.h"
+#include "lib/log/torlog.h"
+#include "app/config/config.h"
+#include "lib/tls/tortls.h"
+#include "app/config/or_state_st.h"
-#include "test.h"
-#include "log_test_helpers.h"
+#include "test/test.h"
+#include "test/log_test_helpers.h"
#define NS_MODULE tortls
#ifndef HAVE_SSL_STATE
@@ -2839,4 +2840,3 @@ struct testcase_t tortls_tests[] = {
LOCAL_TEST_CASE(context_init_one, 0),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_util.c b/src/test/test_util.c
index ec11bfd5f5..99fee4c5a5 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -8,16 +8,36 @@
#define COMPAT_TIME_PRIVATE
#define CONTROL_PRIVATE
#define UTIL_PRIVATE
-#include "or.h"
-#include "buffers.h"
-#include "config.h"
-#include "control.h"
-#include "crypto_rand.h"
-#include "test.h"
-#include "memarea.h"
-#include "util_process.h"
-#include "log_test_helpers.h"
-#include "compress_zstd.h"
+#define UTIL_MALLOC_PRIVATE
+#define SOCKET_PRIVATE
+#define SUBPROCESS_PRIVATE
+#include "lib/testsupport/testsupport.h"
+#include "core/or/or.h"
+#include "lib/container/buffers.h"
+#include "app/config/config.h"
+#include "feature/control/control.h"
+#include "feature/client/transports.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "test/test.h"
+#include "lib/memarea/memarea.h"
+#include "lib/process/waitpid.h"
+#include "test/log_test_helpers.h"
+#include "lib/compress/compress.h"
+#include "lib/compress/compress_zstd.h"
+#include "lib/encoding/keyval.h"
+#include "lib/fdio/fdio.h"
+#include "lib/fs/winlib.h"
+#include "lib/process/env.h"
+#include "lib/process/pidfile.h"
+#include "lib/process/subprocess.h"
+#include "lib/intmath/weakrng.h"
+#include "lib/thread/numcpus.h"
+#include "lib/math/fp.h"
+#include "lib/math/laplace.h"
+#include "lib/meminfo/meminfo.h"
+#include "lib/time/tvdiff.h"
+#include "lib/encoding/confline.h"
#ifdef HAVE_PWD_H
#include <pwd.h>
@@ -28,6 +48,16 @@
#ifdef HAVE_UTIME_H
#include <utime.h>
#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
#ifdef _WIN32
#include <tchar.h>
#endif
@@ -1901,8 +1931,8 @@ test_util_strmisc(void *arg)
tor_snprintf(buf, 10, "abcdef");
tt_int_op(0,OP_EQ, buf[6]);
/* uint64 */
- tor_snprintf(buf, sizeof(buf), "x!"U64_FORMAT"!x",
- U64_PRINTF_ARG(U64_LITERAL(12345678901)));
+ tor_snprintf(buf, sizeof(buf), "x!%"PRIu64"!x",
+ (UINT64_C(12345678901)));
tt_str_op("x!12345678901!x",OP_EQ, buf);
/* Test str{,case}cmpstart */
@@ -2115,20 +2145,10 @@ test_util_parse_integer(void *arg)
tt_int_op(1,OP_EQ, i);
tt_str_op(cp,OP_EQ, " plus garbage");
/* Illogical min max */
- tor_capture_bugs_(1);
tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,4,&i,NULL));
tt_int_op(0,OP_EQ, i);
- tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_()));
- tt_str_op("!(max < min)", OP_EQ,
- smartlist_get(tor_get_captured_bug_log_(), 0));
- tor_end_capture_bugs_();
- tor_capture_bugs_(1);
tt_int_op(0L,OP_EQ, tor_parse_long("-50",10,100,-100,&i,NULL));
tt_int_op(0,OP_EQ, i);
- tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_()));
- tt_str_op("!(max < min)", OP_EQ,
- smartlist_get(tor_get_captured_bug_log_(), 0));
- tor_end_capture_bugs_();
/* Out of bounds */
tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,100,&i,NULL));
tt_int_op(0,OP_EQ, i);
@@ -2139,11 +2159,8 @@ test_util_parse_integer(void *arg)
tt_int_op(0L,OP_EQ, tor_parse_long("2",2,0,100,NULL,NULL));
tt_int_op(68284L,OP_EQ, tor_parse_long("10abc",16,0,70000,NULL,NULL));
tt_int_op(68284L,OP_EQ, tor_parse_long("10ABC",16,0,70000,NULL,NULL));
- tor_capture_bugs_(2);
tt_int_op(0L,OP_EQ, tor_parse_long("10",-2,0,100,NULL,NULL));
tt_int_op(0,OP_EQ, tor_parse_long("10ABC",-1,0,70000,&i,NULL));
- tt_int_op(2, OP_EQ, smartlist_len(tor_get_captured_bug_log_()));
- tor_end_capture_bugs_();
tt_int_op(i,OP_EQ, 0);
/* Test parse_ulong */
@@ -2156,40 +2173,34 @@ test_util_parse_integer(void *arg)
tt_int_op(0UL,OP_EQ, tor_parse_ulong("8",8,0,100,NULL,NULL));
tt_int_op(50UL,OP_EQ, tor_parse_ulong("50",10,50,100,NULL,NULL));
tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,NULL,NULL));
- tor_capture_bugs_(1);
tt_int_op(0UL,OP_EQ, tor_parse_ulong("50",-1,50,100,&i,NULL));
- tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_()));
- tor_end_capture_bugs_();
tt_int_op(0,OP_EQ, i);
tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,&i,NULL));
tt_int_op(0,OP_EQ, i);
/* Test parse_uint64 */
- tt_assert(U64_LITERAL(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp));
+ tt_assert(UINT64_C(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp));
tt_int_op(1,OP_EQ, i);
tt_str_op(cp,OP_EQ, " x");
- tt_assert(U64_LITERAL(12345678901) ==
+ tt_assert(UINT64_C(12345678901) ==
tor_parse_uint64("12345678901",10,0,UINT64_MAX, &i, &cp));
tt_int_op(1,OP_EQ, i);
tt_str_op(cp,OP_EQ, "");
- tt_assert(U64_LITERAL(0) ==
+ tt_assert(UINT64_C(0) ==
tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp));
tt_int_op(0,OP_EQ, i);
- tor_capture_bugs_(1);
- tt_assert(U64_LITERAL(0) ==
+ tt_assert(UINT64_C(0) ==
tor_parse_uint64("123",-1,0,INT32_MAX, &i, &cp));
- tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_()));
- tor_end_capture_bugs_();
tt_int_op(0,OP_EQ, i);
{
/* Test parse_double */
double d = tor_parse_double("10", 0, (double)UINT64_MAX,&i,NULL);
tt_int_op(1,OP_EQ, i);
- tt_assert(DBL_TO_U64(d) == 10);
+ tt_assert(((uint64_t)d) == 10);
d = tor_parse_double("0", 0, (double)UINT64_MAX,&i,NULL);
tt_int_op(1,OP_EQ, i);
- tt_assert(DBL_TO_U64(d) == 0);
+ tt_assert(((uint64_t)d) == 0);
d = tor_parse_double(" ", 0, (double)UINT64_MAX,&i,NULL);
tt_double_op(fabs(d), OP_LT, 1e-10);
tt_int_op(0,OP_EQ, i);
@@ -2201,7 +2212,7 @@ test_util_parse_integer(void *arg)
tt_int_op(1,OP_EQ, i);
d = tor_parse_double("-.0", 0, (double)UINT64_MAX,&i,NULL);
tt_int_op(1,OP_EQ, i);
- tt_assert(DBL_TO_U64(d) == 0);
+ tt_assert(((uint64_t)d) == 0);
d = tor_parse_double("-10", -100.0, 100.0,&i,NULL);
tt_int_op(1,OP_EQ, i);
tt_double_op(fabs(d - -10.0),OP_LT, 1E-12);
@@ -2219,12 +2230,12 @@ test_util_parse_integer(void *arg)
tt_int_op(i,OP_EQ, 0);
tt_int_op(0UL,OP_EQ, tor_parse_ulong(TOOBIG, 10, 0, ULONG_MAX, &i, NULL));
tt_int_op(i,OP_EQ, 0);
- tt_u64_op(U64_LITERAL(0), OP_EQ, tor_parse_uint64(TOOBIG, 10,
+ tt_u64_op(UINT64_C(0), OP_EQ, tor_parse_uint64(TOOBIG, 10,
0, UINT64_MAX, &i, NULL));
tt_int_op(i,OP_EQ, 0);
}
done:
- tor_end_capture_bugs_();
+ ;
}
static void
@@ -2242,17 +2253,17 @@ test_util_pow2(void *arg)
tt_int_op(tor_log2(3),OP_EQ, 1);
tt_int_op(tor_log2(4),OP_EQ, 2);
tt_int_op(tor_log2(5),OP_EQ, 2);
- tt_int_op(tor_log2(U64_LITERAL(40000000000000000)),OP_EQ, 55);
+ tt_int_op(tor_log2(UINT64_C(40000000000000000)),OP_EQ, 55);
tt_int_op(tor_log2(UINT64_MAX),OP_EQ, 63);
/* Test round_to_power_of_2 */
tt_u64_op(round_to_power_of_2(120), OP_EQ, 128);
tt_u64_op(round_to_power_of_2(128), OP_EQ, 128);
tt_u64_op(round_to_power_of_2(130), OP_EQ, 128);
- tt_u64_op(round_to_power_of_2(U64_LITERAL(40000000000000000)), OP_EQ,
- U64_LITERAL(1)<<55);
- tt_u64_op(round_to_power_of_2(U64_LITERAL(0xffffffffffffffff)), OP_EQ,
- U64_LITERAL(1)<<63);
+ tt_u64_op(round_to_power_of_2(UINT64_C(40000000000000000)), OP_EQ,
+ UINT64_C(1)<<55);
+ tt_u64_op(round_to_power_of_2(UINT64_C(0xffffffffffffffff)), OP_EQ,
+ UINT64_C(1)<<63);
tt_u64_op(round_to_power_of_2(0), OP_EQ, 1);
tt_u64_op(round_to_power_of_2(1), OP_EQ, 1);
tt_u64_op(round_to_power_of_2(2), OP_EQ, 2);
@@ -4102,7 +4113,8 @@ test_util_ftruncate(void *ptr)
tt_int_op(fd, OP_GE, 0);
/* Make the file be there. */
- tt_int_op(strlen(message), OP_EQ, write_all(fd, message, strlen(message),0));
+ tt_int_op(strlen(message), OP_EQ,
+ write_all_to_fd(fd, message, strlen(message)));
tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message));
tt_int_op(0, OP_EQ, fstat(fd, &st));
tt_int_op((int)st.st_size, OP_EQ, strlen(message));
@@ -4115,7 +4127,7 @@ test_util_ftruncate(void *ptr)
/* Replace, and see if it got replaced */
tt_int_op(strlen(message2), OP_EQ,
- write_all(fd, message2, strlen(message2), 0));
+ write_all_to_fd(fd, message2, strlen(message2)));
tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message2));
tt_int_op(0, OP_EQ, fstat(fd, &st));
tt_int_op((int)st.st_size, OP_EQ, strlen(message2));
@@ -5558,15 +5570,15 @@ test_util_max_mem(void *arg)
tt_int_op(r, OP_EQ, r2);
tt_uint_op(memory2, OP_EQ, memory1);
- TT_BLATHER(("System memory: "U64_FORMAT, U64_PRINTF_ARG(memory1)));
+ TT_BLATHER(("System memory: %"TOR_PRIuSZ, (memory1)));
if (r==0) {
/* You have at least a megabyte. */
tt_uint_op(memory1, OP_GT, (1<<20));
} else {
/* You do not have a petabyte. */
-#if SIZEOF_SIZE_T == SIZEOF_UINT64_T
- tt_u64_op(memory1, OP_LT, (U64_LITERAL(1)<<50));
+#if SIZEOF_SIZE_T >= 8
+ tt_u64_op(memory1, OP_LT, (UINT64_C(1)<<50));
#endif
}
@@ -6316,4 +6328,3 @@ struct testcase_t util_tests[] = {
UTIL_TEST(get_unquoted_path, 0),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_util_format.c b/src/test/test_util_format.c
index 10645fe117..85d8a8e62e 100644
--- a/src/test/test_util_format.c
+++ b/src/test/test_util_format.c
@@ -1,14 +1,14 @@
-/* Copyright (c) 2010-2017, The Tor Project, Inc. */
+/* Copyright (c) 2010-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
-#include "or.h"
+#include "core/or/or.h"
-#include "test.h"
+#include "test/test.h"
-#include "crypto_rand.h"
+#include "lib/crypt_ops/crypto_rand.h"
#define UTIL_FORMAT_PRIVATE
-#include "util_format.h"
+#include "lib/encoding/binascii.h"
#define NS_MODULE util_format
@@ -19,7 +19,7 @@ test_util_format_unaligned_accessors(void *ignored)
char buf[9] = "onionsoup"; // 6f6e696f6e736f7570
tt_u64_op(get_uint64(buf+1), OP_EQ,
- tor_htonll(U64_LITERAL(0x6e696f6e736f7570)));
+ tor_htonll(UINT64_C(0x6e696f6e736f7570)));
tt_uint_op(get_uint32(buf+1), OP_EQ, htonl(0x6e696f6e));
tt_uint_op(get_uint16(buf+1), OP_EQ, htons(0x6e69));
tt_uint_op(get_uint8(buf+1), OP_EQ, 0x6e);
@@ -33,7 +33,7 @@ test_util_format_unaligned_accessors(void *ignored)
set_uint32(buf+1, htonl(0x78696465));
tt_mem_op(buf, OP_EQ, "oxidestop", 9);
- set_uint64(buf+1, tor_htonll(U64_LITERAL(0x6266757363617465)));
+ set_uint64(buf+1, tor_htonll(UINT64_C(0x6266757363617465)));
tt_mem_op(buf, OP_EQ, "obfuscate", 9);
done:
;
diff --git a/src/test/test_util_process.c b/src/test/test_util_process.c
index 68ce6cfd40..44c4da9169 100644
--- a/src/test/test_util_process.c
+++ b/src/test/test_util_process.c
@@ -1,15 +1,15 @@
-/* Copyright (c) 2010-2017, The Tor Project, Inc. */
+/* Copyright (c) 2010-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define UTIL_PROCESS_PRIVATE
#include "orconfig.h"
-#include "or.h"
+#include "core/or/or.h"
-#include "test.h"
+#include "test/test.h"
-#include "util_process.h"
+#include "lib/process/waitpid.h"
-#include "log_test_helpers.h"
+#include "test/log_test_helpers.h"
#ifndef _WIN32
#define NS_MODULE util_process
diff --git a/src/test/test_util_slow.c b/src/test/test_util_slow.c
index 2cd68cf118..5021e89dff 100644
--- a/src/test/test_util_slow.c
+++ b/src/test/test_util_slow.c
@@ -1,15 +1,21 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#define UTIL_PRIVATE
-#include "util.h"
-#include "util_process.h"
-#include "crypto.h"
-#include "torlog.h"
-#include "test.h"
+#define SUBPROCESS_PRIVATE
+#include "lib/crypt_ops/crypto.h"
+#include "lib/log/torlog.h"
+#include "lib/process/subprocess.h"
+#include "lib/process/waitpid.h"
+#include "lib/string/printf.h"
+#include "lib/time/compat_time.h"
+#include "test/test.h"
+
+#include <errno.h>
+#include <string.h>
#ifndef BUILDDIR
#define BUILDDIR "."
@@ -388,4 +394,3 @@ struct testcase_t slow_util_tests[] = {
UTIL_TEST(spawn_background_waitpid_notify, 0),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_voting_schedule.c b/src/test/test_voting_schedule.c
index df6058b74f..c3a581cf21 100644
--- a/src/test/test_voting_schedule.c
+++ b/src/test/test_voting_schedule.c
@@ -3,10 +3,10 @@
#include "orconfig.h"
-#include "or.h"
-#include "voting_schedule.h"
+#include "core/or/or.h"
+#include "feature/dircommon/voting_schedule.h"
-#include "test.h"
+#include "test/test.h"
static void
test_voting_schedule_interval_start(void *arg)
diff --git a/src/test/test_workqueue.c b/src/test/test_workqueue.c
index cc7073850c..4550bad1f0 100644
--- a/src/test/test_workqueue.c
+++ b/src/test/test_workqueue.c
@@ -1,15 +1,17 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "or.h"
-#include "compat_threads.h"
-#include "onion.h"
-#include "workqueue.h"
-#include "crypto_curve25519.h"
-#include "crypto_rand.h"
-#include "compat_libevent.h"
+#include "core/or/or.h"
+#include "lib/thread/threads.h"
+#include "core/crypto/onion.h"
+#include "lib/evloop/workqueue.h"
+#include "lib/crypt_ops/crypto_curve25519.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/net/alertsock.h"
+#include "lib/evloop/compat_libevent.h"
+#include "lib/intmath/weakrng.h"
#include <stdio.h>
@@ -450,4 +452,3 @@ main(int argc, char **argv)
return 0;
}
}
-
diff --git a/src/test/test_zero_length_keys.sh b/src/test/test_zero_length_keys.sh
index f85edb68db..84ca513b0a 100755
--- a/src/test/test_zero_length_keys.sh
+++ b/src/test/test_zero_length_keys.sh
@@ -3,8 +3,8 @@
exitcode=0
-"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/or/tor" -z || exitcode=1
-"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/or/tor" -d || exitcode=1
-"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/or/tor" -e || exitcode=1
+"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/app/tor" -z || exitcode=1
+"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/app/tor" -d || exitcode=1
+"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/app/tor" -e || exitcode=1
exit ${exitcode}
diff --git a/src/test/testing_common.c b/src/test/testing_common.c
index 4c3fe15960..3880bca9c5 100644
--- a/src/test/testing_common.c
+++ b/src/test/testing_common.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,20 +10,30 @@
#define MAIN_PRIVATE
#include "orconfig.h"
-#include "or.h"
-#include "control.h"
-#include "config.h"
-#include "crypto_rand.h"
-#include "rephist.h"
-#include "backtrace.h"
-#include "test.h"
-#include "channelpadding.h"
-#include "main.h"
+#include "core/or/or.h"
+#include "feature/control/control.h"
+#include "app/config/config.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "feature/stats/rephist.h"
+#include "lib/err/backtrace.h"
+#include "test/test.h"
+#include "core/or/channelpadding.h"
+#include "core/mainloop/main.h"
+#include "lib/compress/compress.h"
+#include "lib/evloop/compat_libevent.h"
#include <stdio.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
#ifdef _WIN32
/* For mkdir() */
@@ -32,11 +42,6 @@
#include <dirent.h>
#endif /* defined(_WIN32) */
-#ifdef USE_DMALLOC
-#include <dmalloc.h>
-#include "main.h"
-#endif
-
/** Temporary directory (set up by setup_directory) under which we store all
* our files during testing. */
static char temp_dir[256];
@@ -231,13 +236,6 @@ main(int c, const char **v)
/* We must initialise logs before we call tor_assert() */
init_logging(1);
-#ifdef USE_DMALLOC
- {
- int r = crypto_use_tor_alloc_functions();
- tor_assert(r == 0);
- }
-#endif /* defined(USE_DMALLOC) */
-
update_approx_time(time(NULL));
options = options_new();
tor_threads_init();
@@ -319,10 +317,7 @@ main(int c, const char **v)
int have_failed = (tinytest_main(c, v, testgroups) != 0);
free_pregenerated_keys();
-#ifdef USE_DMALLOC
- tor_free_all(0);
- dmalloc_log_unfreed();
-#endif
+
crypto_global_cleanup();
if (have_failed)
@@ -330,4 +325,3 @@ main(int c, const char **v)
else
return 0;
}
-
diff --git a/src/test/testing_rsakeys.c b/src/test/testing_rsakeys.c
index 94d3db328a..a8c9ce4ce8 100644
--- a/src/test/testing_rsakeys.c
+++ b/src/test/testing_rsakeys.c
@@ -1,12 +1,12 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "crypto_rand.h"
+#include "lib/crypt_ops/crypto_rand.h"
#include "orconfig.h"
-#include "or.h"
-#include "test.h"
+#include "core/or/or.h"
+#include "test/test.h"
/** Define this if unit tests spend too much time generating public keys.
* This module is meant to save time by using a bunch of pregenerated RSA
diff --git a/src/tools/include.am b/src/tools/include.am
index 016cf3b124..8a2ecb23c9 100644
--- a/src/tools/include.am
+++ b/src/tools/include.am
@@ -6,45 +6,44 @@ endif
src_tools_tor_resolve_SOURCES = src/tools/tor-resolve.c
src_tools_tor_resolve_LDFLAGS =
-src_tools_tor_resolve_LDADD = src/common/libor.a \
- src/common/libor-ctime.a \
+src_tools_tor_resolve_LDADD = \
+ $(TOR_UTIL_LIBS) \
$(rust_ldadd) \
- @TOR_LIB_MATH@ @TOR_LIB_WS32@ @TOR_LIB_USERENV@
+ @TOR_LIB_MATH@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_USERENV@
if COVERAGE_ENABLED
src_tools_tor_cov_resolve_SOURCES = src/tools/tor-resolve.c
src_tools_tor_cov_resolve_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
src_tools_tor_cov_resolve_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
-src_tools_tor_cov_resolve_LDADD = src/common/libor-testing.a \
- src/common/libor-ctime-testing.a \
+src_tools_tor_cov_resolve_LDADD = \
+ $(TOR_UTIL_TESTING_LIBS) \
@TOR_LIB_MATH@ @TOR_LIB_WS32@
endif
src_tools_tor_gencert_SOURCES = src/tools/tor-gencert.c
src_tools_tor_gencert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@
-src_tools_tor_gencert_LDADD = src/common/libor.a src/common/libor-crypto.a \
- src/common/libor-ctime.a \
- $(LIBKECCAK_TINY) \
- $(LIBDONNA) \
+src_tools_tor_gencert_LDADD = \
+ $(TOR_CRYPTO_LIBS) \
+ $(TOR_UTIL_LIBS) \
$(rust_ldadd) \
@TOR_LIB_MATH@ @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ \
- @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@
+ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@
if COVERAGE_ENABLED
src_tools_tor_cov_gencert_SOURCES = src/tools/tor-gencert.c
src_tools_tor_cov_gencert_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
src_tools_tor_cov_gencert_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
src_tools_tor_cov_gencert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@
-src_tools_tor_cov_gencert_LDADD = src/common/libor-testing.a \
- src/common/libor-crypto-testing.a \
- src/common/libor-ctime-testing.a \
- $(LIBKECCAK_TINY) \
- $(LIBDONNA) \
+src_tools_tor_cov_gencert_LDADD = \
+ $(TOR_CRYPTO_TESTING_LIBS) \
+ $(TOR_UTIL_TESTING_LIBS) \
@TOR_LIB_MATH@ @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ \
- @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@
+ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @CURVE25519_LIBS@
endif
if BUILD_LIBTORRUNNER
noinst_LIBRARIES += src/tools/libtorrunner.a
-src_tools_libtorrunner_a_SOURCES = src/tools/tor_runner.c src/or/tor_api.c
+src_tools_libtorrunner_a_SOURCES = \
+ src/tools/tor_runner.c \
+ src/feature/api/tor_api.c
endif
diff --git a/src/tools/tor-gencert.c b/src/tools/tor-gencert.c
index aafefdad74..ce032ed643 100644
--- a/src/tools/tor-gencert.c
+++ b/src/tools/tor-gencert.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2017, The Tor Project, Inc. */
+/* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -13,7 +13,7 @@
#include <unistd.h>
#endif
-#include "compat.h"
+#include "lib/cc/compat_compiler.h"
/* Some versions of OpenSSL declare X509_STORE_CTX_set_verify_cb twice in
* x509.h and x509_vfy.h. Suppress the GCC warning so we can build with
@@ -30,20 +30,20 @@ DISABLE_GCC_WARNING(redundant-decls)
ENABLE_GCC_WARNING(redundant-decls)
#include <errno.h>
-#if 0
-#include <stdlib.h>
-#include <stdarg.h>
-#include <assert.h>
-#endif
-#include "util.h"
-#include "torlog.h"
-#include "crypto.h"
-#include "crypto_digest.h"
-#include "crypto_rand.h"
-#include "crypto_util.h"
-#include "address.h"
-#include "util_format.h"
+#include "lib/crypt_ops/crypto.h"
+#include "lib/crypt_ops/crypto_digest.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/encoding/binascii.h"
+#include "lib/encoding/time_fmt.h"
+#include "lib/fs/files.h"
+#include "lib/log/torlog.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/net/address.h"
+#include "lib/net/ipv4.h"
+#include "lib/string/compat_string.h"
+#include "lib/string/printf.h"
#define IDENTITY_KEY_BITS 3072
#define SIGNING_KEY_BITS 2048
@@ -78,29 +78,6 @@ show_help(void)
"[--passphrase-fd <fd>]\n");
}
-/* XXXX copied from crypto.c */
-static void
-crypto_log_errors(int severity, const char *doing)
-{
- unsigned long err;
- const char *msg, *lib, *func;
- while ((err = ERR_get_error()) != 0) {
- msg = (const char*)ERR_reason_error_string(err);
- lib = (const char*)ERR_lib_error_string(err);
- func = (const char*)ERR_func_error_string(err);
- if (!msg) msg = "(null)";
- if (!lib) lib = "(null)";
- if (!func) func = "(null)";
- if (doing) {
- tor_log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)",
- doing, msg, lib, func);
- } else {
- tor_log(severity, LD_CRYPTO, "crypto error: %s (in %s:%s)",
- msg, lib, func);
- }
- }
-}
-
/** Read the passphrase from the passphrase fd. */
static int
load_passphrase(void)
@@ -108,7 +85,7 @@ load_passphrase(void)
char *cp;
char buf[1024]; /* "Ought to be enough for anybody." */
memset(buf, 0, sizeof(buf)); /* should be needless */
- ssize_t n = read_all(passphrase_fd, buf, sizeof(buf), 0);
+ ssize_t n = read_all_from_fd(passphrase_fd, buf, sizeof(buf));
if (n < 0) {
log_err(LD_GENERAL, "Couldn't read from passphrase fd: %s",
strerror(errno));
@@ -599,4 +576,3 @@ main(int argc, char **argv)
crypto_global_cleanup();
return r;
}
-
diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c
index 966b88b3e8..1532d5f201 100644
--- a/src/tools/tor-resolve.c
+++ b/src/tools/tor-resolve.c
@@ -1,20 +1,25 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson
- * Copyright (c) 2007-2017, The Tor Project, Inc.
+ * Copyright (c) 2007-2018, The Tor Project, Inc.
*/
/* See LICENSE for licensing information */
#include "orconfig.h"
-#include "compat.h"
-#include "util.h"
-#include "address.h"
-#include "torlog.h"
-#include "sandbox.h"
+
+#include "lib/arch/bytes.h"
+#include "lib/log/torlog.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/net/address.h"
+#include "lib/net/resolve.h"
+#include "lib/net/socket.h"
+#include "lib/sandbox/sandbox.h"
+#include "lib/string/util_string.h"
+
+#include "lib/net/socks5_status.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
-#include <assert.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
@@ -225,11 +230,11 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
if (version == 5) {
char method_buf[2];
- if (write_all(s, "\x05\x01\x00", 3, 1) != 3) {
+ if (write_all_to_socket(s, "\x05\x01\x00", 3) != 3) {
log_err(LD_NET, "Error sending SOCKS5 method list.");
goto err;
}
- if (read_all(s, method_buf, 2, 1) != 2) {
+ if (read_all_from_socket(s, method_buf, 2) != 2) {
log_err(LD_NET, "Error reading SOCKS5 methods.");
goto err;
}
@@ -251,7 +256,7 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
tor_assert(!req);
goto err;
}
- if (write_all(s, req, len, 1) != len) {
+ if (write_all_to_socket(s, req, len) != len) {
log_sock_error("sending SOCKS request", s);
tor_free(req);
goto err;
@@ -260,7 +265,7 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
if (version == 4) {
char reply_buf[RESPONSE_LEN_4];
- if (read_all(s, reply_buf, RESPONSE_LEN_4, 1) != RESPONSE_LEN_4) {
+ if (read_all_from_socket(s, reply_buf, RESPONSE_LEN_4) != RESPONSE_LEN_4) {
log_err(LD_NET, "Error reading SOCKS4 response.");
goto err;
}
@@ -271,7 +276,7 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
}
} else {
char reply_buf[16];
- if (read_all(s, reply_buf, 4, 1) != 4) {
+ if (read_all_from_socket(s, reply_buf, 4) != 4) {
log_err(LD_NET, "Error reading SOCKS5 response.");
goto err;
}
@@ -291,14 +296,14 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
}
if (reply_buf[3] == 1) {
/* IPv4 address */
- if (read_all(s, reply_buf, 4, 1) != 4) {
+ if (read_all_from_socket(s, reply_buf, 4) != 4) {
log_err(LD_NET, "Error reading address in socks5 response.");
goto err;
}
tor_addr_from_ipv4n(result_addr, get_uint32(reply_buf));
} else if (reply_buf[3] == 4) {
/* IPv6 address */
- if (read_all(s, reply_buf, 16, 1) != 16) {
+ if (read_all_from_socket(s, reply_buf, 16) != 16) {
log_err(LD_NET, "Error reading address in socks5 response.");
goto err;
}
@@ -306,13 +311,14 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
} else if (reply_buf[3] == 3) {
/* Domain name */
size_t result_len;
- if (read_all(s, reply_buf, 1, 1) != 1) {
+ if (read_all_from_socket(s, reply_buf, 1) != 1) {
log_err(LD_NET, "Error reading address_length in socks5 response.");
goto err;
}
result_len = *(uint8_t*)(reply_buf);
*result_hostname = tor_malloc(result_len+1);
- if (read_all(s, *result_hostname, result_len, 1) != (int) result_len) {
+ if (read_all_from_socket(s, *result_hostname, result_len)
+ != (int) result_len) {
log_err(LD_NET, "Error reading hostname in socks5 response.");
goto err;
}
@@ -451,4 +457,3 @@ main(int argc, char **argv)
}
return 0;
}
-
diff --git a/src/tools/tor_runner.c b/src/tools/tor_runner.c
index 9ed2ee5775..dd90af3df5 100644
--- a/src/tools/tor_runner.c
+++ b/src/tools/tor_runner.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2017, The Tor Project, Inc. */
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -23,8 +23,8 @@
* functions. Don't add more dependencies!
*/
-#include "tor_api.h"
-#include "tor_api_internal.h"
+#include "feature/api/tor_api.h"
+#include "feature/api/tor_api_internal.h"
#include "orconfig.h"
#ifdef HAVE_UNISTD_H
diff --git a/src/trace/include.am b/src/trace/include.am
deleted file mode 100644
index 3285b04de6..0000000000
--- a/src/trace/include.am
+++ /dev/null
@@ -1,22 +0,0 @@
-# Include the src/ so we can use the trace/events.h statement when including
-# any file in that directory.
-AM_CPPFLAGS += -I$(srcdir)/src
-
-noinst_LIBRARIES += \
- src/trace/libor-trace.a
-LIBOR_TRACE_A_SOURCES = \
- src/trace/trace.c
-
-TRACEHEADERS = \
- src/trace/trace.h \
- src/trace/events.h
-
-if USE_EVENT_TRACING_DEBUG
-TRACEHEADERS += \
- src/trace/debug.h
-endif
-
-# Library source files.
-src_trace_libor_trace_a_SOURCES = $(LIBOR_TRACE_A_SOURCES)
-
-noinst_HEADERS+= $(TRACEHEADERS)
diff --git a/src/trunnel/include.am b/src/trunnel/include.am
index b249fb302c..5a0a79c3a0 100644
--- a/src/trunnel/include.am
+++ b/src/trunnel/include.am
@@ -6,8 +6,6 @@ noinst_LIBRARIES += \
src/trunnel/libor-trunnel-testing.a
endif
-AM_CPPFLAGS += -I$(srcdir)/src/ext/trunnel -I$(srcdir)/src/trunnel
-
TRUNNELINPUTS = \
src/trunnel/ed25519_cert.trunnel \
src/trunnel/link_handshake.trunnel \
@@ -39,7 +37,8 @@ TRUNNELHEADERS = \
src/trunnel/channelpadding_negotiation.h
src_trunnel_libor_trunnel_a_SOURCES = $(TRUNNELSOURCES)
-src_trunnel_libor_trunnel_a_CPPFLAGS = -DTRUNNEL_LOCAL_H $(AM_CPPFLAGS)
+src_trunnel_libor_trunnel_a_CPPFLAGS = \
+ -DTRUNNEL_LOCAL_H $(AM_CPPFLAGS) -I$(top_srcdir)/src/trunnel
if UNITTESTS_ENABLED
src_trunnel_libor_trunnel_testing_a_SOURCES = $(TRUNNELSOURCES)
@@ -54,4 +53,3 @@ noinst_HEADERS+= $(TRUNNELHEADERS)
EXTRA_DIST += \
src/trunnel/README
-
diff --git a/src/trunnel/trunnel-local.h b/src/trunnel/trunnel-local.h
index 8aa6d0ddaa..e81396aeea 100644
--- a/src/trunnel/trunnel-local.h
+++ b/src/trunnel/trunnel-local.h
@@ -2,9 +2,9 @@
#ifndef TRUNNEL_LOCAL_H_INCLUDED
#define TRUNNEL_LOCAL_H_INCLUDED
-#include "util.h"
-#include "compat.h"
-#include "crypto_util.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/malloc/util_malloc.h"
+#include "lib/log/util_bug.h"
#define trunnel_malloc tor_malloc
#define trunnel_calloc tor_calloc
diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h
index 45578f9bb8..65a905debe 100644
--- a/src/win32/orconfig.h
+++ b/src/win32/orconfig.h
@@ -218,7 +218,7 @@
#define USING_TWOS_COMPLEMENT
/* Version number of package */
-#define VERSION "0.3.4.4-rc"
+#define VERSION "0.3.5.0-alpha-dev"