📄 config.c
字号:
set_conn_limit = 1;
/* Set up libevent. (We need to do this before we can register the
* listeners as listeners.) */
if (running_tor && !libevent_initialized) {
init_libevent();
libevent_initialized = 1;
}
/* Launch the listeners. (We do this before we setuid, so we can bind to
* ports under 1024.) */
if (retry_all_listeners(replaced_listeners, new_listeners) < 0) {
*msg = tor_strdup("Failed to bind one of the listener ports.");
goto rollback;
}
}
/* Setuid/setgid as appropriate */
if (options->User || options->Group) {
/* XXXX021 We should only do this the first time through, not on
* every setconf. */
if (switch_id(options->User, options->Group) != 0) {
/* No need to roll back, since you can't change the value. */
*msg = tor_strdup("Problem with User or Group value. "
"See logs for details.");
goto done;
}
}
/* Ensure data directory is private; create if possible. */
if (check_private_dir(options->DataDirectory,
running_tor ? CPD_CREATE : CPD_CHECK)<0) {
char buf[1024];
int tmp = tor_snprintf(buf, sizeof(buf),
"Couldn't access/create private data directory \"%s\"",
options->DataDirectory);
*msg = tor_strdup(tmp >= 0 ? buf : "internal error");
goto done;
/* No need to roll back, since you can't change the value. */
}
/* Bail out at this point if we're not going to be a client or server:
* we don't run Tor itself. */
if (!running_tor)
goto commit;
mark_logs_temp(); /* Close current logs once new logs are open. */
logs_marked = 1;
if (options_init_logs(options, 0)<0) { /* Configure the log(s) */
*msg = tor_strdup("Failed to init Log options. See logs for details.");
goto rollback;
}
commit:
r = 0;
if (logs_marked) {
log_severity_list_t *severity =
tor_malloc_zero(sizeof(log_severity_list_t));
close_temp_logs();
add_callback_log(severity, control_event_logmsg);
control_adjust_event_log_severity();
tor_free(severity);
}
SMARTLIST_FOREACH(replaced_listeners, connection_t *, conn,
{
log_notice(LD_NET, "Closing old %s on %s:%d",
conn_type_to_string(conn->type), conn->address, conn->port);
connection_close_immediate(conn);
connection_mark_for_close(conn);
});
goto done;
rollback:
r = -1;
tor_assert(*msg);
if (logs_marked) {
rollback_log_changes();
control_adjust_event_log_severity();
}
if (set_conn_limit && old_options)
set_max_file_descriptors((unsigned)old_options->ConnLimit,
&options->_ConnLimit);
SMARTLIST_FOREACH(new_listeners, connection_t *, conn,
{
log_notice(LD_NET, "Closing partially-constructed listener %s on %s:%d",
conn_type_to_string(conn->type), conn->address, conn->port);
connection_close_immediate(conn);
connection_mark_for_close(conn);
});
done:
smartlist_free(new_listeners);
smartlist_free(replaced_listeners);
return r;
}
/** Fetch the active option list, and take actions based on it. All of the
* things we do should survive being done repeatedly. If present,
* <b>old_options</b> contains the previous value of the options.
*
* Return 0 if all goes well, return -1 if it's time to die.
*
* Note: We haven't moved all the "act on new configuration" logic
* here yet. Some is still in do_hup() and other places.
*/
static int
options_act(or_options_t *old_options)
{
config_line_t *cl;
char *fn;
size_t len;
or_options_t *options = get_options();
int running_tor = options->command == CMD_RUN_TOR;
char *msg;
if (consider_adding_dir_authorities(options, old_options) < 0)
return -1;
if (options->Bridges) {
clear_bridge_list();
for (cl = options->Bridges; cl; cl = cl->next) {
if (parse_bridge_line(cl->value, 0)<0) {
log_warn(LD_BUG,
"Previously validated Bridge line could not be added!");
return -1;
}
}
}
if (running_tor && rend_config_services(options, 0)<0) {
log_warn(LD_BUG,
"Previously validated hidden services line could not be added!");
return -1;
}
if (running_tor && directory_caches_v2_dir_info(options)) {
len = strlen(options->DataDirectory)+32;
fn = tor_malloc(len);
tor_snprintf(fn, len, "%s"PATH_SEPARATOR"cached-status",
options->DataDirectory);
if (check_private_dir(fn, CPD_CREATE) != 0) {
log_warn(LD_CONFIG,
"Couldn't access/create private data directory \"%s\"", fn);
tor_free(fn);
return -1;
}
tor_free(fn);
}
/* Load state */
if (! global_state && running_tor) {
if (or_state_load())
return -1;
rep_hist_load_mtbf_data(time(NULL));
}
/* Bail out at this point if we're not going to be a client or server:
* we want to not fork, and to log stuff to stderr. */
if (!running_tor)
return 0;
{
smartlist_t *sl = smartlist_create();
char *errmsg = NULL;
for (cl = options->RedirectExit; cl; cl = cl->next) {
if (parse_redirect_line(sl, cl, &errmsg)<0) {
log_warn(LD_CONFIG, "%s", errmsg);
tor_free(errmsg);
SMARTLIST_FOREACH(sl, exit_redirect_t *, er, tor_free(er));
smartlist_free(sl);
return -1;
}
}
set_exit_redirects(sl);
}
/* Finish backgrounding the process */
if (running_tor && options->RunAsDaemon) {
/* We may be calling this for the n'th time (on SIGHUP), but it's safe. */
finish_daemon(options->DataDirectory);
}
/* Write our pid to the pid file. If we do not have write permissions we
* will log a warning */
if (running_tor && options->PidFile)
write_pidfile(options->PidFile);
/* Register addressmap directives */
config_register_addressmaps(options);
parse_virtual_addr_network(options->VirtualAddrNetwork, 0, &msg);
/* Update address policies. */
if (policies_parse_from_options(options) < 0) {
/* This should be impossible, but let's be sure. */
log_warn(LD_BUG,"Error parsing already-validated policy options.");
return -1;
}
if (init_cookie_authentication(options->CookieAuthentication) < 0) {
log_warn(LD_CONFIG,"Error creating cookie authentication file.");
return -1;
}
/* reload keys as needed for rendezvous services. */
if (rend_service_load_keys()<0) {
log_warn(LD_GENERAL,"Error loading rendezvous service keys");
return -1;
}
/* Set up accounting */
if (accounting_parse_options(options, 0)<0) {
log_warn(LD_CONFIG,"Error in accounting options");
return -1;
}
if (accounting_is_enabled(options))
configure_accounting(time(NULL));
/* Check for transitions that need action. */
if (old_options) {
if (options->UseEntryGuards && !old_options->UseEntryGuards) {
log_info(LD_CIRC,
"Switching to entry guards; abandoning previous circuits");
circuit_mark_all_unused_circs();
circuit_expire_all_dirty_circs();
}
if (options_transition_affects_workers(old_options, options)) {
log_info(LD_GENERAL,
"Worker-related options changed. Rotating workers.");
if (server_mode(options) && !server_mode(old_options)) {
if (init_keys() < 0) {
log_warn(LD_BUG,"Error initializing keys; exiting");
return -1;
}
ip_address_changed(0);
if (has_completed_circuit || !any_predicted_circuits(time(NULL)))
inform_testing_reachability();
}
cpuworkers_rotate();
if (dns_reset())
return -1;
} else {
if (dns_reset())
return -1;
}
if (options->V3AuthoritativeDir && !old_options->V3AuthoritativeDir)
init_keys();
}
/* Maybe load geoip file */
if (options->GeoIPFile &&
((!old_options || !opt_streq(old_options->GeoIPFile, options->GeoIPFile))
|| !geoip_is_loaded())) {
geoip_load_file(options->GeoIPFile);
}
/* Check if we need to parse and add the EntryNodes config option. */
if (options->EntryNodes &&
(!old_options ||
!opt_streq(old_options->EntryNodes, options->EntryNodes)))
entry_nodes_should_be_added();
/* Since our options changed, we might need to regenerate and upload our
* server descriptor.
*/
if (!old_options ||
options_transition_affects_descriptor(old_options, options))
mark_my_descriptor_dirty();
/* We may need to reschedule some directory stuff if our status changed. */
if (old_options) {
if (authdir_mode_v3(options) && !authdir_mode_v3(old_options))
dirvote_recalculate_timing(options, time(NULL));
if (!bool_eq(directory_fetches_dir_info_early(options),
directory_fetches_dir_info_early(old_options)) ||
!bool_eq(directory_fetches_dir_info_later(options),
directory_fetches_dir_info_later(old_options))) {
/* Make sure update_router_have_min_dir_info gets called. */
router_dir_info_changed();
/* We might need to download a new consensus status later or sooner than
* we had expected. */
update_consensus_networkstatus_fetch_time(time(NULL));
}
}
return 0;
}
/*
* Functions to parse config options
*/
/** If <b>option</b> is an official abbreviation for a longer option,
* return the longer option. Otherwise return <b>option</b>.
* If <b>command_line</b> is set, apply all abbreviations. Otherwise, only
* apply abbreviations that work for the config file and the command line.
* If <b>warn_obsolete</b> is set, warn about deprecated names. */
static const char *
expand_abbrev(config_format_t *fmt, const char *option, int command_line,
int warn_obsolete)
{
int i;
if (! fmt->abbrevs)
return option;
for (i=0; fmt->abbrevs[i].abbreviated; ++i) {
/* Abbreviations are casei. */
if (!strcasecmp(option,fmt->abbrevs[i].abbreviated) &&
(command_line || !fmt->abbrevs[i].commandline_only)) {
if (warn_obsolete && fmt->abbrevs[i].warn) {
log_warn(LD_CONFIG,
"The configuration option '%s' is deprecated; "
"use '%s' instead.",
fmt->abbrevs[i].abbreviated,
fmt->abbrevs[i].full);
}
return fmt->abbrevs[i].full;
}
}
return option;
}
/** Helper: Read a list of configuration options from the command line.
* If successful, put them in *<b>result</b> and return 0, and return
* -1 and leave *<b>result</b> alone. */
static int
config_get_commandlines(int argc, char **argv, config_line_t **result)
{
config_line_t *front = NULL;
config_line_t **new = &front;
char *s;
int i = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -