#include "orconfig.h"
#include "core/or/or.h"
#include "app/config/resolve_addr.h"
#include "core/mainloop/periodic.h"
#include "core/mainloop/cpuworker.h"
#include "core/mainloop/mainloop.h"
#include "core/mainloop/netstatus.h"
#include "core/or/circuituse.h"
#include "feature/relay/dns.h"
#include "feature/relay/relay_periodic.h"
#include "feature/relay/router.h"
#include "feature/relay/routerkeys.h"
#include "feature/relay/routermode.h"
#include "feature/relay/selftest.h"
#include "feature/stats/predict_ports.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "feature/nodelist/routerinfo_st.h"
#include "feature/control/control_events.h"
#ifndef COCCI
#define DECLARE_EVENT(name, roles, flags) \
static periodic_event_item_t name ## _event = \
PERIODIC_EVENT(name, \
PERIODIC_EVENT_ROLE_##roles, \
flags)
#endif
#define FL(name) (PERIODIC_EVENT_FLAG_##name)
static int
retry_dns_callback(time_t now, const or_options_t *options)
{
(void)now;
#define RETRY_DNS_INTERVAL (10*60)
if (server_mode(options) && has_dns_init_failed())
dns_init();
return RETRY_DNS_INTERVAL;
}
DECLARE_EVENT(retry_dns, ROUTER, 0);
static int dns_honesty_first_time = 1;
static int
check_dns_honesty_callback(time_t now, const or_options_t *options)
{
(void)now;
if (net_is_disabled() ||
! public_server_mode(options) ||
router_my_exit_policy_is_reject_star())
return PERIODIC_EVENT_NO_UPDATE;
if (dns_honesty_first_time) {
dns_honesty_first_time = 0;
return crypto_rand_int_range(60, 180);
}
dns_launch_correctness_checks();
return 12*3600 + crypto_rand_int(12*3600);
}
DECLARE_EVENT(check_dns_honesty, RELAY, FL(NEED_NET));
static int
rotate_onion_key_callback(time_t now, const or_options_t *options)
{
if (server_mode(options)) {
int onion_key_lifetime = get_onion_key_lifetime();
time_t rotation_time = get_onion_key_set_at()+onion_key_lifetime;
if (rotation_time > now) {
return ONION_KEY_CONSENSUS_CHECK_INTERVAL;
}
log_info(LD_GENERAL,"Rotating onion key.");
rotate_onion_key();
cpuworkers_rotate_keyinfo();
if (!router_rebuild_descriptor(1)) {
log_info(LD_CONFIG, "Couldn't rebuild router descriptor");
}
if (advertised_server_mode() && !net_is_disabled())
router_upload_dir_desc_to_dirservers(0);
return ONION_KEY_CONSENSUS_CHECK_INTERVAL;
}
return PERIODIC_EVENT_NO_UPDATE;
}
DECLARE_EVENT(rotate_onion_key, ROUTER, 0);
static int
check_descriptor_callback(time_t now, const or_options_t *options)
{
#define CHECK_DESCRIPTOR_INTERVAL (60)
(void)options;
if (!net_is_disabled()) {
check_descriptor_bandwidth_changed(now);
check_descriptor_ipaddress_changed(now);
mark_my_descriptor_dirty_if_too_old(now);
consider_publishable_server(0);
}
return CHECK_DESCRIPTOR_INTERVAL;
}
DECLARE_EVENT(check_descriptor, ROUTER, FL(NEED_NET));
static int dirport_reachability_count = 0;
static int
check_for_reachability_bw_callback(time_t now, const or_options_t *options)
{
#define EARLY_CHECK_REACHABILITY_INTERVAL (60)
if (server_mode(options) &&
(have_completed_a_circuit() || !any_predicted_circuits(now)) &&
!net_is_disabled()) {
if (get_uptime() < TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) {
router_do_reachability_checks(1, dirport_reachability_count==0);
if (++dirport_reachability_count > 5)
dirport_reachability_count = 0;
return EARLY_CHECK_REACHABILITY_INTERVAL;
} else {
const routerinfo_t *me = router_get_my_routerinfo();
static int first_time = 1;
if (!first_time && me &&
me->bandwidthcapacity < me->bandwidthrate &&
me->bandwidthcapacity < 51200) {
reset_bandwidth_test();
}
first_time = 0;
#define BANDWIDTH_RECHECK_INTERVAL (12*60*60)
return BANDWIDTH_RECHECK_INTERVAL;
}
}
return CHECK_DESCRIPTOR_INTERVAL;
}
DECLARE_EVENT(check_for_reachability_bw, ROUTER, FL(NEED_NET));
static int
reachability_warnings_callback(time_t now, const or_options_t *options)
{
(void) now;
if (get_uptime() < TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) {
return (int)(TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT - get_uptime());
}
if (server_mode(options) &&
!net_is_disabled() &&
have_completed_a_circuit()) {
const routerinfo_t *me = router_get_my_routerinfo();
bool v4_ok =
router_orport_seems_reachable(options,AF_INET);
bool v6_ok =
router_orport_seems_reachable(options,AF_INET6);
if (me && !(v4_ok && v6_ok)) {
char *address4 = tor_addr_to_str_dup(&me->ipv4_addr);
char *address6 = tor_addr_to_str_dup(&me->ipv6_addr);
if (address4 || address6) {
char *where4=NULL, *where6=NULL;
if (!v4_ok)
tor_asprintf(&where4, "%s:%d", address4, me->ipv4_orport);
if (!v6_ok)
tor_asprintf(&where6, "[%s]:%d", address6, me->ipv6_orport);
const char *opt_and = (!v4_ok && !v6_ok) ? "and" : "";
if (v4_ok && !v6_ok && !resolved_addr_is_configured(AF_INET6)) {
static ratelim_t rlim = RATELIM_INIT(3600);
log_fn_ratelim(&rlim, LOG_NOTICE, LD_CONFIG,
"Auto-discovered IPv6 address %s has not been found "
"reachable. However, IPv4 address is reachable. "
"Publishing server descriptor without IPv6 address.",
where6 ? where6 : "");
mark_my_descriptor_if_omit_ipv6_changes("IPv4 is reachable. "
"IPv6 is not but was "
"auto-discovered", true);
} else {
log_warn(LD_CONFIG,
"Your server has not managed to confirm reachability for "
"its ORPort(s) at %s%s%s. Relays do not publish "
"descriptors until their ORPort and DirPort are "
"reachable. Please check your firewalls, ports, address, "
"/etc/hosts file, etc.",
where4?where4:"",
opt_and,
where6?where6:"");
}
tor_free(where4);
tor_free(where6);
if (!v4_ok) {
control_event_server_status(LOG_WARN,
"REACHABILITY_FAILED ORADDRESS=%s:%d",
address4, me->ipv4_orport);
}
if (!v6_ok) {
control_event_server_status(LOG_WARN,
"REACHABILITY_FAILED ORADDRESS=[%s]:%d",
address6, me->ipv6_orport);
}
}
tor_free(address4);
tor_free(address6);
}
if (me && !router_dirport_seems_reachable(options)) {
char *address4 = tor_addr_to_str_dup(&me->ipv4_addr);
log_warn(LD_CONFIG,
"Your server (%s:%d) has not managed to confirm that its "
"DirPort is reachable. Relays do not publish descriptors "
"until their ORPort and DirPort are reachable. Please check "
"your firewalls, ports, address, /etc/hosts file, etc.",
address4, me->ipv4_dirport);
control_event_server_status(LOG_WARN,
"REACHABILITY_FAILED DIRADDRESS=%s:%d",
address4, me->ipv4_dirport);
tor_free(address4);
}
}
return TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT;
}
DECLARE_EVENT(reachability_warnings, ROUTER, FL(NEED_NET));
static int
check_ed_keys_callback(time_t now, const or_options_t *options)
{
if (server_mode(options)) {
if (should_make_new_ed_keys(options, now)) {
int new_signing_key = load_ed_keys(options, now);
if (new_signing_key < 0 ||
generate_ed_link_cert(options, now, new_signing_key > 0)) {
log_err(LD_OR, "Unable to update Ed25519 keys! Exiting.");
tor_shutdown_event_loop_and_exit(1);
}
}
return 30;
}
return PERIODIC_EVENT_NO_UPDATE;
}
DECLARE_EVENT(check_ed_keys, ROUTER, 0);
static int
check_onion_keys_expiry_time_callback(time_t now, const or_options_t *options)
{
if (server_mode(options)) {
int onion_key_grace_period = get_onion_key_grace_period();
time_t expiry_time = get_onion_key_set_at()+onion_key_grace_period;
if (expiry_time > now) {
return ONION_KEY_CONSENSUS_CHECK_INTERVAL;
}
log_info(LD_GENERAL, "Expiring old onion keys.");
expire_old_onion_keys();
cpuworkers_rotate_keyinfo();
return ONION_KEY_CONSENSUS_CHECK_INTERVAL;
}
return PERIODIC_EVENT_NO_UPDATE;
}
DECLARE_EVENT(check_onion_keys_expiry_time, ROUTER, 0);
void
relay_register_periodic_events(void)
{
periodic_events_register(&retry_dns_event);
periodic_events_register(&check_dns_honesty_event);
periodic_events_register(&rotate_onion_key_event);
periodic_events_register(&check_descriptor_event);
periodic_events_register(&check_for_reachability_bw_event);
periodic_events_register(&reachability_warnings_event);
periodic_events_register(&check_ed_keys_event);
periodic_events_register(&check_onion_keys_expiry_time_event);
dns_honesty_first_time = 1;
dirport_reachability_count = 0;
}
void
reschedule_descriptor_update_check(void)
{
periodic_event_reschedule(&check_descriptor_event);
}