Back to index

tor  0.2.3.19-rc
Classes | Defines | Typedefs | Enumerations | Functions | Variables
config.c File Reference

Code to parse and interpret configuration files. More...

#include "or.h"
#include "circuitbuild.h"
#include "circuitlist.h"
#include "config.h"
#include "connection.h"
#include "connection_edge.h"
#include "connection_or.h"
#include "control.h"
#include "cpuworker.h"
#include "dirserv.h"
#include "dirvote.h"
#include "dns.h"
#include "geoip.h"
#include "hibernate.h"
#include "main.h"
#include "networkstatus.h"
#include "policies.h"
#include "relay.h"
#include "rendclient.h"
#include "rendservice.h"
#include "rephist.h"
#include "router.h"
#include "util.h"
#include "routerlist.h"
#include "transports.h"
#include "procmon.h"

Go to the source code of this file.

Classes

struct  config_abbrev_t
 An abbreviation for a configuration option allowed on the command line. More...
struct  config_var_t
 A variable allowed in the configuration file or on the command line. More...
struct  config_var_description_t
 Represents an English description of a configuration variable; used when generating configuration file comments. More...
struct  config_format_t
 Information on the keys, value types, key-to-struct-member mappings, variable descriptions, validation functions, and abbreviations for a configuration or storage format. More...
struct  unit_table_t
 Mapping from a unit name to a multiplier for converting that unit into a base unit. More...

Defines

#define CONFIG_PRIVATE
#define PLURAL(tok)   { #tok, #tok "s", 0, 0 }
#define VAR(name, conftype, member, initvalue)
 An entry for config_vars: "The option name has type CONFIG_TYPE_conftype, and corresponds to or_options_t.
#define V(member, conftype, initvalue)   VAR(#member, conftype, member, initvalue)
 As VAR, but the option name and member name are the same.
#define OBSOLETE(name)   { name, CONFIG_TYPE_OBSOLETE, 0, NULL }
 An entry for config_vars: "The option <b>name</b> is obsolete.".
#define VAR(name, conftype, member, initvalue)
 An entry for config_vars: "The option name has type CONFIG_TYPE_conftype, and corresponds to or_options_t.
#define CHECK(fmt, cfg)
 Macro: assert that cfg has the right magic field for format fmt.
#define OR_OPTIONS_MAGIC   9090909
 Magic value for or_options_t.
#define OR_STATE_MAGIC   0x57A73f57
 Magic value for or_state_t.
#define RELAY_BRIDGE_STATS_DELAY   (6 * 60 * 60)
#define MIN_REND_POST_PERIOD   (10*60)
 Lowest allowable value for RendPostPeriod; if this is too low, hidden services can overload the directory system.
#define MAX_DIR_PERIOD   (MIN_ONION_KEY_LIFETIME/2)
 Highest allowable value for RendPostPeriod.
#define MIN_MAX_CIRCUIT_DIRTINESS   10
 Lowest allowable value for MaxCircuitDirtiness; if this is too low, Tor will generate too many circuits and potentially overload the network.
#define MIN_CIRCUIT_STREAM_TIMEOUT   10
 Lowest allowable value for CircuitStreamTimeout; if this is too low, Tor will generate too many circuits and potentially overload the network.
#define MIN_HEARTBEAT_PERIOD   (30*60)
 Lowest allowable value for HeartbeatPeriod; if this is too low, we might expose more information than we're comfortable with.
#define RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT   (10)
 Lowest recommended value for CircuitBuildTimeout; if it is set too low and LearnCircuitBuildTimeout is off, the failure rate for circuit construction may be very high.
#define REJECT(arg)   STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
#define COMPLAIN(arg)   STMT_BEGIN log(LOG_WARN, LD_CONFIG, arg); STMT_END
#define CL_PORT_NO_OPTIONS   (1u<<0)
#define CL_PORT_WARN_NONLOCAL   (1u<<1)
#define CL_PORT_ALLOW_EXTRA_LISTENADDR   (1u<<2)
#define CL_PORT_SERVER_OPTIONS   (1u<<3)
#define CL_PORT_FORBID_NONLOCAL   (1u<<4)
#define GENERATED_FILE_PREFIX
 This string must remain the same forevermore.
#define GENERATED_FILE_COMMENT
 This string can change; it tries to give the reader an idea that editing this file by hand is not a good plan.
#define STATE_WRITE_RETRY_INTERVAL   3600
 If writing the state to disk fails, try again after this many seconds.
#define STATE_RELAY_CHECKPOINT_INTERVAL   (12*60*60)
 If we're a relay, how often should we checkpoint our state file even if nothing else dirties it? This will checkpoint ongoing stats like bandwidth used, per-country user stats, etc.
#define VERY_OLD_FILE_AGE   (28*24*60*60)

Typedefs

typedef enum config_type_t config_type_t
 Enumeration of types which option values can take.
typedef struct config_abbrev_t config_abbrev_t
 An abbreviation for a configuration option allowed on the command line.
typedef struct config_var_t config_var_t
 A variable allowed in the configuration file or on the command line.
typedef struct
config_var_description_t 
config_var_description_t
 Represents an English description of a configuration variable; used when generating configuration file comments.
typedef int(* validate_fn_t )(void *, void *, int, char **)
 Type of a callback to validate whether a given configuration is well-formed and consistent.

Enumerations

enum  config_type_t {
  CONFIG_TYPE_STRING = 0, CONFIG_TYPE_FILENAME, CONFIG_TYPE_UINT, CONFIG_TYPE_INT,
  CONFIG_TYPE_PORT, CONFIG_TYPE_INTERVAL, CONFIG_TYPE_MSEC_INTERVAL, CONFIG_TYPE_MEMUNIT,
  CONFIG_TYPE_DOUBLE, CONFIG_TYPE_BOOL, CONFIG_TYPE_AUTOBOOL, CONFIG_TYPE_ISOTIME,
  CONFIG_TYPE_CSV, CONFIG_TYPE_LINELIST, CONFIG_TYPE_LINELIST_S, CONFIG_TYPE_LINELIST_V,
  CONFIG_TYPE_ROUTERSET, CONFIG_TYPE_OBSOLETE
}
 Enumeration of types which option values can take. More...

Functions

static void config_line_append (config_line_t **lst, const char *key, const char *val)
 Helper: allocate a new configuration option mapping 'key' to 'val', append it to *lst.
static void option_clear (const config_format_t *fmt, or_options_t *options, const config_var_t *var)
 Reset config option var to 0, 0.0, NULL, or the equivalent.
static void option_reset (const config_format_t *fmt, or_options_t *options, const config_var_t *var, int use_defaults)
 Clear the option indexed by var in options.
static void config_free (const config_format_t *fmt, void *options)
 Release storage held by options.
static int config_lines_eq (config_line_t *a, config_line_t *b)
 Return true iff a and b contain identical keys and values in identical order.
static int option_is_same (const config_format_t *fmt, const or_options_t *o1, const or_options_t *o2, const char *name)
 Return true iff the option name has the same value in o1 and o2.
static or_options_toptions_dup (const config_format_t *fmt, const or_options_t *old)
 Copy storage held by old into a new or_options_t and return it.
static int options_validate (or_options_t *old_options, or_options_t *options, int from_setconf, char **msg)
 Return 0 if every setting in options is reasonable, and a permissible transition from old_options.
static int options_act_reversible (const or_options_t *old_options, char **msg)
 Fetch the active option list, and take actions based on it.
static int options_act (const or_options_t *old_options)
 Fetch the active option list, and take actions based on it.
static int options_transition_allowed (const or_options_t *old, const or_options_t *new_val, char **msg)
 Check if any of the previous options have changed but aren't allowed to.
static int options_transition_affects_workers (const or_options_t *old_options, const or_options_t *new_options)
 Return 1 if any change from old_options to new_options will require us to rotate the CPU and DNS workers; else return 0.
static int options_transition_affects_descriptor (const or_options_t *old_options, const or_options_t *new_options)
 Return 1 if any change from old_options to new_options will require us to generate a new descriptor; else return 0.
static int check_nickname_list (const char *lst, const char *name, char **msg)
 Verify whether lst is a string containing valid-looking comma-separated nicknames, or NULL.
static int parse_bridge_line (const char *line, int validate_only)
 Read the contents of a Bridge line from line.
static int parse_client_transport_line (const char *line, int validate_only)
 Read the contents of a ClientTransportPlugin line from line.
static int parse_server_transport_line (const char *line, int validate_only)
 Read the contents of a ServerTransportPlugin line from line.
static int parse_dir_server_line (const char *line, dirinfo_type_t required_type, int validate_only)
 Read the contents of a DirServer line from line.
static void port_cfg_free (port_cfg_t *port)
 Free all storage held in port
static int parse_ports (const or_options_t *options, int validate_only, char **msg, int *n_ports_out)
 Parse all client port types (Socks, DNS, Trans, NATD) from options.
static int check_server_ports (const smartlist_t *ports, const or_options_t *options)
 Given a list of port_cfg_t in ports, check them for internal consistency and warn as appropriate.
static int validate_data_directory (or_options_t *options)
 Check and normalize the value of options->DataDirectory; return 0 if it is sane, -1 otherwise.
static int write_configuration_file (const char *fname, const or_options_t *options)
 Save a configuration file for the configuration in options into the file fname.
static config_line_tget_assigned_option (const config_format_t *fmt, const void *options, const char *key, int escape_val)
 Return newly allocated line or lines corresponding to key in the configuration options.
static void config_init (const config_format_t *fmt, void *options)
 Set all vars in the configuration object options to their default values.
static int or_state_validate (or_state_t *old_state, or_state_t *state, int from_setconf, char **msg)
 Return 0 if every setting in state is reasonable, and a permissible transition from old_state.
static int or_state_load (void)
 Reload the persistent state from disk, generating a new state as needed.
static int options_init_logs (or_options_t *options, int validate_only)
 Initialize the logs based on the configuration file.
static uint64_t config_parse_memunit (const char *s, int *ok)
 Parse a string in the format "number unit", where unit is a unit of information (byte, KB, M, etc).
static int config_parse_msec_interval (const char *s, int *ok)
 Parse a string in the format "number unit", where unit is a unit of time in milliseconds.
static int config_parse_interval (const char *s, int *ok)
 Parse a string in the format "number unit", where unit is a unit of time.
static void init_libevent (const or_options_t *options)
 Initialize the libevent library.
static int opt_streq (const char *s1, const char *s2)
 Helper: return true iff s1 and s2 are both NULL, or both non-NULL equal strings.
const char * get_dirportfrontpage (void)
 Return the contents of our frontpage string, or NULL if not configured.
static void * config_alloc (const config_format_t *fmt)
 Allocate an empty configuration object of a given format type.
or_options_tget_options_mutable (void)
 Return the currently configured options.
const or_options_tget_options (void)
 Returns the currently configured options.
int set_options (or_options_t *new_val, char **msg)
 Change the current global options to contain new_val instead of their current value; take action based on the new value; free the old value as necessary.
const char * get_version (void)
 Return the current Tor version.
const char * get_short_version (void)
 Return the current Tor version, without any git tag.
static void or_options_free (or_options_t *options)
 Release additional memory allocated in options.
void config_free_all (void)
 Release all memory and resources held by global configuration structures.
const char * safe_str_client (const char *address)
 Make address -- a piece of information related to our operation as a client -- safe to log according to the settings in options->SafeLogging, and return it.
const char * safe_str (const char *address)
 Make address -- a piece of information of unspecified sensitivity -- safe to log according to the settings in options->SafeLogging, and return it.
const char * escaped_safe_str_client (const char *address)
 Equivalent to escaped(safe_str_client(address)).
const char * escaped_safe_str (const char *address)
 Equivalent to escaped(safe_str(address)).
static void add_default_trusted_dir_authorities (dirinfo_type_t type)
 Add the default directory authorities directly into the trusted dir list, but only add them insofar as they share bits with type.
static int validate_dir_authorities (or_options_t *options, or_options_t *old_options)
 Look at all the config options for using alternate directory authorities, and make sure none of them are broken.
static int consider_adding_dir_authorities (const or_options_t *options, const or_options_t *old_options)
 Look at all the config options and assign new dir authorities as appropriate.
int options_need_geoip_info (const or_options_t *options, const char **reason_out)
 If we need to have a GEOIP ip-to-country map to run with our configured options, return 1 and set *reason_out to a description of why.
uint32_t get_effective_bwrate (const or_options_t *options)
 Return the bandwidthrate that we are going to report to the authorities based on the config options.
uint32_t get_effective_bwburst (const or_options_t *options)
 Return the bandwidthburst that we are going to report to the authorities based on the config options.
static int options_transition_requires_fresh_tls_context (const or_options_t *old_options, const or_options_t *new_options)
 Return True if any changes from old_options to new_options needs us to refresh our TLS context.
static const char * expand_abbrev (const config_format_t *fmt, const char *option, int command_line, int warn_obsolete)
 If option is an official abbreviation for a longer option, return the longer option.
static int config_get_commandlines (int argc, char **argv, config_line_t **result)
 Helper: Read a list of configuration options from the command line.
int config_get_lines (const char *string, config_line_t **result, int extended)
 Helper: parse the config string and strdup into key/value strings.
void config_free_lines (config_line_t *front)
 Free all the configuration lines on the linked list front.
static config_var_tconfig_find_option_mutable (config_format_t *fmt, const char *key)
 As config_find_option, but return a non-const pointer.
static const config_var_tconfig_find_option (const config_format_t *fmt, const char *key)
 If key is a configuration option, return the corresponding const config_var_t.
static int config_count_options (const config_format_t *fmt)
 Return the number of option entries in fmt.
static int config_assign_value (const config_format_t *fmt, or_options_t *options, config_line_t *c, char **msg)
 c->key is known to be a real key.
static void config_mark_lists_fragile (const config_format_t *fmt, or_options_t *options)
 Mark every linelist in options "fragile", so that fresh assignments to it will replace old ones.
static int config_assign_line (const config_format_t *fmt, or_options_t *options, config_line_t *c, int use_defaults, int clear_first, bitarray_t *options_seen, char **msg)
 If c is a syntactically valid configuration line, update options with its value and return 0.
static void config_reset_line (const config_format_t *fmt, or_options_t *options, const char *key, int use_defaults)
 Restore the option named key in options to its default value.
int option_is_recognized (const char *key)
 Return true iff key is a valid configuration option.
const char * option_get_canonical_name (const char *key)
 Return the canonical name of a configuration option, or NULL if no such option exists.
config_line_toption_get_assignment (const or_options_t *options, const char *key)
 Return a canonical list of the options assigned for key.
static int config_value_needs_escape (const char *value)
 Return true iff value needs to be quoted and escaped to be used in a configuration file.
static config_line_tconfig_lines_dup (const config_line_t *inp)
 Return a newly allocated deep copy of the lines in inp.
static int config_assign (const config_format_t *fmt, void *options, config_line_t *list, int use_defaults, int clear_first, char **msg)
 Iterate through the linked list of requested options list.
setopt_err_t options_trial_assign (config_line_t *list, int use_defaults, int clear_first, char **msg)
 Try assigning list to the global options.
static void print_usage (void)
 Print a usage message for tor.
static void list_torrc_options (void)
 Print all non-obsolete torrc options.
int resolve_my_address (int warn_severity, const or_options_t *options, uint32_t *addr_out, char **hostname_out)
 Based on options->Address, guess our public IP address and put it (in host order) into *addr_out.
int is_local_addr (const tor_addr_t *addr)
 Return true iff addr is judged to be on the same network as us, or on a private network.
or_options_toptions_new (void)
 Return a new empty or_options_t.
void options_init (or_options_t *options)
 Set options to hold reasonable defaults for most options.
static char * config_dump (const config_format_t *fmt, const void *default_options, const void *options, int minimal, int comment_defaults)
 Allocate and return a new string holding the written-out values of the vars in 'options'.
char * options_dump (const or_options_t *options, int minimal)
 Return a string containing a possible configuration file that would give the configuration in options.
static int validate_ports_csv (smartlist_t *sl, const char *name, char **msg)
 Return 0 if every element of sl is a string holding a decimal representation of a port number, or if sl is NULL.
static int ensure_bandwidth_cap (uint64_t *value, const char *desc, char **msg)
 If value exceeds ROUTER_MAX_DECLARED_BANDWIDTH, write a complaint into *msg using string desc, and return -1.
static int compute_publishserverdescriptor (or_options_t *options)
 Parse an authority type from options->PublishServerDescriptor and write it to options->_PublishServerDescriptor.
static const char * get_default_conf_file (int defaults_file)
 Return the default location for our torrc file (if defaults_file is false), or for the torrc-defaults file (if defaults_file is true).
static char * find_torrc_filename (int argc, char **argv, int defaults_file, int *using_default_fname, int *ignore_missing_torrc)
 Learn config file name from command line arguments, or use the default.
static char * load_torrc_from_disk (int argc, char **argv, int defaults_file)
 Load a configuration file from disk, setting torrc_fname or torrc_defaults_fname if successful.
int options_init_from_torrc (int argc, char **argv)
 Read a configuration file into options, finding the configuration file location based on the command line.
setopt_err_t options_init_from_string (const char *cf_defaults, const char *cf, int command, const char *command_arg, char **msg)
 Load the options from the configuration in cf, validate them for consistency and take actions based on them.
const char * get_torrc_fname (int defaults_fname)
 Return the location for our configuration file.
void config_register_addressmaps (const or_options_t *options)
 Adjust the address map based on the MapAddress elements in the configuration options
static void warn_nonlocal_client_ports (const smartlist_t *ports, const char *portname)
 Warn for every port in ports that is on a publicly routable address.
static void warn_nonlocal_controller_ports (smartlist_t *ports, unsigned forbid)
 Given a list of port_cfg_t in ports, warn any controller port there is listening on any non-loopback address.
static int parse_port_config (smartlist_t *out, const config_line_t *ports, const config_line_t *listenaddrs, const char *portname, int listener_type, const char *defaultaddr, int defaultport, unsigned flags)
 Parse port configuration for a single port type.
static int parse_unix_socket_config (smartlist_t *out, const config_line_t *cfg, int listener_type)
 Parse a list of config_line_t for an AF_UNIX unix socket listener option from cfg and add them to out.
const smartlist_tget_configured_ports (void)
 Return a list of port_cfg_t for client ports parsed from the options.
char * get_first_listener_addrport_string (int listener_type)
 Return an address:port string representation of the address where the first listener_type listener waits for connections.
int get_first_advertised_port_by_type_af (int listener_type, int address_family)
 Return the first advertised port of type listener_type in address_family.
static int normalize_data_directory (or_options_t *options)
 Adjust the value of options->DataDirectory, or fill it in if it's absent.
int options_save_current (void)
 Save the current configuration file value to disk.
static uint64_t config_parse_units (const char *val, struct unit_table_t *u, int *ok)
 Parse a string val containing a number, zero or more spaces, and an optional unit string.
int get_num_cpus (const or_options_t *options)
 Return the number of cpus configured in options.
or_state_tget_or_state (void)
 Return the persistent state struct for this Tor.
char * options_get_datadir_fname2_suffix (const or_options_t *options, const char *sub1, const char *sub2, const char *suffix)
 Return a newly allocated string holding a filename relative to the data directory.
static int state_transport_line_is_valid (const char *line)
 Return true if line is a valid state TransportProxy line.
static int validate_transports_in_state (or_state_t *state)
 Return 0 if all TransportProxy lines in state are well formed.
static int or_state_set (or_state_t *new_state)
 Replace the current persistent state with new_state
static void or_state_save_broken (char *fname)
 Save a broken state file to a backup location.
int did_last_state_file_write_fail (void)
 Return whether the state file failed to write last time we tried.
int or_state_save (time_t now)
 Write the persistent state to disk.
static config_line_tget_transport_in_state_by_name (const char *transport)
 Return the config line for transport transport in the current state.
static const char * get_transport_bindaddr (const char *line, const char *transport)
 Return string containing the address:port part of the TransportProxy line for transport transport.
char * get_stored_bindaddr_for_server_transport (const char *transport)
 Return a string containing the address:port that a proxy transport should bind on.
void save_transport_to_state (const char *transport, const tor_addr_t *addr, uint16_t port)
 Save transport listening on addr:port to state.
void remove_file_if_very_old (const char *fname, time_t now)
 Given a file name check to see whether the file exists but has not been modified for a very long time.
int getinfo_helper_config (control_connection_t *conn, const char *question, char **answer, const char **errmsg)
 Helper to implement GETINFO functions about configuration variables (not their values).

Variables

int quiet_level
 Decides our behavior when no logs are configured/before any logs have been configured.
static config_abbrev_t _option_abbrevs []
 A list of abbreviations and aliases to map command-line options, obsolete option names, or alternative option names, to their current values.
static config_abbrev_t _state_abbrevs []
 A list of state-file "abbreviations," for compatibility.
static config_var_t _option_vars []
 Array of configuration options.
static const config_var_t testing_tor_network_defaults []
 Override default values with these if the user sets the TestingTorNetwork option.
static config_var_t _state_vars []
 Array of "state" variables saved to the ~/.tor/state file.
static config_format_t options_format
 Configuration format for or_options_t.
static config_var_t state_extra_var
 "Extra" variable in the state that receives lines we can't parse.
static const config_format_t state_format
 Configuration format for or_state_t.
static or_options_tglobal_options = NULL
 Command-line and config-file options.
static or_options_tglobal_default_options = NULL
 The fallback options_t object; this is where we look for options not in torrc before we fall back to Tor's defaults.
static char * torrc_fname = NULL
 Name of most recently read torrc file.
static char * torrc_defaults_fname
 Name of the most recently read torrc-defaults file.
static or_state_tglobal_state = NULL
 Persistent serialized state.
static config_line_tglobal_cmdline_options = NULL
 Configuration Options set by command line.
static char * global_dirfrontpagecontents = NULL
 Contents of most recently read DirPortFrontPage file.
static smartlist_tconfigured_ports = NULL
 List of port_cfg_t for all configured ports.
const char tor_git_revision []
 String describing which Tor subversion repository version the source was built from.
static char * the_tor_version = NULL
 The version of this Tor process, as parsed.
static char * the_short_tor_version = NULL
 A shorter version of this Tor process's version, for export in our router descriptor.
static uint32_t last_resolved_addr = 0
 Last value actually set by resolve_my_address.
static struct unit_table_t []
 Table to map the names of memory units to the number of bytes they contain.
static int last_state_file_write_failed = 0
 Did the last time we tried to write the state file fail? If so, we should consider disabling such features as preemptive circuit generation to compute circuit-build-time.

Detailed Description

Code to parse and interpret configuration files.

Definition in file config.c.


Class Documentation

struct config_abbrev_t

An abbreviation for a configuration option allowed on the command line.

Definition at line 79 of file config.c.

Class Members
const char * abbreviated
int commandline_only
const char * full
int warn
struct config_var_t

A variable allowed in the configuration file or on the command line.

Definition at line 150 of file config.c.

Class Members
const char * initvalue String (or null) describing initial value.
const char * name The full keyword (case insensitive).
config_type_t type How to interpret the type and turn it into a value.
off_t var_offset Offset of the corresponding member of or_options_t.
struct config_var_description_t

Represents an English description of a configuration variable; used when generating configuration file comments.

Definition at line 550 of file config.c.

Class Members
const char * description
const char * name
struct config_format_t

Information on the keys, value types, key-to-struct-member mappings, variable descriptions, validation functions, and abbreviations for a configuration or storage format.

Definition at line 563 of file config.c.

Collaboration diagram for config_format_t:
Class Members
config_abbrev_t * abbrevs List of abbreviations that we expand when parsing this format.
config_var_t * extra If present, extra is a LINELIST variable for unrecognized lines. Otherwise, unrecognized lines are an error.
uint32_t magic Required 'magic value' to make sure we have a struct of the right type.
off_t magic_offset Offset of the magic value within the struct.
size_t size Size of the struct that everything gets parsed into.
validate_fn_t validate_fn Function to validate config.
config_var_t * vars List of variables we recognize, their default values, and where we stick them in the structure.
struct unit_table_t

Mapping from a unit name to a multiplier for converting that unit into a base unit.

Used by config_parse_unit.

Definition at line 6369 of file config.c.

Class Members
uint64_t multiplier How many of the base unit appear in this unit.
const char * unit The name of the unit.

Define Documentation

#define CHECK (   fmt,
  cfg 
)
Value:
STMT_BEGIN                                      \
    tor_assert(fmt && cfg);                                             \
    tor_assert((fmt)->magic ==                                          \
               *(uint32_t*)STRUCT_VAR_P(cfg,fmt->magic_offset));        \
  STMT_END

Macro: assert that cfg has the right magic field for format fmt.

Definition at line 580 of file config.c.

#define CL_PORT_ALLOW_EXTRA_LISTENADDR   (1u<<2)

Definition at line 5565 of file config.c.

#define CL_PORT_FORBID_NONLOCAL   (1u<<4)

Definition at line 5567 of file config.c.

#define CL_PORT_NO_OPTIONS   (1u<<0)

Definition at line 5563 of file config.c.

#define CL_PORT_SERVER_OPTIONS   (1u<<3)

Definition at line 5566 of file config.c.

#define CL_PORT_WARN_NONLOCAL   (1u<<1)

Definition at line 5564 of file config.c.

#define COMPLAIN (   arg)    STMT_BEGIN log(LOG_WARN, LD_CONFIG, arg); STMT_END
#define CONFIG_PRIVATE

Definition at line 12 of file config.c.

Value:
"# The old torrc file was renamed " \
  "to torrc.orig.1 or similar, and Tor will ignore it"

This string can change; it tries to give the reader an idea that editing this file by hand is not a good plan.

Definition at line 6277 of file config.c.

Value:
"# This file was generated by Tor; " \
  "if you edit it, comments will not be preserved"

This string must remain the same forevermore.

It is how we recognize that the torrc file doesn't need to be backed up.

Definition at line 6273 of file config.c.

Highest allowable value for RendPostPeriod.

Definition at line 3322 of file config.c.

#define MIN_CIRCUIT_STREAM_TIMEOUT   10

Lowest allowable value for CircuitStreamTimeout; if this is too low, Tor will generate too many circuits and potentially overload the network.

Definition at line 3330 of file config.c.

#define MIN_HEARTBEAT_PERIOD   (30*60)

Lowest allowable value for HeartbeatPeriod; if this is too low, we might expose more information than we're comfortable with.

Definition at line 3334 of file config.c.

#define MIN_MAX_CIRCUIT_DIRTINESS   10

Lowest allowable value for MaxCircuitDirtiness; if this is too low, Tor will generate too many circuits and potentially overload the network.

Definition at line 3326 of file config.c.

#define MIN_REND_POST_PERIOD   (10*60)

Lowest allowable value for RendPostPeriod; if this is too low, hidden services can overload the directory system.

Definition at line 3319 of file config.c.

#define OBSOLETE (   name)    { name, CONFIG_TYPE_OBSOLETE, 0, NULL }

An entry for config_vars: "The option <b>name</b> is obsolete.".

Definition at line 169 of file config.c.

#define OR_OPTIONS_MAGIC   9090909

Magic value for or_options_t.

Definition at line 648 of file config.c.

#define OR_STATE_MAGIC   0x57A73f57

Magic value for or_state_t.

Definition at line 662 of file config.c.

#define PLURAL (   tok)    { #tok, #tok "s", 0, 0 }

Definition at line 88 of file config.c.

Lowest recommended value for CircuitBuildTimeout; if it is set too low and LearnCircuitBuildTimeout is off, the failure rate for circuit construction may be very high.

In that case, if it is set below this threshold emit a warning.

Definition at line 3341 of file config.c.

#define REJECT (   arg)    STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
#define RELAY_BRIDGE_STATS_DELAY   (6 * 60 * 60)
#define STATE_RELAY_CHECKPOINT_INTERVAL   (12*60*60)

If we're a relay, how often should we checkpoint our state file even if nothing else dirties it? This will checkpoint ongoing stats like bandwidth used, per-country user stats, etc.

Definition at line 6906 of file config.c.

#define STATE_WRITE_RETRY_INTERVAL   3600

If writing the state to disk fails, try again after this many seconds.

Definition at line 6901 of file config.c.

#define V (   member,
  conftype,
  initvalue 
)    VAR(#member, conftype, member, initvalue)

As VAR, but the option name and member name are the same.

Definition at line 166 of file config.c.

#define VAR (   name,
  conftype,
  member,
  initvalue 
)
Value:
{ name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_options_t, member), \
      initvalue }

An entry for config_vars: "The option name has type CONFIG_TYPE_conftype, and corresponds to or_options_t.

member"

Definition at line 488 of file config.c.

#define VAR (   name,
  conftype,
  member,
  initvalue 
)
Value:
{ name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_state_t, member),  \
      initvalue }

An entry for config_vars: "The option name has type CONFIG_TYPE_conftype, and corresponds to or_options_t.

member"

Definition at line 488 of file config.c.

#define VERY_OLD_FILE_AGE   (28*24*60*60)

Typedef Documentation

An abbreviation for a configuration option allowed on the command line.

Enumeration of types which option values can take.

Represents an English description of a configuration variable; used when generating configuration file comments.

typedef struct config_var_t config_var_t

A variable allowed in the configuration file or on the command line.

typedef int(* validate_fn_t)(void *, void *, int, char **)

Type of a callback to validate whether a given configuration is well-formed and consistent.

See options_trial_assign() for documentation of arguments.

Definition at line 558 of file config.c.


Enumeration Type Documentation

Enumeration of types which option values can take.

Enumerator:
CONFIG_TYPE_STRING 

An arbitrary string.

CONFIG_TYPE_FILENAME 

A filename: some prefixes get expanded.

CONFIG_TYPE_UINT 

A non-negative integer less than MAX_INT.

CONFIG_TYPE_INT 

Any integer.

CONFIG_TYPE_PORT 

A port from 1...65535, 0 for "not set", or "auto".

CONFIG_TYPE_INTERVAL 

A number of seconds, with optional units.

CONFIG_TYPE_MSEC_INTERVAL 

A number of milliseconds, with optional units.

CONFIG_TYPE_MEMUNIT 

A number of bytes, with optional units.

CONFIG_TYPE_DOUBLE 

A floating-point value.

CONFIG_TYPE_BOOL 

A boolean value, expressed as 0 or 1.

CONFIG_TYPE_AUTOBOOL 

A boolean+auto value, expressed 0 for false, 1 for true, and -1 for auto.

CONFIG_TYPE_ISOTIME 

An ISO-formatted time relative to GMT.

CONFIG_TYPE_CSV 

A list of strings, separated by commas and optional whitespace.

CONFIG_TYPE_LINELIST 

Uninterpreted config lines.

CONFIG_TYPE_LINELIST_S 

Uninterpreted, context-sensitive config lines, mixed with other keywords.

CONFIG_TYPE_LINELIST_V 

Catch-all "virtual" option to summarize context-sensitive config lines when fetching.

CONFIG_TYPE_ROUTERSET 

A list of router names, addrs, and fps, parsed into a routerset_t.

CONFIG_TYPE_OBSOLETE 

Obsolete (ignored) option.

Definition at line 49 of file config.c.


Function Documentation

static void add_default_trusted_dir_authorities ( dirinfo_type_t  type) [static]

Add the default directory authorities directly into the trusted dir list, but only add them insofar as they share bits with type.

Definition at line 939 of file config.c.

{
  int i;
  const char *dirservers[] = {
    "moria1 orport=9101 no-v2 "
      "v3ident=D586D18309DED4CD6D57C18FDB97EFA96D330566 "
      "128.31.0.39:9131 9695 DFC3 5FFE B861 329B 9F1A B04C 4639 7020 CE31",
    "tor26 v1 orport=443 v3ident=14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4 "
      "86.59.21.38:80 847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D",
    "dizum orport=443 v3ident=E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58 "
      "194.109.206.212:80 7EA6 EAD6 FD83 083C 538F 4403 8BBF A077 587D D755",
    "Tonga orport=443 bridge no-v2 82.94.251.203:80 "
      "4A0C CD2D DC79 9508 3D73 F5D6 6710 0C8A 5831 F16D",
    "turtles orport=9090 no-v2 "
      "v3ident=27B6B5996C426270A5C95488AA5BCEB6BCC86956 "
      "76.73.17.194:9030 F397 038A DC51 3361 35E7 B80B D99C A384 4360 292B",
    "gabelmoo orport=443 no-v2 "
      "v3ident=ED03BB616EB2F60BEC80151114BB25CEF515B226 "
      "212.112.245.170:80 F204 4413 DAC2 E02E 3D6B CF47 35A1 9BCA 1DE9 7281",
    "dannenberg orport=443 no-v2 "
      "v3ident=585769C78764D58426B8B52B6651A5A71137189A "
      "193.23.244.244:80 7BE6 83E6 5D48 1413 21C5 ED92 F075 C553 64AC 7123",
    "urras orport=80 no-v2 v3ident=80550987E1D626E3EBA5E5E75A458DE0626D088C "
      "208.83.223.34:443 0AD3 FA88 4D18 F89E EA2D 89C0 1937 9E0E 7FD9 4417",
    "maatuska orport=80 no-v2 "
      "v3ident=49015F787433103580E3B66A1707A00E60F2D15B "
      "171.25.193.9:443 BD6A 8292 55CB 08E6 6FBE 7D37 4836 3586 E46B 3810",
    NULL
  };
  for (i=0; dirservers[i]; i++) {
    if (parse_dir_server_line(dirservers[i], type, 0)<0) {
      log_err(LD_BUG, "Couldn't parse internal dirserver line %s",
              dirservers[i]);
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int check_nickname_list ( const char *  lst,
const char *  name,
char **  msg 
) [static]

Verify whether lst is a string containing valid-looking comma-separated nicknames, or NULL.

Return 0 on success. Warn and return -1 on failure.

Definition at line 4423 of file config.c.

{
  int r = 0;
  smartlist_t *sl;

  if (!lst)
    return 0;
  sl = smartlist_new();

  smartlist_split_string(sl, lst, ",",
    SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0);

  SMARTLIST_FOREACH(sl, const char *, s,
    {
      if (!is_legal_nickname_or_hexdigest(s)) {
        tor_asprintf(msg, "Invalid nickname '%s' in %s line", s, name);
        r = -1;
        break;
      }
    });
  SMARTLIST_FOREACH(sl, char *, s, tor_free(s));
  smartlist_free(sl);
  return r;
}

Here is the call graph for this function:

static int check_server_ports ( const smartlist_t ports,
const or_options_t options 
) [static]

Given a list of port_cfg_t in ports, check them for internal consistency and warn as appropriate.

Definition at line 6054 of file config.c.

{
  int n_orport_advertised = 0;
  int n_orport_advertised_ipv4 = 0;
  int n_orport_listeners = 0;
  int n_dirport_advertised = 0;
  int n_dirport_listeners = 0;
  int n_low_port = 0;
  int r = 0;

  SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) {
    if (port->type == CONN_TYPE_DIR_LISTENER) {
      if (! port->no_advertise)
        ++n_dirport_advertised;
      if (! port->no_listen)
        ++n_dirport_listeners;
    } else if (port->type == CONN_TYPE_OR_LISTENER) {
      if (! port->no_advertise) {
        ++n_orport_advertised;
        if (tor_addr_family(&port->addr) == AF_INET ||
            (tor_addr_family(&port->addr) == AF_UNSPEC && !port->ipv6_only))
          ++n_orport_advertised_ipv4;
      }
      if (! port->no_listen)
        ++n_orport_listeners;
    } else {
      continue;
    }
#ifndef _WIN32
    if (!port->no_advertise && port->port < 1024)
      ++n_low_port;
#endif
  } SMARTLIST_FOREACH_END(port);

  if (n_orport_advertised && !n_orport_listeners) {
    log_warn(LD_CONFIG, "We are advertising an ORPort, but not actually "
             "listening on one.");
    r = -1;
  }
  if (n_dirport_advertised && !n_dirport_listeners) {
    log_warn(LD_CONFIG, "We are advertising a DirPort, but not actually "
             "listening on one.");
    r = -1;
  }
  if (n_dirport_advertised > 1) {
    log_warn(LD_CONFIG, "Can't advertise more than one DirPort.");
    r = -1;
  }
  if (n_orport_advertised && !n_orport_advertised_ipv4 &&
      !options->BridgeRelay) {
    log_warn(LD_CONFIG, "Configured non-bridge only to listen on an IPv6 "
             "address.");
    r = -1;
  }

  if (n_low_port && options->AccountingMax) {
    log(LOG_WARN, LD_CONFIG,
          "You have set AccountingMax to use hibernation. You have also "
          "chosen a low DirPort or OrPort. This combination can make Tor stop "
          "working when it tries to re-attach the port after a period of "
          "hibernation. Please choose a different port or turn off "
          "hibernation unless you know this combination will work on your "
          "platform.");
  }

  return r;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int compute_publishserverdescriptor ( or_options_t options) [static]

Parse an authority type from options->PublishServerDescriptor and write it to options->_PublishServerDescriptor.

Treat "1" as "v2,v3" unless BridgeRelay is 1, in which case treat it as "bridge". Treat "0" as "". Return 0 on success or -1 if not a recognized authority type (in which case the value of _PublishServerDescriptor is undefined).

Definition at line 3284 of file config.c.

{
  smartlist_t *list = options->PublishServerDescriptor;
  dirinfo_type_t *auth = &options->_PublishServerDescriptor;
  *auth = NO_DIRINFO;
  if (!list) /* empty list, answer is none */
    return 0;
  SMARTLIST_FOREACH(list, const char *, string, {
    if (!strcasecmp(string, "v1"))
      *auth |= V1_DIRINFO;
    else if (!strcmp(string, "1"))
      if (options->BridgeRelay)
        *auth |= BRIDGE_DIRINFO;
      else
        *auth |= V2_DIRINFO | V3_DIRINFO;
    else if (!strcasecmp(string, "v2"))
      *auth |= V2_DIRINFO;
    else if (!strcasecmp(string, "v3"))
      *auth |= V3_DIRINFO;
    else if (!strcasecmp(string, "bridge"))
      *auth |= BRIDGE_DIRINFO;
    else if (!strcasecmp(string, "hidserv"))
      log_warn(LD_CONFIG,
               "PublishServerDescriptor hidserv is invalid. See "
               "PublishHidServDescriptors.");
    else if (!strcasecmp(string, "") || !strcmp(string, "0"))
      /* no authority */;
    else
      return -1;
    });
  return 0;
}
static void* config_alloc ( const config_format_t fmt) [static]

Allocate an empty configuration object of a given format type.

Definition at line 712 of file config.c.

{
  void *opts = tor_malloc_zero(fmt->size);
  *(uint32_t*)STRUCT_VAR_P(opts, fmt->magic_offset) = fmt->magic;
  CHECK(fmt, opts);
  return opts;
}

Here is the caller graph for this function:

static int config_assign ( const config_format_t fmt,
void *  options,
config_line_t list,
int  use_defaults,
int  clear_first,
char **  msg 
) [static]

Iterate through the linked list of requested options list.

For each item, convert as appropriate and assign to options. If an item is unrecognized, set *msg and return -1 immediately, else return 0 for success.

If clear_first, interpret config options as replacing (not extending) their previous values. If clear_first is set, then use_defaults to decide if you set to defaults after clearing, or make the value 0 or NULL.

Here are the use cases:

  1. A non-empty AllowInvalid line in your torrc. Appends to current if linelist, replaces current if csv.
  2. An empty AllowInvalid line in your torrc. Should clear it.
  3. "RESETCONF AllowInvalid" sets it to default.
  4. "SETCONF AllowInvalid" makes it NULL.
  5. "SETCONF AllowInvalid=foo" clears it and sets it to "foo".

Use_defaults Clear_first 0 0 "append" 1 0 undefined, don't use 0 1 "set to null first" 1 1 "set to defaults first" Return 0 on success, -1 on bad key, -2 on bad value.

As an additional special case, if a LINELIST config option has no value and clear_first is 0, then warn and ignore it.

Now we're done assigning a group of options to the configuration. Subsequent group assignments should replace linelists, not extend them.

Definition at line 2647 of file config.c.

{
  config_line_t *p;
  bitarray_t *options_seen;
  const int n_options = config_count_options(fmt);

  CHECK(fmt, options);

  /* pass 1: normalize keys */
  for (p = list; p; p = p->next) {
    const char *full = expand_abbrev(fmt, p->key, 0, 1);
    if (strcmp(full,p->key)) {
      tor_free(p->key);
      p->key = tor_strdup(full);
    }
  }

  /* pass 2: if we're reading from a resetting source, clear all
   * mentioned config options, and maybe set to their defaults. */
  if (clear_first) {
    for (p = list; p; p = p->next)
      config_reset_line(fmt, options, p->key, use_defaults);
  }

  options_seen = bitarray_init_zero(n_options);
  /* pass 3: assign. */
  while (list) {
    int r;
    if ((r=config_assign_line(fmt, options, list, use_defaults,
                              clear_first, options_seen, msg))) {
      bitarray_free(options_seen);
      return r;
    }
    list = list->next;
  }
  bitarray_free(options_seen);

  config_mark_lists_fragile(fmt, options);

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int config_assign_line ( const config_format_t fmt,
or_options_t options,
config_line_t c,
int  use_defaults,
int  clear_first,
bitarray_t options_seen,
char **  msg 
) [static]

If c is a syntactically valid configuration line, update options with its value and return 0.

Otherwise return -1 for bad key, -2 for bad value.

If clear_first is set, clear the value first. Then if use_defaults is set, set the value to the default.

Called from config_assign().

Definition at line 2306 of file config.c.

{
  const config_var_t *var;

  CHECK(fmt, options);

  var = config_find_option(fmt, c->key);
  if (!var) {
    if (fmt->extra) {
      void *lvalue = STRUCT_VAR_P(options, fmt->extra->var_offset);
      log_info(LD_CONFIG,
               "Found unrecognized option '%s'; saving it.", c->key);
      config_line_append((config_line_t**)lvalue, c->key, c->value);
      return 0;
    } else {
      tor_asprintf(msg,
                "Unknown option '%s'.  Failing.", c->key);
      return -1;
    }
  }

  /* Put keyword into canonical case. */
  if (strcmp(var->name, c->key)) {
    tor_free(c->key);
    c->key = tor_strdup(var->name);
  }

  if (!strlen(c->value)) {
    /* reset or clear it, then return */
    if (!clear_first) {
      if ((var->type == CONFIG_TYPE_LINELIST ||
           var->type == CONFIG_TYPE_LINELIST_S) &&
          c->command != CONFIG_LINE_CLEAR) {
        /* We got an empty linelist from the torrc or command line.
           As a special case, call this an error. Warn and ignore. */
        log_warn(LD_CONFIG,
                 "Linelist option '%s' has no value. Skipping.", c->key);
      } else { /* not already cleared */
        option_reset(fmt, options, var, use_defaults);
      }
    }
    return 0;
  } else if (c->command == CONFIG_LINE_CLEAR && !clear_first) {
    option_reset(fmt, options, var, use_defaults);
  }

  if (options_seen && (var->type != CONFIG_TYPE_LINELIST &&
                       var->type != CONFIG_TYPE_LINELIST_S)) {
    /* We're tracking which options we've seen, and this option is not
     * supposed to occur more than once. */
    int var_index = (int)(var - fmt->vars);
    if (bitarray_is_set(options_seen, var_index)) {
      log_warn(LD_CONFIG, "Option '%s' used more than once; all but the last "
               "value will be ignored.", var->name);
    }
    bitarray_set(options_seen, var_index);
  }

  if (config_assign_value(fmt, options, c, msg) < 0)
    return -2;
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int config_assign_value ( const config_format_t fmt,
or_options_t options,
config_line_t c,
char **  msg 
) [static]

c->key is known to be a real key.

Update options with c->value and return 0, or return -1 if bad value.

Called from config_assign_line() and option_reset().

Definition at line 2104 of file config.c.

{
  int i, ok;
  const config_var_t *var;
  void *lvalue;

  CHECK(fmt, options);

  var = config_find_option(fmt, c->key);
  tor_assert(var);

  lvalue = STRUCT_VAR_P(options, var->var_offset);

  switch (var->type) {

  case CONFIG_TYPE_PORT:
    if (!strcasecmp(c->value, "auto")) {
      *(int *)lvalue = CFG_AUTO_PORT;
      break;
    }
    /* fall through */
  case CONFIG_TYPE_INT:
  case CONFIG_TYPE_UINT:
    i = (int)tor_parse_long(c->value, 10,
                            var->type==CONFIG_TYPE_INT ? INT_MIN : 0,
                            var->type==CONFIG_TYPE_PORT ? 65535 : INT_MAX,
                            &ok, NULL);
    if (!ok) {
      tor_asprintf(msg,
          "Int keyword '%s %s' is malformed or out of bounds.",
          c->key, c->value);
      return -1;
    }
    *(int *)lvalue = i;
    break;

  case CONFIG_TYPE_INTERVAL: {
    i = config_parse_interval(c->value, &ok);
    if (!ok) {
      tor_asprintf(msg,
          "Interval '%s %s' is malformed or out of bounds.",
          c->key, c->value);
      return -1;
    }
    *(int *)lvalue = i;
    break;
  }

  case CONFIG_TYPE_MSEC_INTERVAL: {
    i = config_parse_msec_interval(c->value, &ok);
    if (!ok) {
      tor_asprintf(msg,
          "Msec interval '%s %s' is malformed or out of bounds.",
          c->key, c->value);
      return -1;
    }
    *(int *)lvalue = i;
    break;
  }

  case CONFIG_TYPE_MEMUNIT: {
    uint64_t u64 = config_parse_memunit(c->value, &ok);
    if (!ok) {
      tor_asprintf(msg,
          "Value '%s %s' is malformed or out of bounds.",
          c->key, c->value);
      return -1;
    }
    *(uint64_t *)lvalue = u64;
    break;
  }

  case CONFIG_TYPE_BOOL:
    i = (int)tor_parse_long(c->value, 10, 0, 1, &ok, NULL);
    if (!ok) {
      tor_asprintf(msg,
          "Boolean '%s %s' expects 0 or 1.",
          c->key, c->value);
      return -1;
    }
    *(int *)lvalue = i;
    break;

  case CONFIG_TYPE_AUTOBOOL:
    if (!strcmp(c->value, "auto"))
      *(int *)lvalue = -1;
    else if (!strcmp(c->value, "0"))
      *(int *)lvalue = 0;
    else if (!strcmp(c->value, "1"))
      *(int *)lvalue = 1;
    else {
      tor_asprintf(msg, "Boolean '%s %s' expects 0, 1, or 'auto'.",
                   c->key, c->value);
      return -1;
    }
    break;

  case CONFIG_TYPE_STRING:
  case CONFIG_TYPE_FILENAME:
    tor_free(*(char **)lvalue);
    *(char **)lvalue = tor_strdup(c->value);
    break;

  case CONFIG_TYPE_DOUBLE:
    *(double *)lvalue = atof(c->value);
    break;

  case CONFIG_TYPE_ISOTIME:
    if (parse_iso_time(c->value, (time_t *)lvalue)) {
      tor_asprintf(msg,
          "Invalid time '%s' for keyword '%s'", c->value, c->key);
      return -1;
    }
    break;

  case CONFIG_TYPE_ROUTERSET:
    if (*(routerset_t**)lvalue) {
      routerset_free(*(routerset_t**)lvalue);
    }
    *(routerset_t**)lvalue = routerset_new();
    if (routerset_parse(*(routerset_t**)lvalue, c->value, c->key)<0) {
      tor_asprintf(msg, "Invalid exit list '%s' for option '%s'",
                   c->value, c->key);
      return -1;
    }
    break;

  case CONFIG_TYPE_CSV:
    if (*(smartlist_t**)lvalue) {
      SMARTLIST_FOREACH(*(smartlist_t**)lvalue, char *, cp, tor_free(cp));
      smartlist_clear(*(smartlist_t**)lvalue);
    } else {
      *(smartlist_t**)lvalue = smartlist_new();
    }

    smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",",
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
    break;

  case CONFIG_TYPE_LINELIST:
  case CONFIG_TYPE_LINELIST_S:
    {
      config_line_t *lastval = *(config_line_t**)lvalue;
      if (lastval && lastval->fragile) {
        if (c->command != CONFIG_LINE_APPEND) {
          config_free_lines(lastval);
          *(config_line_t**)lvalue = NULL;
        } else {
          lastval->fragile = 0;
        }
      }

      config_line_append((config_line_t**)lvalue, c->key, c->value);
    }
    break;
  case CONFIG_TYPE_OBSOLETE:
    log_warn(LD_CONFIG, "Skipping obsolete configuration option '%s'", c->key);
    break;
  case CONFIG_TYPE_LINELIST_V:
    tor_asprintf(msg,
        "You may not provide a value for virtual option '%s'", c->key);
    return -1;
  default:
    tor_assert(0);
    break;
  }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int config_count_options ( const config_format_t fmt) [static]

Return the number of option entries in fmt.

Definition at line 2086 of file config.c.

{
  int i;
  for (i=0; fmt->vars[i].name; ++i)
    ;
  return i;
}

Here is the caller graph for this function:

static char* config_dump ( const config_format_t fmt,
const void *  default_options,
const void *  options,
int  minimal,
int  comment_defaults 
) [static]

Allocate and return a new string holding the written-out values of the vars in 'options'.

If 'minimal', do not write out any default-valued vars. Else, if comment_defaults, write default values as comments.

Definition at line 3156 of file config.c.

{
  smartlist_t *elements;
  const or_options_t *defaults = default_options;
  void *defaults_tmp = NULL;
  config_line_t *line, *assigned;
  char *result;
  int i;
  char *msg = NULL;

  if (defaults == NULL) {
    defaults = defaults_tmp = config_alloc(fmt);
    config_init(fmt, defaults_tmp);
  }

  /* XXX use a 1 here so we don't add a new log line while dumping */
  if (default_options == NULL) {
    if (fmt->validate_fn(NULL, defaults_tmp, 1, &msg) < 0) {
      log_err(LD_BUG, "Failed to validate default config.");
      tor_free(msg);
      tor_assert(0);
    }
  }

  elements = smartlist_new();
  for (i=0; fmt->vars[i].name; ++i) {
    int comment_option = 0;
    if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE ||
        fmt->vars[i].type == CONFIG_TYPE_LINELIST_S)
      continue;
    /* Don't save 'hidden' control variables. */
    if (!strcmpstart(fmt->vars[i].name, "__"))
      continue;
    if (minimal && option_is_same(fmt, options, defaults, fmt->vars[i].name))
      continue;
    else if (comment_defaults &&
             option_is_same(fmt, options, defaults, fmt->vars[i].name))
      comment_option = 1;

    line = assigned = get_assigned_option(fmt, options, fmt->vars[i].name, 1);

    for (; line; line = line->next) {
      smartlist_add_asprintf(elements, "%s%s %s\n",
                   comment_option ? "# " : "",
                   line->key, line->value);
    }
    config_free_lines(assigned);
  }

  if (fmt->extra) {
    line = *(config_line_t**)STRUCT_VAR_P(options, fmt->extra->var_offset);
    for (; line; line = line->next) {
      smartlist_add_asprintf(elements, "%s %s\n", line->key, line->value);
    }
  }

  result = smartlist_join_strings(elements, "", 0, NULL);
  SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
  smartlist_free(elements);
  if (defaults_tmp)
    config_free(fmt, defaults_tmp);
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static const config_var_t* config_find_option ( const config_format_t fmt,
const char *  key 
) [static]

If key is a configuration option, return the corresponding const config_var_t.

Otherwise, if key is a non-standard abbreviation, warn, and return the corresponding const config_var_t. Otherwise return NULL.

Definition at line 2079 of file config.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static config_var_t* config_find_option_mutable ( config_format_t fmt,
const char *  key 
) [static]

As config_find_option, but return a non-const pointer.

Definition at line 2048 of file config.c.

{
  int i;
  size_t keylen = strlen(key);
  if (!keylen)
    return NULL; /* if they say "--" on the command line, it's not an option */
  /* First, check for an exact (case-insensitive) match */
  for (i=0; fmt->vars[i].name; ++i) {
    if (!strcasecmp(key, fmt->vars[i].name)) {
      return &fmt->vars[i];
    }
  }
  /* If none, check for an abbreviated match */
  for (i=0; fmt->vars[i].name; ++i) {
    if (!strncasecmp(key, fmt->vars[i].name, keylen)) {
      log_warn(LD_CONFIG, "The abbreviation '%s' is deprecated. "
               "Please use '%s' instead",
               key, fmt->vars[i].name);
      return &fmt->vars[i];
    }
  }
  /* Okay, unrecognized option */
  return NULL;
}

Here is the caller graph for this function:

static void config_free ( const config_format_t fmt,
void *  options 
) [static]

Release storage held by options.

Definition at line 3034 of file config.c.

{
  int i;

  if (!options)
    return;

  tor_assert(fmt);

  for (i=0; fmt->vars[i].name; ++i)
    option_clear(fmt, options, &(fmt->vars[i]));
  if (fmt->extra) {
    config_line_t **linep = STRUCT_VAR_P(options, fmt->extra->var_offset);
    config_free_lines(*linep);
    *linep = NULL;
  }
  tor_free(options);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void config_free_all ( void  )

Release all memory and resources held by global configuration structures.

Definition at line 853 of file config.c.

Here is the call graph for this function:

Here is the caller graph for this function:

void config_free_lines ( config_line_t front)

Free all the configuration lines on the linked list front.

Definition at line 2032 of file config.c.

{
  config_line_t *tmp;

  while (front) {
    tmp = front;
    front = tmp->next;

    tor_free(tmp->key);
    tor_free(tmp->value);
    tor_free(tmp);
  }
}

Here is the caller graph for this function:

static int config_get_commandlines ( int  argc,
char **  argv,
config_line_t **  result 
) [static]

Helper: Read a list of configuration options from the command line.

If successful, put them in *result and return 0, and return -1 and leave *result alone.

Definition at line 1881 of file config.c.

{
  config_line_t *front = NULL;
  config_line_t **new = &front;
  char *s;
  int i = 1;

  while (i < argc) {
    unsigned command = CONFIG_LINE_NORMAL;
    int want_arg = 1;

    if (!strcmp(argv[i],"-f") ||
        !strcmp(argv[i],"--defaults-torrc") ||
        !strcmp(argv[i],"--hash-password")) {
      i += 2; /* command-line option with argument. ignore them. */
      continue;
    } else if (!strcmp(argv[i],"--list-fingerprint") ||
               !strcmp(argv[i],"--verify-config") ||
               !strcmp(argv[i],"--ignore-missing-torrc") ||
               !strcmp(argv[i],"--quiet") ||
               !strcmp(argv[i],"--hush")) {
      i += 1; /* command-line option. ignore it. */
      continue;
    } else if (!strcmp(argv[i],"--nt-service") ||
               !strcmp(argv[i],"-nt-service")) {
      i += 1;
      continue;
    }

    *new = tor_malloc_zero(sizeof(config_line_t));
    s = argv[i];

    /* Each keyword may be prefixed with one or two dashes. */
    if (*s == '-')
      s++;
    if (*s == '-')
      s++;
    /* Figure out the command, if any. */
    if (*s == '+') {
      s++;
      command = CONFIG_LINE_APPEND;
    } else if (*s == '/') {
      s++;
      command = CONFIG_LINE_CLEAR;
      /* A 'clear' command has no argument. */
      want_arg = 0;
    }

    if (want_arg && i == argc-1) {
      log_warn(LD_CONFIG,"Command-line option '%s' with no value. Failing.",
               argv[i]);
      config_free_lines(front);
      return -1;
    }

    (*new)->key = tor_strdup(expand_abbrev(&options_format, s, 1, 1));
    (*new)->value = want_arg ? tor_strdup(argv[i+1]) : tor_strdup("");
    (*new)->command = command;
    (*new)->next = NULL;
    log(LOG_DEBUG, LD_CONFIG, "command line: parsed keyword '%s', value '%s'",
        (*new)->key, (*new)->value);

    new = &((*new)->next);
    i += want_arg ? 2 : 1;
  }
  *result = front;
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int config_get_lines ( const char *  string,
config_line_t **  result,
int  extended 
)

Helper: parse the config string and strdup into key/value strings.

Set *result to the list, or NULL if parsing the string failed. Return 0 on success, -1 on failure. Warn and ignore any misformatted lines.

If extended is set, then treat keys beginning with / and with + as indicating "clear" and "append" respectively.

Definition at line 1977 of file config.c.

{
  config_line_t *list = NULL, **next;
  char *k, *v;

  next = &list;
  do {
    k = v = NULL;
    string = parse_config_line_from_str(string, &k, &v);
    if (!string) {
      config_free_lines(list);
      tor_free(k);
      tor_free(v);
      return -1;
    }
    if (k && v) {
      unsigned command = CONFIG_LINE_NORMAL;
      if (extended) {
        if (k[0] == '+') {
          char *k_new = tor_strdup(k+1);
          tor_free(k);
          k = k_new;
          command = CONFIG_LINE_APPEND;
        } else if (k[0] == '/') {
          char *k_new = tor_strdup(k+1);
          tor_free(k);
          k = k_new;
          tor_free(v);
          v = tor_strdup("");
          command = CONFIG_LINE_CLEAR;
        }
      }
      /* This list can get long, so we keep a pointer to the end of it
       * rather than using config_line_append over and over and getting
       * n^2 performance. */
      *next = tor_malloc_zero(sizeof(config_line_t));
      (*next)->key = k;
      (*next)->value = v;
      (*next)->next = NULL;
      (*next)->command = command;
      next = &((*next)->next);
    } else {
      tor_free(k);
      tor_free(v);
    }
  } while (*string);

  *result = list;
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void config_init ( const config_format_t fmt,
void *  options 
) [static]

Set all vars in the configuration object options to their default values.

Definition at line 3137 of file config.c.

{
  int i;
  const config_var_t *var;
  CHECK(fmt, options);

  for (i=0; fmt->vars[i].name; ++i) {
    var = &fmt->vars[i];
    if (!var->initvalue)
      continue; /* defaults to NULL or 0 */
    option_reset(fmt, options, var, 1);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void config_line_append ( config_line_t **  lst,
const char *  key,
const char *  val 
) [static]

Helper: allocate a new configuration option mapping 'key' to 'val', append it to *lst.

Definition at line 1953 of file config.c.

{
  config_line_t *newline;

  newline = tor_malloc_zero(sizeof(config_line_t));
  newline->key = tor_strdup(key);
  newline->value = tor_strdup(val);
  newline->next = NULL;
  while (*lst)
    lst = &((*lst)->next);

  (*lst) = newline;
}

Here is the caller graph for this function:

static config_line_t* config_lines_dup ( const config_line_t inp) [static]

Return a newly allocated deep copy of the lines in inp.

Definition at line 2441 of file config.c.

{
  config_line_t *result = NULL;
  config_line_t **next_out = &result;
  while (inp) {
    *next_out = tor_malloc_zero(sizeof(config_line_t));
    (*next_out)->key = tor_strdup(inp->key);
    (*next_out)->value = tor_strdup(inp->value);
    inp = inp->next;
    next_out = &((*next_out)->next);
  }
  (*next_out) = NULL;
  return result;
}

Here is the caller graph for this function:

static int config_lines_eq ( config_line_t a,
config_line_t b 
) [static]

Return true iff a and b contain identical keys and values in identical order.

Definition at line 3056 of file config.c.

{
  while (a && b) {
    if (strcasecmp(a->key, b->key) || strcmp(a->value, b->value))
      return 0;
    a = a->next;
    b = b->next;
  }
  if (a || b)
    return 0;
  return 1;
}

Here is the caller graph for this function:

static void config_mark_lists_fragile ( const config_format_t fmt,
or_options_t options 
) [static]

Mark every linelist in options "fragile", so that fresh assignments to it will replace old ones.

Definition at line 2277 of file config.c.

{
  int i;
  tor_assert(fmt);
  tor_assert(options);

  for (i = 0; fmt->vars[i].name; ++i) {
    const config_var_t *var = &fmt->vars[i];
    config_line_t *list;
    if (var->type != CONFIG_TYPE_LINELIST &&
        var->type != CONFIG_TYPE_LINELIST_V)
      continue;

    list = *(config_line_t **)STRUCT_VAR_P(options, var->var_offset);
    if (list)
      list->fragile = 1;
  }
}

Here is the caller graph for this function:

static int config_parse_interval ( const char *  s,
int *  ok 
) [static]

Parse a string in the format "number unit", where unit is a unit of time.

On success, set *ok to true and return the number of seconds in the provided interval. Otherwise, set *ok to 0 and return -1.

Definition at line 6527 of file config.c.

{
  uint64_t r;
  r = config_parse_units(s, time_units, ok);
  if (!ok)
    return -1;
  if (r > INT_MAX) {
    log_warn(LD_CONFIG, "Interval '%s' is too long", s);
    *ok = 0;
    return -1;
  }
  return (int)r;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static uint64_t config_parse_memunit ( const char *  s,
int *  ok 
) [static]

Parse a string in the format "number unit", where unit is a unit of information (byte, KB, M, etc).

On success, set *ok to true and return the number of bytes specified. Otherwise, set *ok to false and return 0.

Definition at line 6497 of file config.c.

{
  uint64_t u = config_parse_units(s, memory_units, ok);
  return u;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int config_parse_msec_interval ( const char *  s,
int *  ok 
) [static]

Parse a string in the format "number unit", where unit is a unit of time in milliseconds.

On success, set *ok to true and return the number of milliseconds in the provided interval. Otherwise, set *ok to 0 and return -1.

Definition at line 6508 of file config.c.

{
  uint64_t r;
  r = config_parse_units(s, time_msec_units, ok);
  if (!ok)
    return -1;
  if (r > INT_MAX) {
    log_warn(LD_CONFIG, "Msec interval '%s' is too long", s);
    *ok = 0;
    return -1;
  }
  return (int)r;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static uint64_t config_parse_units ( const char *  val,
struct unit_table_t u,
int *  ok 
) [static]

Parse a string val containing a number, zero or more spaces, and an optional unit string.

If the unit appears in the table u, then multiply the number by the unit multiplier. On success, set *ok to 1 and return this product. Otherwise, set *ok to 0.

Definition at line 6447 of file config.c.

{
  uint64_t v = 0;
  double d = 0;
  int use_float = 0;
  char *cp;

  tor_assert(ok);

  v = tor_parse_uint64(val, 10, 0, UINT64_MAX, ok, &cp);
  if (!*ok || (cp && *cp == '.')) {
    d = tor_parse_double(val, 0, UINT64_MAX, ok, &cp);
    if (!*ok)
      goto done;
    use_float = 1;
  }

  if (!cp) {
    *ok = 1;
    v = use_float ? DBL_TO_U64(d) :  v;
    goto done;
  }

  cp = (char*) eat_whitespace(cp);

  for ( ;u->unit;++u) {
    if (!strcasecmp(u->unit, cp)) {
      if (use_float)
        v = u->multiplier * d;
      else
        v *= u->multiplier;
      *ok = 1;
      goto done;
    }
  }
  log_warn(LD_CONFIG, "Unknown unit '%s'.", cp);
  *ok = 0;
 done:

  if (*ok)
    return v;
  else
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void config_register_addressmaps ( const or_options_t options)

Adjust the address map based on the MapAddress elements in the configuration options

Definition at line 4823 of file config.c.

{
  smartlist_t *elts;
  config_line_t *opt;
  char *from, *to;

  addressmap_clear_configured();
  elts = smartlist_new();
  for (opt = options->AddressMap; opt; opt = opt->next) {
    int from_wildcard = 0, to_wildcard = 0;
    smartlist_split_string(elts, opt->value, NULL,
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
    if (smartlist_len(elts) < 2) {
      log_warn(LD_CONFIG,"MapAddress '%s' has too few arguments. Ignoring.",
               opt->value);
      goto cleanup;
    }

    from = smartlist_get(elts,0);
    to = smartlist_get(elts,1);

    if (to[0] == '.' || from[0] == '.') {
      log_warn(LD_CONFIG,"MapAddress '%s' is ambiguous - address starts with a"
              "'.'. Ignoring.",opt->value);
      goto cleanup;
    }

    if (!strcmp(to, "*") || !strcmp(from, "*")) {
      log_warn(LD_CONFIG,"MapAddress '%s' is unsupported - can't remap from "
               "or to *. Ignoring.",opt->value);
      goto cleanup;
    }
    /* Detect asterisks in expressions of type: '*.example.com' */
    if (!strncmp(from,"*.",2)) {
      from += 2;
      from_wildcard = 1;
    }
    if (!strncmp(to,"*.",2)) {
      to += 2;
      to_wildcard = 1;
    }

    if (to_wildcard && !from_wildcard) {
      log_warn(LD_CONFIG,
                "Skipping invalid argument '%s' to MapAddress: "
                "can only use wildcard (i.e. '*.') if 'from' address "
                "uses wildcard also", opt->value);
      goto cleanup;
    }

    if (address_is_invalid_destination(to, 1)) {
      log_warn(LD_CONFIG,
                "Skipping invalid argument '%s' to MapAddress", opt->value);
      goto cleanup;
    }

    addressmap_register(from, tor_strdup(to), 0, ADDRMAPSRC_TORRC,
                        from_wildcard, to_wildcard);

    if (smartlist_len(elts) > 2)
      log_warn(LD_CONFIG,"Ignoring extra arguments to MapAddress.");

  cleanup:
    SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp));
    smartlist_clear(elts);
  }
  smartlist_free(elts);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void config_reset_line ( const config_format_t fmt,
or_options_t options,
const char *  key,
int  use_defaults 
) [static]

Restore the option named key in options to its default value.

Called from config_assign().

Definition at line 2374 of file config.c.

{
  const config_var_t *var;

  CHECK(fmt, options);

  var = config_find_option(fmt, key);
  if (!var)
    return; /* give error on next pass. */

  option_reset(fmt, options, var, use_defaults);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int config_value_needs_escape ( const char *  value) [static]

Return true iff value needs to be quoted and escaped to be used in a configuration file.

Definition at line 2416 of file config.c.

{
  if (*value == '\"')
    return 1;
  while (*value) {
    switch (*value)
    {
    case '\r':
    case '\n':
    case '#':
      /* Note: quotes and backspaces need special handling when we are using
       * quotes, not otherwise, so they don't trigger escaping on their
       * own. */
      return 1;
    default:
      if (!TOR_ISPRINT(*value))
        return 1;
    }
    ++value;
  }
  return 0;
}

Here is the caller graph for this function:

static int consider_adding_dir_authorities ( const or_options_t options,
const or_options_t old_options 
) [static]

Look at all the config options and assign new dir authorities as appropriate.

Definition at line 1032 of file config.c.

{
  config_line_t *cl;
  int need_to_update =
    !smartlist_len(router_get_trusted_dir_servers()) || !old_options ||
    !config_lines_eq(options->DirServers, old_options->DirServers) ||
    !config_lines_eq(options->AlternateBridgeAuthority,
                     old_options->AlternateBridgeAuthority) ||
    !config_lines_eq(options->AlternateDirAuthority,
                     old_options->AlternateDirAuthority) ||
    !config_lines_eq(options->AlternateHSAuthority,
                     old_options->AlternateHSAuthority);

  if (!need_to_update)
    return 0; /* all done */

  /* Start from a clean slate. */
  clear_trusted_dir_servers();

  if (!options->DirServers) {
    /* then we may want some of the defaults */
    dirinfo_type_t type = NO_DIRINFO;
    if (!options->AlternateBridgeAuthority)
      type |= BRIDGE_DIRINFO;
    if (!options->AlternateDirAuthority)
      type |= V1_DIRINFO | V2_DIRINFO | V3_DIRINFO | EXTRAINFO_DIRINFO |
        MICRODESC_DIRINFO;
    if (!options->AlternateHSAuthority)
      type |= HIDSERV_DIRINFO;
    add_default_trusted_dir_authorities(type);
  }

  for (cl = options->DirServers; cl; cl = cl->next)
    if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
      return -1;
  for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next)
    if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
      return -1;
  for (cl = options->AlternateDirAuthority; cl; cl = cl->next)
    if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
      return -1;
  for (cl = options->AlternateHSAuthority; cl; cl = cl->next)
    if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
      return -1;
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return whether the state file failed to write last time we tried.

Definition at line 6895 of file config.c.

Here is the caller graph for this function:

static int ensure_bandwidth_cap ( uint64_t *  value,
const char *  desc,
char **  msg 
) [static]

If value exceeds ROUTER_MAX_DECLARED_BANDWIDTH, write a complaint into *msg using string desc, and return -1.

Else return 0.

Definition at line 3261 of file config.c.

{
  if (*value > ROUTER_MAX_DECLARED_BANDWIDTH) {
    /* This handles an understandable special case where somebody says "2gb"
     * whereas our actual maximum is 2gb-1 (INT_MAX) */
    --*value;
  }
  if (*value > ROUTER_MAX_DECLARED_BANDWIDTH) {
    tor_asprintf(msg, "%s ("U64_FORMAT") must be at most %d",
                 desc, U64_PRINTF_ARG(*value),
                 ROUTER_MAX_DECLARED_BANDWIDTH);
    return -1;
  }
  return 0;
}

Here is the call graph for this function:

const char* escaped_safe_str ( const char *  address)

Equivalent to escaped(safe_str(address)).

See reentrancy note on escaped(): don't use this outside the main thread, or twice in the same log statement.

Definition at line 928 of file config.c.

{
  if (get_options()->_SafeLogging != SAFELOG_SCRUB_NONE)
    return "[scrubbed]";
  else
    return escaped(address);
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* escaped_safe_str_client ( const char *  address)

Equivalent to escaped(safe_str_client(address)).

See reentrancy note on escaped(): don't use this outside the main thread, or twice in the same log statement.

Definition at line 916 of file config.c.

{
  if (get_options()->_SafeLogging == SAFELOG_SCRUB_ALL)
    return "[scrubbed]";
  else
    return escaped(address);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static const char* expand_abbrev ( const config_format_t fmt,
const char *  option,
int  command_line,
int  warn_obsolete 
) [static]

If option is an official abbreviation for a longer option, return the longer option.

Otherwise return option. If command_line is set, apply all abbreviations. Otherwise, only apply abbreviations that work for the config file and the command line. If warn_obsolete is set, warn about deprecated names.

Definition at line 1851 of file config.c.

{
  int i;
  if (! fmt->abbrevs)
    return option;
  for (i=0; fmt->abbrevs[i].abbreviated; ++i) {
    /* Abbreviations are case insensitive. */
    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);
      }
      /* Keep going through the list in case we want to rewrite it more.
       * (We could imagine recursing here, but I don't want to get the
       * user into an infinite loop if we craft our list wrong.) */
      option = fmt->abbrevs[i].full;
    }
  }
  return option;
}

Here is the caller graph for this function:

static char* find_torrc_filename ( int  argc,
char **  argv,
int  defaults_file,
int *  using_default_fname,
int *  ignore_missing_torrc 
) [static]

Learn config file name from command line arguments, or use the default.

If defaults_file is true, we're looking for torrc-defaults; otherwise, we're looking for the regular torrc_file.

Set *using_default_fname to true if we're using the default configuration file name; or false if we've set it from the command line.

Set *ignore_missing_torrc to true if we should ignore the resulting filename if it doesn't exist.

Definition at line 4460 of file config.c.

{
  char *fname=NULL;
  int i;
  const char *fname_opt = defaults_file ? "--defaults-torrc" : "-f";
  const char *ignore_opt = defaults_file ? NULL : "--ignore-missing-torrc";

  if (defaults_file)
    *ignore_missing_torrc = 1;

  for (i = 1; i < argc; ++i) {
    if (i < argc-1 && !strcmp(argv[i],fname_opt)) {
      if (fname) {
        log(LOG_WARN, LD_CONFIG, "Duplicate %s options on command line.",
            fname_opt);
        tor_free(fname);
      }
      fname = expand_filename(argv[i+1]);

      {
        char *absfname;
        absfname = make_path_absolute(fname);
        tor_free(fname);
        fname = absfname;
      }

      *using_default_fname = 0;
      ++i;
    } else if (ignore_opt && !strcmp(argv[i],ignore_opt)) {
      *ignore_missing_torrc = 1;
    }
  }

  if (*using_default_fname) {
    /* didn't find one, try CONFDIR */
    const char *dflt = get_default_conf_file(defaults_file);
    if (dflt && file_status(dflt) == FN_FILE) {
      fname = tor_strdup(dflt);
    } else {
#ifndef _WIN32
      char *fn = NULL;
      if (!defaults_file)
        fn = expand_filename("~/.torrc");
      if (fn && file_status(fn) == FN_FILE) {
        fname = fn;
      } else {
        tor_free(fn);
        fname = tor_strdup(dflt);
      }
#else
      fname = tor_strdup(dflt);
#endif
    }
  }
  return fname;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static config_line_t * get_assigned_option ( const config_format_t fmt,
const void *  options,
const char *  key,
int  escape_val 
) [static]

Return newly allocated line or lines corresponding to key in the configuration options.

If escape_val is true and a value needs to be quoted before it's put in a config file, quote and escape that value. Return NULL if no such key exists.

Definition at line 2461 of file config.c.

{
  const config_var_t *var;
  const void *value;
  config_line_t *result;
  tor_assert(options && key);

  CHECK(fmt, options);

  var = config_find_option(fmt, key);
  if (!var) {
    log_warn(LD_CONFIG, "Unknown option '%s'.  Failing.", key);
    return NULL;
  }
  value = STRUCT_VAR_P(options, var->var_offset);

  result = tor_malloc_zero(sizeof(config_line_t));
  result->key = tor_strdup(var->name);
  switch (var->type)
    {
    case CONFIG_TYPE_STRING:
    case CONFIG_TYPE_FILENAME:
      if (*(char**)value) {
        result->value = tor_strdup(*(char**)value);
      } else {
        tor_free(result->key);
        tor_free(result);
        return NULL;
      }
      break;
    case CONFIG_TYPE_ISOTIME:
      if (*(time_t*)value) {
        result->value = tor_malloc(ISO_TIME_LEN+1);
        format_iso_time(result->value, *(time_t*)value);
      } else {
        tor_free(result->key);
        tor_free(result);
      }
      escape_val = 0; /* Can't need escape. */
      break;
    case CONFIG_TYPE_PORT:
      if (*(int*)value == CFG_AUTO_PORT) {
        result->value = tor_strdup("auto");
        escape_val = 0;
        break;
      }
      /* fall through */
    case CONFIG_TYPE_INTERVAL:
    case CONFIG_TYPE_MSEC_INTERVAL:
    case CONFIG_TYPE_UINT:
    case CONFIG_TYPE_INT:
      /* This means every or_options_t uint or bool element
       * needs to be an int. Not, say, a uint16_t or char. */
      tor_asprintf(&result->value, "%d", *(int*)value);
      escape_val = 0; /* Can't need escape. */
      break;
    case CONFIG_TYPE_MEMUNIT:
      tor_asprintf(&result->value, U64_FORMAT,
                   U64_PRINTF_ARG(*(uint64_t*)value));
      escape_val = 0; /* Can't need escape. */
      break;
    case CONFIG_TYPE_DOUBLE:
      tor_asprintf(&result->value, "%f", *(double*)value);
      escape_val = 0; /* Can't need escape. */
      break;

    case CONFIG_TYPE_AUTOBOOL:
      if (*(int*)value == -1) {
        result->value = tor_strdup("auto");
        escape_val = 0;
        break;
      }
      /* fall through */
    case CONFIG_TYPE_BOOL:
      result->value = tor_strdup(*(int*)value ? "1" : "0");
      escape_val = 0; /* Can't need escape. */
      break;
    case CONFIG_TYPE_ROUTERSET:
      result->value = routerset_to_string(*(routerset_t**)value);
      break;
    case CONFIG_TYPE_CSV:
      if (*(smartlist_t**)value)
        result->value =
          smartlist_join_strings(*(smartlist_t**)value, ",", 0, NULL);
      else
        result->value = tor_strdup("");
      break;
    case CONFIG_TYPE_OBSOLETE:
      log_fn(LOG_PROTOCOL_WARN, LD_CONFIG,
             "You asked me for the value of an obsolete config option '%s'.",
             key);
      tor_free(result->key);
      tor_free(result);
      return NULL;
    case CONFIG_TYPE_LINELIST_S:
      log_warn(LD_CONFIG,
               "Can't return context-sensitive '%s' on its own", key);
      tor_free(result->key);
      tor_free(result);
      return NULL;
    case CONFIG_TYPE_LINELIST:
    case CONFIG_TYPE_LINELIST_V:
      tor_free(result->key);
      tor_free(result);
      result = config_lines_dup(*(const config_line_t**)value);
      break;
    default:
      tor_free(result->key);
      tor_free(result);
      log_warn(LD_BUG,"Unknown type %d for known key '%s'",
               var->type, key);
      return NULL;
    }

  if (escape_val) {
    config_line_t *line;
    for (line = result; line; line = line->next) {
      if (line->value && config_value_needs_escape(line->value)) {
        char *newval = esc_for_log(line->value);
        tor_free(line->value);
        line->value = newval;
      }
    }
  }

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

const smartlist_t* get_configured_ports ( void  )

Return a list of port_cfg_t for client ports parsed from the options.

Definition at line 6126 of file config.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static const char* get_default_conf_file ( int  defaults_file) [static]

Return the default location for our torrc file (if defaults_file is false), or for the torrc-defaults file (if defaults_file is true).

Definition at line 4400 of file config.c.

{
#ifdef _WIN32
  if (defaults_file) {
    static char defaults_path[MAX_PATH+1];
    tor_snprintf(defaults_path, MAX_PATH, "%s\\torrc-defaults",
                 get_windows_conf_root());
    return defaults_path;
  } else {
    static char path[MAX_PATH+1];
    tor_snprintf(path, MAX_PATH, "%s\\torrc",
                 get_windows_conf_root());
    return path;
  }
#else
  return defaults_file ? CONFDIR "/torrc-defaults" : CONFDIR "/torrc";
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* get_dirportfrontpage ( void  )

Return the contents of our frontpage string, or NULL if not configured.

Definition at line 705 of file config.c.

Here is the caller graph for this function:

uint32_t get_effective_bwburst ( const or_options_t options)

Return the bandwidthburst that we are going to report to the authorities based on the config options.

Definition at line 1323 of file config.c.

{
  uint64_t bw = options->BandwidthBurst;
  if (options->RelayBandwidthBurst > 0 && bw > options->RelayBandwidthBurst)
    bw = options->RelayBandwidthBurst;
  /* ensure_bandwidth_cap() makes sure that this cast can't overflow. */
  return (uint32_t)bw;
}

Here is the caller graph for this function:

uint32_t get_effective_bwrate ( const or_options_t options)

Return the bandwidthrate that we are going to report to the authorities based on the config options.

Definition at line 1309 of file config.c.

{
  uint64_t bw = options->BandwidthRate;
  if (bw > options->MaxAdvertisedBandwidth)
    bw = options->MaxAdvertisedBandwidth;
  if (options->RelayBandwidthRate > 0 && bw > options->RelayBandwidthRate)
    bw = options->RelayBandwidthRate;
  /* ensure_bandwidth_cap() makes sure that this cast can't overflow. */
  return (uint32_t)bw;
}

Here is the caller graph for this function:

int get_first_advertised_port_by_type_af ( int  listener_type,
int  address_family 
)

Return the first advertised port of type listener_type in address_family.

Definition at line 6195 of file config.c.

{
  if (!configured_ports)
    return 0;
  SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) {
    if (cfg->type == listener_type &&
        !cfg->no_advertise &&
        (tor_addr_family(&cfg->addr) == address_family ||
         tor_addr_family(&cfg->addr) == AF_UNSPEC)) {
      if (tor_addr_family(&cfg->addr) != AF_UNSPEC ||
          (address_family == AF_INET && !cfg->ipv6_only) ||
          (address_family == AF_INET6 && !cfg->ipv4_only)) {
        return cfg->port;
      }
    }
  } SMARTLIST_FOREACH_END(cfg);
  return 0;
}

Here is the call graph for this function:

char* get_first_listener_addrport_string ( int  listener_type)

Return an address:port string representation of the address where the first listener_type listener waits for connections.

Return NULL if we couldn't find a listener. The string is allocated on the heap and it's the responsibility of the caller to free it after use.

This function is meant to be used by the pluggable transport proxy spawning code, please make sure that it fits your purposes before using it.

Definition at line 6143 of file config.c.

{
  static const char *ipv4_localhost = "127.0.0.1";
  static const char *ipv6_localhost = "[::1]";
  const char *address;
  uint16_t port;
  char *string = NULL;

  if (!configured_ports)
    return NULL;

  SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) {
    if (cfg->no_listen)
      continue;

    if (cfg->type == listener_type &&
        tor_addr_family(&cfg->addr) != AF_UNSPEC) {

      /* We found the first listener of the type we are interested in! */

      /* If a listener is listening on INADDR_ANY, assume that it's
         also listening on 127.0.0.1, and point the transport proxy
         there: */
      if (tor_addr_is_null(&cfg->addr))
        address = tor_addr_is_v4(&cfg->addr) ? ipv4_localhost : ipv6_localhost;
      else
        address = fmt_and_decorate_addr(&cfg->addr);

      /* If a listener is configured with port 'auto', we are forced
         to iterate all listener connections and find out in which
         port it ended up listening: */
      if (cfg->port == CFG_AUTO_PORT) {
        port = router_get_active_listener_port_by_type(listener_type);
        if (!port)
          return NULL;
      } else {
        port = cfg->port;
      }

      tor_asprintf(&string, "%s:%u", address, port);

      return string;
    }

  } SMARTLIST_FOREACH_END(cfg);

  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int get_num_cpus ( const or_options_t options)

Return the number of cpus configured in options.

If we are told to auto-detect the number of cpus, return the auto-detected number.

Definition at line 6544 of file config.c.

{
  if (options->NumCPUs == 0) {
    int n = compute_num_cpus();
    return (n >= 1) ? n : 1;
  } else {
    return options->NumCPUs;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

const or_options_t* get_options ( void  )

Returns the currently configured options.

Definition at line 730 of file config.c.

{
  return get_options_mutable();
}

Here is the call graph for this function:

Return the currently configured options.

Definition at line 722 of file config.c.

Here is the caller graph for this function:

or_state_t* get_or_state ( void  )

Return the persistent state struct for this Tor.

Definition at line 6596 of file config.c.

Here is the caller graph for this function:

const char* get_short_version ( void  )

Return the current Tor version, without any git tag.

Definition at line 819 of file config.c.

{

  if (the_short_tor_version == NULL) {
#ifdef TOR_BUILD_TAG
    tor_asprintf(&the_short_tor_version, "%s (%s)", VERSION, TOR_BUILD_TAG);
#else
    the_short_tor_version = tor_strdup(VERSION);
#endif
  }
  return the_short_tor_version;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* get_stored_bindaddr_for_server_transport ( const char *  transport)

Return a string containing the address:port that a proxy transport should bind on.

The string is stored on the heap and must be freed by the caller of this function.

If we didn't find references for this pluggable transport in the state file, we should instruct the pluggable transport proxy to listen on INADDR_ANY on a random ephemeral port.

Definition at line 7035 of file config.c.

{
  char *default_addrport = NULL;
  const char *stored_bindaddr = NULL;

  config_line_t *line = get_transport_in_state_by_name(transport);
  if (!line) /* Found no references in state for this transport. */
    goto no_bindaddr_found;

  stored_bindaddr = get_transport_bindaddr(line->value, transport);
  if (stored_bindaddr) /* found stored bindaddr in state file. */
    return tor_strdup(stored_bindaddr);

 no_bindaddr_found:
  tor_asprintf(&default_addrport, "%s:%s", fmt_addr32(INADDR_ANY), "0");
  return default_addrport;
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* get_torrc_fname ( int  defaults_fname)

Return the location for our configuration file.

Definition at line 4809 of file config.c.

{
  const char *fname = defaults_fname ? torrc_defaults_fname : torrc_fname;

  if (fname)
    return fname;
  else
    return get_default_conf_file(defaults_fname);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static const char* get_transport_bindaddr ( const char *  line,
const char *  transport 
) [static]

Return string containing the address:port part of the TransportProxy line for transport transport.

If the line is corrupted, return NULL.

Definition at line 7009 of file config.c.

{
  char *line_tmp = NULL;

  if (strlen(line) < strlen(transport) + 2) {
    goto broken_state;
  } else {
    /* line should start with the name of the transport and a space.
       (for example, "obfs2 127.0.0.1:47245") */
    tor_asprintf(&line_tmp, "%s ", transport);
    if (strcmpstart(line, line_tmp))
      goto broken_state;

    tor_free(line_tmp);
    return (line+strlen(transport)+1);
  }

 broken_state:
  tor_free(line_tmp);
  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static config_line_t* get_transport_in_state_by_name ( const char *  transport) [static]

Return the config line for transport transport in the current state.

Return NULL if there is no config line for transport.

Definition at line 6971 of file config.c.

{
  or_state_t *or_state = get_or_state();
  config_line_t *line;
  config_line_t *ret = NULL;
  smartlist_t *items = NULL;

  for (line = or_state->TransportProxies ; line ; line = line->next) {
    tor_assert(!strcmp(line->key, "TransportProxy"));

    items = smartlist_new();
    smartlist_split_string(items, line->value, NULL,
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
    if (smartlist_len(items) != 2) /* broken state */
      goto done;

    if (!strcmp(smartlist_get(items, 0), transport)) {
      ret = line;
      goto done;
    }

    SMARTLIST_FOREACH(items, char*, s, tor_free(s));
    smartlist_free(items);
    items = NULL;
  }

 done:
  if (items) {
    SMARTLIST_FOREACH(items, char*, s, tor_free(s));
    smartlist_free(items);
  }
  return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* get_version ( void  )

Return the current Tor version.

Definition at line 804 of file config.c.

Here is the call graph for this function:

Here is the caller graph for this function:

int getinfo_helper_config ( control_connection_t conn,
const char *  question,
char **  answer,
const char **  errmsg 
)

Helper to implement GETINFO functions about configuration variables (not their values).

Given a "config/names" question, set *answer to a new string describing the supported configuration variables and their types.

Definition at line 7142 of file config.c.

{
  (void) conn;
  (void) errmsg;
  if (!strcmp(question, "config/names")) {
    smartlist_t *sl = smartlist_new();
    int i;
    for (i = 0; _option_vars[i].name; ++i) {
      const config_var_t *var = &_option_vars[i];
      const char *type;
      switch (var->type) {
        case CONFIG_TYPE_STRING: type = "String"; break;
        case CONFIG_TYPE_FILENAME: type = "Filename"; break;
        case CONFIG_TYPE_UINT: type = "Integer"; break;
        case CONFIG_TYPE_INT: type = "SignedInteger"; break;
        case CONFIG_TYPE_PORT: type = "Port"; break;
        case CONFIG_TYPE_INTERVAL: type = "TimeInterval"; break;
        case CONFIG_TYPE_MSEC_INTERVAL: type = "TimeMsecInterval"; break;
        case CONFIG_TYPE_MEMUNIT: type = "DataSize"; break;
        case CONFIG_TYPE_DOUBLE: type = "Float"; break;
        case CONFIG_TYPE_BOOL: type = "Boolean"; break;
        case CONFIG_TYPE_AUTOBOOL: type = "Boolean+Auto"; break;
        case CONFIG_TYPE_ISOTIME: type = "Time"; break;
        case CONFIG_TYPE_ROUTERSET: type = "RouterList"; break;
        case CONFIG_TYPE_CSV: type = "CommaList"; break;
        case CONFIG_TYPE_LINELIST: type = "LineList"; break;
        case CONFIG_TYPE_LINELIST_S: type = "Dependant"; break;
        case CONFIG_TYPE_LINELIST_V: type = "Virtual"; break;
        default:
        case CONFIG_TYPE_OBSOLETE:
          type = NULL; break;
      }
      if (!type)
        continue;
      smartlist_add_asprintf(sl, "%s %s\n",var->name,type);
    }
    *answer = smartlist_join_strings(sl, "", 0, NULL);
    SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
    smartlist_free(sl);
  }
  return 0;
}

Here is the call graph for this function:

static void init_libevent ( const or_options_t options) [static]

Initialize the libevent library.

Definition at line 6558 of file config.c.

{
  const char *badness=NULL;
  tor_libevent_cfg cfg;

  tor_assert(options);

  configure_libevent_logging();
  /* If the kernel complains that some method (say, epoll) doesn't
   * exist, we don't care about it, since libevent will cope.
   */
  suppress_libevent_log_msg("Function not implemented");

  tor_check_libevent_header_compatibility();

  memset(&cfg, 0, sizeof(cfg));
  cfg.disable_iocp = options->DisableIOCP;
  cfg.num_cpus = get_num_cpus(options);
  cfg.msec_per_tick = options->TokenBucketRefillInterval;

  tor_libevent_initialize(&cfg);

  suppress_libevent_log_msg(NULL);

  tor_check_libevent_version(tor_libevent_get_method(),
                             get_options()->ORPort != NULL,
                             &badness);
  if (badness) {
    const char *v = tor_libevent_get_version_str();
    const char *m = tor_libevent_get_method();
    control_event_general_status(LOG_WARN,
        "BAD_LIBEVENT VERSION=%s METHOD=%s BADNESS=%s RECOVERED=NO",
                                 v, m, badness);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int is_local_addr ( const tor_addr_t addr)

Return true iff addr is judged to be on the same network as us, or on a private network.

Definition at line 3007 of file config.c.

{
  if (tor_addr_is_internal(addr, 0))
    return 1;
  /* Check whether ip is on the same /24 as we are. */
  if (get_options()->EnforceDistinctSubnets == 0)
    return 0;
  if (tor_addr_family(addr) == AF_INET) {
    /*XXXX023 IP6 what corresponds to an /24? */
    uint32_t ip = tor_addr_to_ipv4h(addr);

    /* It's possible that this next check will hit before the first time
     * resolve_my_address actually succeeds.  (For clients, it is likely that
     * resolve_my_address will never be called at all).  In those cases,
     * last_resolved_addr will be 0, and so checking to see whether ip is on
     * the same /24 as last_resolved_addr will be the same as checking whether
     * it was on net 0, which is already done by is_internal_IP.
     */
    if ((last_resolved_addr & (uint32_t)0xffffff00ul)
        == (ip & (uint32_t)0xffffff00ul))
      return 1;
  }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void list_torrc_options ( void  ) [static]

Print all non-obsolete torrc options.

Definition at line 2833 of file config.c.

{
  int i;
  smartlist_t *lines = smartlist_new();
  for (i = 0; _option_vars[i].name; ++i) {
    const config_var_t *var = &_option_vars[i];
    if (var->type == CONFIG_TYPE_OBSOLETE ||
        var->type == CONFIG_TYPE_LINELIST_V)
      continue;
    printf("%s\n", var->name);
  }
  smartlist_free(lines);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* load_torrc_from_disk ( int  argc,
char **  argv,
int  defaults_file 
) [static]

Load a configuration file from disk, setting torrc_fname or torrc_defaults_fname if successful.

If defaults_file is true, load torrc-defaults; otherwise load torrc.

Return the contents of the file on success, and NULL on failure.

Definition at line 4527 of file config.c.

{
  char *fname=NULL;
  char *cf = NULL;
  int using_default_torrc = 1;
  int ignore_missing_torrc = 0;
  char **fname_var = defaults_file ? &torrc_defaults_fname : &torrc_fname;

  fname = find_torrc_filename(argc, argv, defaults_file,
                              &using_default_torrc, &ignore_missing_torrc);
  tor_assert(fname);
  log(LOG_DEBUG, LD_CONFIG, "Opening config file \"%s\"", fname);

  tor_free(*fname_var);
  *fname_var = fname;

  /* Open config file */
  if (file_status(fname) != FN_FILE ||
      !(cf = read_file_to_str(fname,0,NULL))) {
    if (using_default_torrc == 1 || ignore_missing_torrc) {
      if (!defaults_file)
        log(LOG_NOTICE, LD_CONFIG, "Configuration file \"%s\" not present, "
            "using reasonable defaults.", fname);
      tor_free(fname); /* sets fname to NULL */
      *fname_var = NULL;
      cf = tor_strdup("");
    } else {
      log(LOG_WARN, LD_CONFIG,
          "Unable to open configuration file \"%s\".", fname);
      goto err;
    }
  } else {
    log(LOG_NOTICE, LD_CONFIG, "Read configuration file \"%s\".", fname);
  }

  return cf;
 err:
  tor_free(fname);
  *fname_var = NULL;
  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int normalize_data_directory ( or_options_t options) [static]

Adjust the value of options->DataDirectory, or fill it in if it's absent.

Return 0 on success, -1 on failure.

Definition at line 6217 of file config.c.

{
#ifdef _WIN32
  char *p;
  if (options->DataDirectory)
    return 0; /* all set */
  p = tor_malloc(MAX_PATH);
  strlcpy(p,get_windows_conf_root(),MAX_PATH);
  options->DataDirectory = p;
  return 0;
#else
  const char *d = options->DataDirectory;
  if (!d)
    d = "~/.tor";

 if (strncmp(d,"~/",2) == 0) {
   char *fn = expand_filename(d);
   if (!fn) {
     log_warn(LD_CONFIG,"Failed to expand filename \"%s\".", d);
     return -1;
   }
   if (!options->DataDirectory && !strcmp(fn,"/.tor")) {
     /* If our homedir is /, we probably don't want to use it. */
     /* Default to LOCALSTATEDIR/tor which is probably closer to what we
      * want. */
     log_warn(LD_CONFIG,
              "Default DataDirectory is \"~/.tor\".  This expands to "
              "\"%s\", which is probably not what you want.  Using "
              "\"%s"PATH_SEPARATOR"tor\" instead", fn, LOCALSTATEDIR);
     tor_free(fn);
     fn = tor_strdup(LOCALSTATEDIR PATH_SEPARATOR "tor");
   }
   tor_free(options->DataDirectory);
   options->DataDirectory = fn;
 }
 return 0;
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int opt_streq ( const char *  s1,
const char *  s2 
) [static]

Helper: return true iff s1 and s2 are both NULL, or both non-NULL equal strings.

Definition at line 4201 of file config.c.

{
  return 0 == strcmp_opt(s1, s2);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void option_clear ( const config_format_t fmt,
or_options_t options,
const config_var_t var 
) [static]

Reset config option var to 0, 0.0, NULL, or the equivalent.

Called from option_reset() and config_free().

Definition at line 2737 of file config.c.

{
  void *lvalue = STRUCT_VAR_P(options, var->var_offset);
  (void)fmt; /* unused */
  switch (var->type) {
    case CONFIG_TYPE_STRING:
    case CONFIG_TYPE_FILENAME:
      tor_free(*(char**)lvalue);
      break;
    case CONFIG_TYPE_DOUBLE:
      *(double*)lvalue = 0.0;
      break;
    case CONFIG_TYPE_ISOTIME:
      *(time_t*)lvalue = 0;
      break;
    case CONFIG_TYPE_INTERVAL:
    case CONFIG_TYPE_MSEC_INTERVAL:
    case CONFIG_TYPE_UINT:
    case CONFIG_TYPE_INT:
    case CONFIG_TYPE_PORT:
    case CONFIG_TYPE_BOOL:
      *(int*)lvalue = 0;
      break;
    case CONFIG_TYPE_AUTOBOOL:
      *(int*)lvalue = -1;
      break;
    case CONFIG_TYPE_MEMUNIT:
      *(uint64_t*)lvalue = 0;
      break;
    case CONFIG_TYPE_ROUTERSET:
      if (*(routerset_t**)lvalue) {
        routerset_free(*(routerset_t**)lvalue);
        *(routerset_t**)lvalue = NULL;
      }
      break;
    case CONFIG_TYPE_CSV:
      if (*(smartlist_t**)lvalue) {
        SMARTLIST_FOREACH(*(smartlist_t **)lvalue, char *, cp, tor_free(cp));
        smartlist_free(*(smartlist_t **)lvalue);
        *(smartlist_t **)lvalue = NULL;
      }
      break;
    case CONFIG_TYPE_LINELIST:
    case CONFIG_TYPE_LINELIST_S:
      config_free_lines(*(config_line_t **)lvalue);
      *(config_line_t **)lvalue = NULL;
      break;
    case CONFIG_TYPE_LINELIST_V:
      /* handled by linelist_s. */
      break;
    case CONFIG_TYPE_OBSOLETE:
      break;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

config_line_t* option_get_assignment ( const or_options_t options,
const char *  key 
)

Return a canonical list of the options assigned for key.

Definition at line 2408 of file config.c.

{
  return get_assigned_option(&options_format, options, key, 1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* option_get_canonical_name ( const char *  key)

Return the canonical name of a configuration option, or NULL if no such option exists.

Definition at line 2399 of file config.c.

{
  const config_var_t *var = config_find_option(&options_format, key);
  return var ? var->name : NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int option_is_recognized ( const char *  key)

Return true iff key is a valid configuration option.

Definition at line 2390 of file config.c.

{
  const config_var_t *var = config_find_option(&options_format, key);
  return (var != NULL);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int option_is_same ( const config_format_t fmt,
const or_options_t o1,
const or_options_t o2,
const char *  name 
) [static]

Return true iff the option name has the same value in o1 and o2.

Must not be called for LINELIST_S or OBSOLETE options.

Definition at line 3073 of file config.c.

{
  config_line_t *c1, *c2;
  int r = 1;
  CHECK(fmt, o1);
  CHECK(fmt, o2);

  c1 = get_assigned_option(fmt, o1, name, 0);
  c2 = get_assigned_option(fmt, o2, name, 0);
  r = config_lines_eq(c1, c2);
  config_free_lines(c1);
  config_free_lines(c2);
  return r;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void option_reset ( const config_format_t fmt,
or_options_t options,
const config_var_t var,
int  use_defaults 
) [static]

Clear the option indexed by var in options.

Then if use_defaults, set it to its default value. Called by config_init() and option_reset_line() and option_assign_line().

Definition at line 2797 of file config.c.

{
  config_line_t *c;
  char *msg = NULL;
  CHECK(fmt, options);
  option_clear(fmt, options, var); /* clear it first */
  if (!use_defaults)
    return; /* all done */
  if (var->initvalue) {
    c = tor_malloc_zero(sizeof(config_line_t));
    c->key = tor_strdup(var->name);
    c->value = tor_strdup(var->initvalue);
    if (config_assign_value(fmt, options, c, &msg) < 0) {
      log_warn(LD_BUG, "Failed to assign default: %s", msg);
      tor_free(msg); /* if this happens it's a bug */
    }
    config_free_lines(c);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int options_act ( const or_options_t old_options) [static]

Fetch the active option list, and take actions based on it.

All of the things we do should survive being done repeatedly. If present, old_options 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.

Definition at line 1360 of file config.c.

{
  config_line_t *cl;
  or_options_t *options = get_options_mutable();
  int running_tor = options->command == CMD_RUN_TOR;
  char *msg;
  const int transition_affects_workers =
    old_options && options_transition_affects_workers(old_options, options);

  /* disable ptrace and later, other basic debugging techniques */
  {
    /* Remember if we already disabled debugger attachment */
    static int disabled_debugger_attach = 0;
    /* Remember if we already warned about being configured not to disable
     * debugger attachment */
    static int warned_debugger_attach = 0;
    /* Don't disable debugger attachment when we're running the unit tests. */
    if (options->DisableDebuggerAttachment && !disabled_debugger_attach &&
        running_tor) {
      int ok = tor_disable_debugger_attach();
      if (warned_debugger_attach && ok == 1) {
        log_notice(LD_CONFIG, "Disabled attaching debuggers for unprivileged "
                   "users.");
      }
      disabled_debugger_attach = (ok == 1);
    } else if (!options->DisableDebuggerAttachment &&
               !warned_debugger_attach) {
      log_notice(LD_CONFIG, "Not disabling debugger attaching for "
                 "unprivileged users.");
      warned_debugger_attach = 1;
    }
  }

  if (running_tor && !have_lockfile()) {
    if (try_locking(options, 1) < 0)
      return -1;
  }

  if (consider_adding_dir_authorities(options, old_options) < 0)
    return -1;

#ifdef NON_ANONYMOUS_MODE_ENABLED
  log(LOG_WARN, LD_GENERAL, "This copy of Tor was compiled to run in a "
      "non-anonymous mode. It will provide NO ANONYMITY.");
#endif

#ifdef ENABLE_TOR2WEB_MODE
  if (!options->Tor2webMode) {
    log_err(LD_CONFIG, "This copy of Tor was compiled to run in "
            "'tor2web mode'. It can only be run with the Tor2webMode torrc "
            "option enabled.");
    return -1;
  }
#else
  if (options->Tor2webMode) {
    log_err(LD_CONFIG, "This copy of Tor was not compiled to run in "
            "'tor2web mode'. It cannot be run with the Tor2webMode torrc "
            "option enabled. To enable Tor2webMode recompile with the "
            "--enable-tor2webmode option.");
    return -1;
  }
#endif

  if (options->Bridges) {
    mark_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;
      }
    }
    sweep_bridge_list();
  }

  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 && rend_parse_service_authorization(options, 0) < 0) {
    log_warn(LD_BUG, "Previously validated client authorization for "
                     "hidden services could not be added!");
    return -1;
  }

  /* Load state */
  if (! global_state && running_tor) {
    if (or_state_load())
      return -1;
    rep_hist_load_mtbf_data(time(NULL));
  }

  mark_transport_list();
  pt_prepare_proxy_list_for_config_read();
  if (options->ClientTransportPlugin) {
    for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
      if (parse_client_transport_line(cl->value, 0)<0) {
        log_warn(LD_BUG,
                 "Previously validated ClientTransportPlugin line "
                 "could not be added!");
        return -1;
      }
    }
  }

  if (options->ServerTransportPlugin) {
    for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
      if (parse_server_transport_line(cl->value, 0)<0) {
        log_warn(LD_BUG,
                 "Previously validated ServerTransportPlugin line "
                 "could not be added!");
        return -1;
      }
    }
  }
  sweep_transport_list();
  sweep_proxy_list();

  /* 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;

  /* Finish backgrounding the process */
  if (options->RunAsDaemon) {
    /* We may be calling this for the n'th time (on SIGHUP), but it's safe. */
    finish_daemon(options->DataDirectory);
  }

  /* If needed, generate a new TLS DH prime according to the current torrc. */
  if (server_mode(options) && options->DynamicDHGroups) {
    char *keydir = get_datadir_fname("keys");
    if (check_private_dir(keydir, CPD_CREATE, options->User)) {
      tor_free(keydir);
      return -1;
    }
    tor_free(keydir);

    if (!old_options || !old_options->DynamicDHGroups) {
      char *fname = get_datadir_fname2("keys", "dynamic_dh_params");
      crypto_set_tls_dh_prime(fname);
      tor_free(fname);
    }
  } else { /* clients don't need a dynamic DH prime. */
    crypto_set_tls_dh_prime(NULL);
  }

  /* We want to reinit keys as needed before we do much of anything else:
     keys are important, and other things can depend on them. */
  if (transition_affects_workers ||
      (options->V3AuthoritativeDir && (!old_options ||
                                       !old_options->V3AuthoritativeDir))) {
    if (init_keys() < 0) {
      log_warn(LD_BUG,"Error initializing keys; exiting");
      return -1;
    }
  } else if (old_options &&
             options_transition_requires_fresh_tls_context(old_options,
                                                           options)) {
    if (router_initialize_tls_context() < 0) {
      log_warn(LD_BUG,"Error initializing TLS context.");
      return -1;
    }
  }

  /* Write our PID to the PID file. If we do not have write permissions we
   * will log a warning */
  if (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;
  }

  monitor_owning_controller_process(options->OwningControllerProcess);

  /* 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));

#ifdef USE_BUFFEREVENTS
  /* If we're using the bufferevents implementation and our rate limits
   * changed, we need to tell the rate-limiting system about it. */
  if (!old_options ||
      old_options->BandwidthRate != options->BandwidthRate ||
      old_options->BandwidthBurst != options->BandwidthBurst ||
      old_options->RelayBandwidthRate != options->RelayBandwidthRate ||
      old_options->RelayBandwidthBurst != options->RelayBandwidthBurst)
    connection_bucket_init();
#endif

  /* Change the cell EWMA settings */
  cell_ewma_set_scale_factor(options, networkstatus_get_latest_consensus());

  /* Update the BridgePassword's hashed version as needed.  We store this as a
   * digest so that we can do side-channel-proof comparisons on it.
   */
  if (options->BridgePassword) {
    char *http_authenticator;
    http_authenticator = alloc_http_authenticator(options->BridgePassword);
    if (!http_authenticator) {
      log_warn(LD_BUG, "Unable to allocate HTTP authenticator. Not setting "
               "BridgePassword.");
      return -1;
    }
    options->_BridgePassword_AuthDigest = tor_malloc(DIGEST256_LEN);
    crypto_digest256(options->_BridgePassword_AuthDigest,
                     http_authenticator, strlen(http_authenticator),
                     DIGEST_SHA256);
    tor_free(http_authenticator);
  }

  /* Check for transitions that need action. */
  if (old_options) {
    int revise_trackexithosts = 0;
    int revise_automap_entries = 0;
    if ((options->UseEntryGuards && !old_options->UseEntryGuards) ||
        options->UseBridges != old_options->UseBridges ||
        (options->UseBridges &&
         !config_lines_eq(options->Bridges, old_options->Bridges)) ||
        !routerset_equal(old_options->ExcludeNodes,options->ExcludeNodes) ||
        !routerset_equal(old_options->ExcludeExitNodes,
                         options->ExcludeExitNodes) ||
        !routerset_equal(old_options->EntryNodes, options->EntryNodes) ||
        !routerset_equal(old_options->ExitNodes, options->ExitNodes) ||
        options->StrictNodes != old_options->StrictNodes) {
      log_info(LD_CIRC,
               "Changed to using entry guards or bridges, or changed "
               "preferred or excluded node lists. "
               "Abandoning previous circuits.");
      circuit_mark_all_unused_circs();
      circuit_expire_all_dirty_circs();
      revise_trackexithosts = 1;
    }

    if (!smartlist_strings_eq(old_options->TrackHostExits,
                              options->TrackHostExits))
      revise_trackexithosts = 1;

    if (revise_trackexithosts)
      addressmap_clear_excluded_trackexithosts(options);

    if (!options->AutomapHostsOnResolve) {
      if (old_options->AutomapHostsOnResolve)
        revise_automap_entries = 1;
    } else {
      if (!smartlist_strings_eq(old_options->AutomapHostsSuffixes,
                                options->AutomapHostsSuffixes))
        revise_automap_entries = 1;
      else if (!opt_streq(old_options->VirtualAddrNetwork,
                          options->VirtualAddrNetwork))
        revise_automap_entries = 1;
    }

    if (revise_automap_entries)
      addressmap_clear_invalid_automaps(options);

/* How long should we delay counting bridge stats after becoming a bridge?
 * We use this so we don't count people who used our bridge thinking it is
 * a relay. If you change this, don't forget to change the log message
 * below. It's 4 hours (the time it takes to stop being used by clients)
 * plus some extra time for clock skew. */
#define RELAY_BRIDGE_STATS_DELAY (6 * 60 * 60)

    if (! bool_eq(options->BridgeRelay, old_options->BridgeRelay)) {
      int was_relay = 0;
      if (options->BridgeRelay) {
        time_t int_start = time(NULL);
        if (config_lines_eq(old_options->ORPort, options->ORPort)) {
          int_start += RELAY_BRIDGE_STATS_DELAY;
          was_relay = 1;
        }
        geoip_bridge_stats_init(int_start);
        log_info(LD_CONFIG, "We are acting as a bridge now.  Starting new "
                 "GeoIP stats interval%s.", was_relay ? " in 6 "
                 "hours from now" : "");
      } else {
        geoip_bridge_stats_term();
        log_info(LD_GENERAL, "We are no longer acting as a bridge.  "
                 "Forgetting GeoIP stats.");
      }
    }

    if (transition_affects_workers) {
      log_info(LD_GENERAL,
               "Worker-related options changed. Rotating workers.");

      if (server_mode(options) && !server_mode(old_options)) {
        ip_address_changed(0);
        if (can_complete_circuit || !any_predicted_circuits(time(NULL)))
          inform_testing_reachability();
      }
      cpuworkers_rotate();
      if (dns_reset())
        return -1;
    } else {
      if (dns_reset())
        return -1;
    }

    if (options->PerConnBWRate != old_options->PerConnBWRate ||
        options->PerConnBWBurst != old_options->PerConnBWBurst)
      connection_or_update_token_buckets(get_connection_array(), options);
  }

  /* Maybe load geoip file */
  if (options->GeoIPFile &&
      ((!old_options || !opt_streq(old_options->GeoIPFile, options->GeoIPFile))
       || !geoip_is_loaded())) {
    /* XXXX Don't use this "<default>" junk; make our filename options
     * understand prefixes somehow. -NM */
    /* XXXX024 Reload GeoIPFile on SIGHUP. -NM */
    char *actual_fname = tor_strdup(options->GeoIPFile);
#ifdef _WIN32
    if (!strcmp(actual_fname, "<default>")) {
      const char *conf_root = get_windows_conf_root();
      tor_free(actual_fname);
      tor_asprintf(&actual_fname, "%s\\geoip", conf_root);
    }
#endif
    geoip_load_file(actual_fname, options);
    tor_free(actual_fname);
  }

  if (options->CellStatistics || options->DirReqStatistics ||
      options->EntryStatistics || options->ExitPortStatistics ||
      options->ConnDirectionStatistics ||
      options->BridgeAuthoritativeDir) {
    time_t now = time(NULL);
    int print_notice = 0;

    /* If we aren't acting as a server, we can't collect stats anyway. */
    if (!server_mode(options)) {
      options->CellStatistics = 0;
      options->DirReqStatistics = 0;
      options->EntryStatistics = 0;
      options->ExitPortStatistics = 0;
    }

    if ((!old_options || !old_options->CellStatistics) &&
        options->CellStatistics) {
      rep_hist_buffer_stats_init(now);
      print_notice = 1;
    }
    if ((!old_options || !old_options->DirReqStatistics) &&
        options->DirReqStatistics) {
      if (geoip_is_loaded()) {
        geoip_dirreq_stats_init(now);
        print_notice = 1;
      } else {
        options->DirReqStatistics = 0;
        /* Don't warn Tor clients, they don't use statistics */
        if (options->ORPort)
          log_notice(LD_CONFIG, "Configured to measure directory request "
                                "statistics, but no GeoIP database found. "
                                "Please specify a GeoIP database using the "
                                "GeoIPFile option.");
      }
    }
    if ((!old_options || !old_options->EntryStatistics) &&
        options->EntryStatistics && !should_record_bridge_info(options)) {
      if (geoip_is_loaded()) {
        geoip_entry_stats_init(now);
        print_notice = 1;
      } else {
        options->EntryStatistics = 0;
        log_notice(LD_CONFIG, "Configured to measure entry node "
                              "statistics, but no GeoIP database found. "
                              "Please specify a GeoIP database using the "
                              "GeoIPFile option.");
      }
    }
    if ((!old_options || !old_options->ExitPortStatistics) &&
        options->ExitPortStatistics) {
      rep_hist_exit_stats_init(now);
      print_notice = 1;
    }
    if ((!old_options || !old_options->ConnDirectionStatistics) &&
        options->ConnDirectionStatistics) {
      rep_hist_conn_stats_init(now);
    }
    if ((!old_options || !old_options->BridgeAuthoritativeDir) &&
        options->BridgeAuthoritativeDir) {
      rep_hist_desc_stats_init(now);
      print_notice = 1;
    }
    if (print_notice)
      log_notice(LD_CONFIG, "Configured to measure statistics. Look for "
                 "the *-stats files that will first be written to the "
                 "data directory in 24 hours from now.");
  }

  if (old_options && old_options->CellStatistics &&
      !options->CellStatistics)
    rep_hist_buffer_stats_term();
  if (old_options && old_options->DirReqStatistics &&
      !options->DirReqStatistics)
    geoip_dirreq_stats_term();
  if (old_options && old_options->EntryStatistics &&
      !options->EntryStatistics)
    geoip_entry_stats_term();
  if (old_options && old_options->ExitPortStatistics &&
      !options->ExitPortStatistics)
    rep_hist_exit_stats_term();
  if (old_options && old_options->ConnDirectionStatistics &&
      !options->ConnDirectionStatistics)
    rep_hist_conn_stats_term();
  if (old_options && old_options->BridgeAuthoritativeDir &&
      !options->BridgeAuthoritativeDir)
    rep_hist_desc_stats_term();

  /* Check if we need to parse and add the EntryNodes config option. */
  if (options->EntryNodes &&
      (!old_options ||
       !routerset_equal(old_options->EntryNodes,options->EntryNodes) ||
       !routerset_equal(old_options->ExcludeNodes,options->ExcludeNodes)))
    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("config change");

  /* 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));
    }
  }

  /* Load the webpage we're going to serve every time someone asks for '/' on
     our DirPort. */
  tor_free(global_dirfrontpagecontents);
  if (options->DirPortFrontPage) {
    global_dirfrontpagecontents =
      read_file_to_str(options->DirPortFrontPage, 0, NULL);
    if (!global_dirfrontpagecontents) {
      log_warn(LD_CONFIG,
               "DirPortFrontPage file '%s' not found. Continuing anyway.",
               options->DirPortFrontPage);
    }
  }

  return 0;
}

Here is the caller graph for this function:

static int options_act_reversible ( const or_options_t old_options,
char **  msg 
) [static]

Fetch the active option list, and take actions based on it.

All of the things we do should survive being done repeatedly. If present, old_options contains the previous value of the options.

Return 0 if all goes well, return -1 if things went badly.

Definition at line 1087 of file config.c.

{
  smartlist_t *new_listeners = smartlist_new();
  smartlist_t *replaced_listeners = smartlist_new();
  static int libevent_initialized = 0;
  or_options_t *options = get_options_mutable();
  int running_tor = options->command == CMD_RUN_TOR;
  int set_conn_limit = 0;
  int r = -1;
  int logs_marked = 0;

  /* Daemonize _first_, since we only want to open most of this stuff in
   * the subprocess.  Libevent bases can't be reliably inherited across
   * processes. */
  if (running_tor && options->RunAsDaemon) {
    /* No need to roll back, since you can't change the value. */
    start_daemon();
  }

#ifndef HAVE_SYS_UN_H
  if (options->ControlSocket || options->ControlSocketsGroupWritable) {
    *msg = tor_strdup("Unix domain sockets (ControlSocket) not supported "
                      "on this OS/with this build.");
    goto rollback;
  }
#else
  if (options->ControlSocketsGroupWritable && !options->ControlSocket) {
    *msg = tor_strdup("Setting ControlSocketGroupWritable without setting"
                      "a ControlSocket makes no sense.");
    goto rollback;
  }
#endif

  if (running_tor) {
    int n_ports=0;
    /* We need to set the connection limit before we can open the listeners. */
    if (set_max_file_descriptors((unsigned)options->ConnLimit,
                                 &options->_ConnLimit) < 0) {
      *msg = tor_strdup("Problem with ConnLimit value. See logs for details.");
      goto rollback;
    }
    set_conn_limit = 1;

    /* Set up libevent.  (We need to do this before we can register the
     * listeners as listeners.) */
    if (running_tor && !libevent_initialized) {
      init_libevent(options);
      libevent_initialized = 1;
    }

    /* Adjust the port configuration so we can launch listeners. */
    if (parse_ports(options, 0, msg, &n_ports)) {
      if (!*msg)
        *msg = tor_strdup("Unexpected problem parsing port config");
      goto rollback;
    }

    /* Set the hibernation state appropriately.*/
    consider_hibernation(time(NULL));

    /* Launch the listeners.  (We do this before we setuid, so we can bind to
     * ports under 1024.)  We don't want to rebind if we're hibernating. If
     * networking is disabled, this will close all but the control listeners,
     * but disable those. */
    if (!we_are_hibernating()) {
      if (retry_all_listeners(replaced_listeners, new_listeners,
                              options->DisableNetwork) < 0) {
        *msg = tor_strdup("Failed to bind one of the listener ports.");
        goto rollback;
      }
    }
    if (options->DisableNetwork) {
      /* Aggressively close non-controller stuff, NOW */
      log_notice(LD_NET, "DisableNetwork is set. Tor will not make or accept "
                 "non-control network connections. Shutting down all existing "
                 "connections.");
      connection_mark_all_noncontrol_connections();
    }
  }

#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
  /* Open /dev/pf before dropping privileges. */
  if (options->TransPort) {
    if (get_pf_socket() < 0) {
      *msg = tor_strdup("Unable to open /dev/pf for transparent proxy.");
      goto rollback;
    }
  }
#endif

  /* Attempt to lock all current and future memory with mlockall() only once */
  if (options->DisableAllSwap) {
    if (tor_mlockall() == -1) {
      *msg = tor_strdup("DisableAllSwap failure. Do you have proper "
                        "permissions?");
      goto done;
    }
  }

  /* Setuid/setgid as appropriate */
  if (options->User) {
    if (switch_id(options->User) != 0) {
      /* No need to roll back, since you can't change the value. */
      *msg = tor_strdup("Problem with User value. See logs for details.");
      goto done;
    }
  }

  /* Ensure data directory is private; create if possible. */
  if (check_private_dir(options->DataDirectory,
                        running_tor ? CPD_CREATE : CPD_CHECK,
                        options->User)<0) {
    tor_asprintf(msg,
              "Couldn't access/create private data directory \"%s\"",
              options->DataDirectory);
    goto done;
    /* No need to roll back, since you can't change the value. */
  }

  /* Write control ports to disk as appropriate */
  control_ports_write_to_file();

  if (directory_caches_v2_dir_info(options)) {
    char *fn = NULL;
    tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-status",
                 options->DataDirectory);
    if (check_private_dir(fn, running_tor ? CPD_CREATE : CPD_CHECK,
                          options->User) < 0) {
      tor_asprintf(msg,
                "Couldn't access/create private data directory \"%s\"", fn);
      tor_free(fn);
      goto done;
    }
    tor_free(fn);
  }

  /* 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 %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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* options_dump ( const or_options_t options,
int  minimal 
)

Return a string containing a possible configuration file that would give the configuration in options.

If minimal is true, do not include options that are the same as Tor's defaults.

Definition at line 3227 of file config.c.

{
  return config_dump(&options_format, global_default_options,
                     options, minimal, 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static or_options_t * options_dup ( const config_format_t fmt,
const or_options_t old 
) [static]

Copy storage held by old into a new or_options_t and return it.

Definition at line 3092 of file config.c.

{
  or_options_t *newopts;
  int i;
  config_line_t *line;

  newopts = config_alloc(fmt);
  for (i=0; fmt->vars[i].name; ++i) {
    if (fmt->vars[i].type == CONFIG_TYPE_LINELIST_S)
      continue;
    if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE)
      continue;
    line = get_assigned_option(fmt, old, fmt->vars[i].name, 0);
    if (line) {
      char *msg = NULL;
      if (config_assign(fmt, newopts, line, 0, 0, &msg) < 0) {
        log_err(LD_BUG, "Config_get_assigned_option() generated "
                "something we couldn't config_assign(): %s", msg);
        tor_free(msg);
        tor_assert(0);
      }
    }
    config_free_lines(line);
  }
  return newopts;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* options_get_datadir_fname2_suffix ( const or_options_t options,
const char *  sub1,
const char *  sub2,
const char *  suffix 
)

Return a newly allocated string holding a filename relative to the data directory.

If sub1 is present, it is the first path component after the data directory. If sub2 is also present, it is the second path component after the data directory. If suffix is present, it is appended to the filename.

Examples: get_datadir_fname2_suffix("a", NULL, NULL) -> $DATADIR/a get_datadir_fname2_suffix("a", NULL, ".tmp") -> $DATADIR/a.tmp get_datadir_fname2_suffix("a", "b", ".tmp") -> $DATADIR/a/b/.tmp get_datadir_fname2_suffix("a", "b", NULL) -> $DATADIR/a/b

Note: Consider using the get_datadir_fname* macros in or.h.

Definition at line 6617 of file config.c.

{
  char *fname = NULL;
  size_t len;
  tor_assert(options);
  tor_assert(options->DataDirectory);
  tor_assert(sub1 || !sub2); /* If sub2 is present, sub1 must be present. */
  len = strlen(options->DataDirectory);
  if (sub1) {
    len += strlen(sub1)+1;
    if (sub2)
      len += strlen(sub2)+1;
  }
  if (suffix)
    len += strlen(suffix);
  len++;
  fname = tor_malloc(len);
  if (sub1) {
    if (sub2) {
      tor_snprintf(fname, len, "%s"PATH_SEPARATOR"%s"PATH_SEPARATOR"%s",
                   options->DataDirectory, sub1, sub2);
    } else {
      tor_snprintf(fname, len, "%s"PATH_SEPARATOR"%s",
                   options->DataDirectory, sub1);
    }
  } else {
    strlcpy(fname, options->DataDirectory, len);
  }
  if (suffix)
    strlcat(fname, suffix, len);
  return fname;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void options_init ( or_options_t options)

Set options to hold reasonable defaults for most options.

Each option defaults to zero.

Definition at line 3129 of file config.c.

{
  config_init(&options_format, options);
}

Here is the call graph for this function:

Here is the caller graph for this function:

setopt_err_t options_init_from_string ( const char *  cf_defaults,
const char *  cf,
int  command,
const char *  command_arg,
char **  msg 
)

Load the options from the configuration in cf, validate them for consistency and take actions based on them.

Return 0 if success, negative on error:

  • -1 for general errors.
  • -2 for failure to parse/validate,
  • -3 for transition not allowed
  • -4 for error while setting the new options

Definition at line 4667 of file config.c.

{
  or_options_t *oldoptions, *newoptions, *newdefaultoptions=NULL;
  config_line_t *cl;
  int retval, i;
  setopt_err_t err = SETOPT_ERR_MISC;
  tor_assert(msg);

  oldoptions = global_options; /* get_options unfortunately asserts if
                                  this is the first time we run*/

  newoptions = tor_malloc_zero(sizeof(or_options_t));
  newoptions->_magic = OR_OPTIONS_MAGIC;
  options_init(newoptions);
  newoptions->command = command;
  newoptions->command_arg = command_arg;

  for (i = 0; i < 2; ++i) {
    const char *body = i==0 ? cf_defaults : cf;
    if (!body)
      continue;
    /* get config lines, assign them */
    retval = config_get_lines(body, &cl, 1);
    if (retval < 0) {
      err = SETOPT_ERR_PARSE;
      goto err;
    }
    retval = config_assign(&options_format, newoptions, cl, 0, 0, msg);
    config_free_lines(cl);
    if (retval < 0) {
      err = SETOPT_ERR_PARSE;
      goto err;
    }
    if (i==0)
      newdefaultoptions = options_dup(&options_format, newoptions);
  }

  /* Go through command-line variables too */
  retval = config_assign(&options_format, newoptions,
                         global_cmdline_options, 0, 0, msg);
  if (retval < 0) {
    err = SETOPT_ERR_PARSE;
    goto err;
  }

  /* If this is a testing network configuration, change defaults
   * for a list of dependent config options, re-initialize newoptions
   * with the new defaults, and assign all options to it second time. */
  if (newoptions->TestingTorNetwork) {
    /* XXXX this is a bit of a kludge.  perhaps there's a better way to do
     * this?  We could, for example, make the parsing algorithm do two passes
     * over the configuration.  If it finds any "suite" options like
     * TestingTorNetwork, it could change the defaults before its second pass.
     * Not urgent so long as this seems to work, but at any sign of trouble,
     * let's clean it up.  -NM */

    /* Change defaults. */
    int i;
    for (i = 0; testing_tor_network_defaults[i].name; ++i) {
      const config_var_t *new_var = &testing_tor_network_defaults[i];
      config_var_t *old_var =
          config_find_option_mutable(&options_format, new_var->name);
      tor_assert(new_var);
      tor_assert(old_var);
      old_var->initvalue = new_var->initvalue;
    }

    /* Clear newoptions and re-initialize them with new defaults. */
    config_free(&options_format, newoptions);
    config_free(&options_format, newdefaultoptions);
    newdefaultoptions = NULL;
    newoptions = tor_malloc_zero(sizeof(or_options_t));
    newoptions->_magic = OR_OPTIONS_MAGIC;
    options_init(newoptions);
    newoptions->command = command;
    newoptions->command_arg = command_arg;

    /* Assign all options a second time. */
    for (i = 0; i < 2; ++i) {
      const char *body = i==0 ? cf_defaults : cf;
      if (!body)
        continue;
      /* get config lines, assign them */
      retval = config_get_lines(body, &cl, 1);
      if (retval < 0) {
        err = SETOPT_ERR_PARSE;
        goto err;
      }
      retval = config_assign(&options_format, newoptions, cl, 0, 0, msg);
      config_free_lines(cl);
      if (retval < 0) {
        err = SETOPT_ERR_PARSE;
        goto err;
      }
      if (i==0)
        newdefaultoptions = options_dup(&options_format, newoptions);
    }
    /* Assign command-line variables a second time too */
    retval = config_assign(&options_format, newoptions,
                           global_cmdline_options, 0, 0, msg);
    if (retval < 0) {
      err = SETOPT_ERR_PARSE;
      goto err;
    }
  }

  /* Validate newoptions */
  if (options_validate(oldoptions, newoptions, 0, msg) < 0) {
    err = SETOPT_ERR_PARSE; /*XXX make this a separate return value.*/
    goto err;
  }

  if (options_transition_allowed(oldoptions, newoptions, msg) < 0) {
    err = SETOPT_ERR_TRANSITION;
    goto err;
  }

  if (set_options(newoptions, msg)) {
    err = SETOPT_ERR_SETTING;
    goto err; /* frees and replaces old options */
  }
  config_free(&options_format, global_default_options);
  global_default_options = newdefaultoptions;

  return SETOPT_OK;

 err:
  config_free(&options_format, newoptions);
  config_free(&options_format, newdefaultoptions);
  if (*msg) {
    char *old_msg = *msg;
    tor_asprintf(msg, "Failed to parse/validate config: %s", old_msg);
    tor_free(old_msg);
  }
  return err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int options_init_from_torrc ( int  argc,
char **  argv 
)

Read a configuration file into options, finding the configuration file location based on the command line.

After loading the file call options_init_from_string() to load the config. Return 0 if success, -1 if failure.

Definition at line 4574 of file config.c.

{
  char *cf=NULL, *cf_defaults=NULL;
  int i, command;
  int retval = -1;
  static char **backup_argv;
  static int backup_argc;
  char *command_arg = NULL;
  char *errmsg=NULL;

  if (argv) { /* first time we're called. save command line args */
    backup_argv = argv;
    backup_argc = argc;
  } else { /* we're reloading. need to clean up old options first. */
    argv = backup_argv;
    argc = backup_argc;
  }
  if (argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1],"--help"))) {
    print_usage();
    exit(0);
  }
  if (argc > 1 && !strcmp(argv[1], "--list-torrc-options")) {
    /* For documenting validating whether we've documented everything. */
    list_torrc_options();
    exit(0);
  }

  if (argc > 1 && (!strcmp(argv[1],"--version"))) {
    printf("Tor version %s.\n",get_version());
    exit(0);
  }
  if (argc > 1 && (!strcmp(argv[1],"--digests"))) {
    printf("Tor version %s.\n",get_version());
    printf("%s", libor_get_digests());
    printf("%s", tor_get_digests());
    exit(0);
  }

  /* Go through command-line variables */
  if (!global_cmdline_options) {
    /* Or we could redo the list every time we pass this place.
     * It does not really matter */
    if (config_get_commandlines(argc, argv, &global_cmdline_options) < 0) {
      goto err;
    }
  }

  command = CMD_RUN_TOR;
  for (i = 1; i < argc; ++i) {
    if (!strcmp(argv[i],"--list-fingerprint")) {
      command = CMD_LIST_FINGERPRINT;
    } else if (!strcmp(argv[i],"--hash-password")) {
      command = CMD_HASH_PASSWORD;
      command_arg = tor_strdup( (i < argc-1) ? argv[i+1] : "");
      ++i;
    } else if (!strcmp(argv[i],"--verify-config")) {
      command = CMD_VERIFY_CONFIG;
    }
  }

  if (command == CMD_HASH_PASSWORD) {
    cf = tor_strdup("");
  } else {
    cf_defaults = load_torrc_from_disk(argc, argv, 1);
    cf = load_torrc_from_disk(argc, argv, 0);
    if (!cf)
      goto err;
  }

  retval = options_init_from_string(cf_defaults, cf, command, command_arg,
                                    &errmsg);

 err:

  tor_free(cf);
  tor_free(cf_defaults);
  if (errmsg) {
    log(LOG_WARN,LD_CONFIG,"%s", errmsg);
    tor_free(errmsg);
  }
  return retval < 0 ? -1 : 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int options_init_logs ( or_options_t options,
int  validate_only 
) [static]

Initialize the logs based on the configuration file.

Definition at line 4896 of file config.c.

{
  config_line_t *opt;
  int ok;
  smartlist_t *elts;
  int daemon =
#ifdef _WIN32
               0;
#else
               options->RunAsDaemon;
#endif

  if (options->LogTimeGranularity <= 0) {
    log_warn(LD_CONFIG, "Log time granularity '%d' has to be positive.",
             options->LogTimeGranularity);
    return -1;
  } else if (1000 % options->LogTimeGranularity != 0 &&
             options->LogTimeGranularity % 1000 != 0) {
    int granularity = options->LogTimeGranularity;
    if (granularity < 40) {
      do granularity++;
      while (1000 % granularity != 0);
    } else if (granularity < 1000) {
      granularity = 1000 / granularity;
      while (1000 % granularity != 0)
        granularity--;
      granularity = 1000 / granularity;
    } else {
      granularity = 1000 * ((granularity / 1000) + 1);
    }
    log_warn(LD_CONFIG, "Log time granularity '%d' has to be either a "
                        "divisor or a multiple of 1 second. Changing to "
                        "'%d'.",
             options->LogTimeGranularity, granularity);
    if (!validate_only)
      set_log_time_granularity(granularity);
  } else {
    if (!validate_only)
      set_log_time_granularity(options->LogTimeGranularity);
  }

  ok = 1;
  elts = smartlist_new();

  for (opt = options->Logs; opt; opt = opt->next) {
    log_severity_list_t *severity;
    const char *cfg = opt->value;
    severity = tor_malloc_zero(sizeof(log_severity_list_t));
    if (parse_log_severity_config(&cfg, severity) < 0) {
      log_warn(LD_CONFIG, "Couldn't parse log levels in Log option 'Log %s'",
               opt->value);
      ok = 0; goto cleanup;
    }

    smartlist_split_string(elts, cfg, NULL,
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);

    if (smartlist_len(elts) == 0)
      smartlist_add(elts, tor_strdup("stdout"));

    if (smartlist_len(elts) == 1 &&
        (!strcasecmp(smartlist_get(elts,0), "stdout") ||
         !strcasecmp(smartlist_get(elts,0), "stderr"))) {
      int err = smartlist_len(elts) &&
        !strcasecmp(smartlist_get(elts,0), "stderr");
      if (!validate_only) {
        if (daemon) {
          log_warn(LD_CONFIG,
                   "Can't log to %s with RunAsDaemon set; skipping stdout",
                   err?"stderr":"stdout");
        } else {
          add_stream_log(severity, err?"<stderr>":"<stdout>",
                         fileno(err?stderr:stdout));
        }
      }
      goto cleanup;
    }
    if (smartlist_len(elts) == 1 &&
        !strcasecmp(smartlist_get(elts,0), "syslog")) {
#ifdef HAVE_SYSLOG_H
      if (!validate_only) {
        add_syslog_log(severity);
      }
#else
      log_warn(LD_CONFIG, "Syslog is not supported on this system. Sorry.");
#endif
      goto cleanup;
    }

    if (smartlist_len(elts) == 2 &&
        !strcasecmp(smartlist_get(elts,0), "file")) {
      if (!validate_only) {
        char *fname = expand_filename(smartlist_get(elts, 1));
        if (add_file_log(severity, fname) < 0) {
          log_warn(LD_CONFIG, "Couldn't open file for 'Log %s': %s",
                   opt->value, strerror(errno));
          ok = 0;
        }
        tor_free(fname);
      }
      goto cleanup;
    }

    log_warn(LD_CONFIG, "Bad syntax on file Log option 'Log %s'",
             opt->value);
    ok = 0; goto cleanup;

  cleanup:
    SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp));
    smartlist_clear(elts);
    tor_free(severity);
  }
  smartlist_free(elts);

  if (ok && !validate_only)
    logs_set_domain_logging(options->LogMessageDomains);

  return ok?0:-1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int options_need_geoip_info ( const or_options_t options,
const char **  reason_out 
)

If we need to have a GEOIP ip-to-country map to run with our configured options, return 1 and set *reason_out to a description of why.

Definition at line 1284 of file config.c.

{
  int bridge_usage =
    options->BridgeRelay && options->BridgeRecordUsageByCountry;
  int routerset_usage =
    routerset_needs_geoip(options->EntryNodes) ||
    routerset_needs_geoip(options->ExitNodes) ||
    routerset_needs_geoip(options->ExcludeExitNodes) ||
    routerset_needs_geoip(options->ExcludeNodes);

  if (routerset_usage && reason_out) {
    *reason_out = "We've been configured to use (or avoid) nodes in certain "
      "countries, and we need GEOIP information to figure out which ones they "
      "are.";
  } else if (bridge_usage && reason_out) {
    *reason_out = "We've been configured to see which countries can access "
      "us as a bridge, and we need GEOIP information to tell which countries "
      "clients are in.";
  }
  return bridge_usage || routerset_usage;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return a new empty or_options_t.

Used for testing.

Definition at line 3121 of file config.c.

Here is the call graph for this function:

Here is the caller graph for this function:

int options_save_current ( void  )

Save the current configuration file value to disk.

Return 0 on success, -1 on failure.

Definition at line 6357 of file config.c.

{
  /* This fails if we can't write to our configuration file.
   *
   * If we try falling back to datadirectory or something, we have a better
   * chance of saving the configuration, but a better chance of doing
   * something the user never expected. */
  return write_configuration_file(get_torrc_fname(0), get_options());
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int options_transition_affects_descriptor ( const or_options_t old_options,
const or_options_t new_options 
) [static]

Return 1 if any change from old_options to new_options will require us to generate a new descriptor; else return 0.

Definition at line 4308 of file config.c.

{
  /* XXX We can be smarter here. If your DirPort isn't being
   * published and you just turned it off, no need to republish. Etc. */
  if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) ||
      !opt_streq(old_options->Nickname,new_options->Nickname) ||
      !opt_streq(old_options->Address,new_options->Address) ||
      !config_lines_eq(old_options->ExitPolicy,new_options->ExitPolicy) ||
      old_options->ExitPolicyRejectPrivate !=
        new_options->ExitPolicyRejectPrivate ||
      !config_lines_eq(old_options->ORPort, new_options->ORPort) ||
      !config_lines_eq(old_options->DirPort, new_options->DirPort) ||
      old_options->ClientOnly != new_options->ClientOnly ||
      old_options->DisableNetwork != new_options->DisableNetwork ||
      old_options->_PublishServerDescriptor !=
        new_options->_PublishServerDescriptor ||
      get_effective_bwrate(old_options) != get_effective_bwrate(new_options) ||
      get_effective_bwburst(old_options) !=
        get_effective_bwburst(new_options) ||
      !opt_streq(old_options->ContactInfo, new_options->ContactInfo) ||
      !opt_streq(old_options->MyFamily, new_options->MyFamily) ||
      !opt_streq(old_options->AccountingStart, new_options->AccountingStart) ||
      old_options->AccountingMax != new_options->AccountingMax ||
      public_server_mode(old_options) != public_server_mode(new_options))
    return 1;

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int options_transition_affects_workers ( const or_options_t old_options,
const or_options_t new_options 
) [static]

Return 1 if any change from old_options to new_options will require us to rotate the CPU and DNS workers; else return 0.

Definition at line 4284 of file config.c.

{
  if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) ||
      old_options->NumCPUs != new_options->NumCPUs ||
      !config_lines_eq(old_options->ORPort, new_options->ORPort) ||
      old_options->ServerDNSSearchDomains !=
                                       new_options->ServerDNSSearchDomains ||
      old_options->_SafeLogging != new_options->_SafeLogging ||
      old_options->ClientOnly != new_options->ClientOnly ||
      public_server_mode(old_options) != public_server_mode(new_options) ||
      !config_lines_eq(old_options->Logs, new_options->Logs) ||
      old_options->LogMessageDomains != new_options->LogMessageDomains)
    return 1;

  /* Check whether log options match. */

  /* Nothing that changed matters. */
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int options_transition_allowed ( const or_options_t old,
const or_options_t new_val,
char **  msg 
) [static]

Check if any of the previous options have changed but aren't allowed to.

Definition at line 4208 of file config.c.

{
  if (!old)
    return 0;

  if (!opt_streq(old->PidFile, new_val->PidFile)) {
    *msg = tor_strdup("PidFile is not allowed to change.");
    return -1;
  }

  if (old->RunAsDaemon != new_val->RunAsDaemon) {
    *msg = tor_strdup("While Tor is running, changing RunAsDaemon "
                      "is not allowed.");
    return -1;
  }

  if (strcmp(old->DataDirectory,new_val->DataDirectory)!=0) {
    tor_asprintf(msg,
               "While Tor is running, changing DataDirectory "
               "(\"%s\"->\"%s\") is not allowed.",
               old->DataDirectory, new_val->DataDirectory);
    return -1;
  }

  if (!opt_streq(old->User, new_val->User)) {
    *msg = tor_strdup("While Tor is running, changing User is not allowed.");
    return -1;
  }

  if ((old->HardwareAccel != new_val->HardwareAccel)
      || !opt_streq(old->AccelName, new_val->AccelName)
      || !opt_streq(old->AccelDir, new_val->AccelDir)) {
    *msg = tor_strdup("While Tor is running, changing OpenSSL hardware "
                      "acceleration engine is not allowed.");
    return -1;
  }

  if (old->TestingTorNetwork != new_val->TestingTorNetwork) {
    *msg = tor_strdup("While Tor is running, changing TestingTorNetwork "
                      "is not allowed.");
    return -1;
  }

  if (old->DisableAllSwap != new_val->DisableAllSwap) {
    *msg = tor_strdup("While Tor is running, changing DisableAllSwap "
                      "is not allowed.");
    return -1;
  }

  if (old->TokenBucketRefillInterval != new_val->TokenBucketRefillInterval) {
    *msg = tor_strdup("While Tor is running, changing TokenBucketRefill"
                      "Interval is not allowed");
    return -1;
  }

  if (old->DisableIOCP != new_val->DisableIOCP) {
    *msg = tor_strdup("While Tor is running, changing DisableIOCP "
                      "is not allowed.");
    return -1;
  }

  if (old->DisableDebuggerAttachment &&
      !new_val->DisableDebuggerAttachment) {
    *msg = tor_strdup("While Tor is running, disabling "
                      "DisableDebuggerAttachment is not allowed.");
    return -1;
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int options_transition_requires_fresh_tls_context ( const or_options_t old_options,
const or_options_t new_options 
) [static]

Return True if any changes from old_options to new_options needs us to refresh our TLS context.

Definition at line 1335 of file config.c.

{
  tor_assert(new_options);

  if (!old_options)
    return 0;

  if ((old_options->DynamicDHGroups != new_options->DynamicDHGroups)) {
    return 1;
  }

  return 0;
}

Here is the caller graph for this function:

setopt_err_t options_trial_assign ( config_line_t list,
int  use_defaults,
int  clear_first,
char **  msg 
)

Try assigning list to the global options.

You do this by duping options, assigning list to the new one, then validating it. If it's ok, then throw out the old one and stick with the new one. Else, revert to old and return failure. Return SETOPT_OK on success, or a setopt_err_t on failure.

If not success, point *msg to a newly allocated string describing what went wrong.

Definition at line 2703 of file config.c.

{
  int r;
  or_options_t *trial_options = options_dup(&options_format, get_options());

  if ((r=config_assign(&options_format, trial_options,
                       list, use_defaults, clear_first, msg)) < 0) {
    config_free(&options_format, trial_options);
    return r;
  }

  if (options_validate(get_options_mutable(), trial_options, 1, msg) < 0) {
    config_free(&options_format, trial_options);
    return SETOPT_ERR_PARSE; /*XXX make this a separate return value. */
  }

  if (options_transition_allowed(get_options(), trial_options, msg) < 0) {
    config_free(&options_format, trial_options);
    return SETOPT_ERR_TRANSITION;
  }

  if (set_options(trial_options, msg)<0) {
    config_free(&options_format, trial_options);
    return SETOPT_ERR_SETTING;
  }

  /* we liked it. put it in place. */
  return SETOPT_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int options_validate ( or_options_t old_options,
or_options_t options,
int  from_setconf,
char **  msg 
) [static]

Return 0 if every setting in options is reasonable, and a permissible transition from old_options.

Else return -1. Should have no side effects, except for normalizing the contents of options.

On error, tor_strdup an error explanation into *msg.

XXX If from_setconf, we were called by the controller, and our Log line should stay empty. If it's 0, then give us a default log if there are no logs defined.

Definition at line 3356 of file config.c.

{
  int i;
  config_line_t *cl;
  const char *uname = get_uname();
  int n_ports=0;
#define REJECT(arg) \
  STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
#define COMPLAIN(arg) STMT_BEGIN log(LOG_WARN, LD_CONFIG, arg); STMT_END

  tor_assert(msg);
  *msg = NULL;

  if (server_mode(options) &&
      (!strcmpstart(uname, "Windows 95") ||
       !strcmpstart(uname, "Windows 98") ||
       !strcmpstart(uname, "Windows Me"))) {
    log(LOG_WARN, LD_CONFIG, "Tor is running as a server, but you are "
        "running %s; this probably won't work. See "
        "https://wiki.torproject.org/TheOnionRouter/TorFAQ#ServerOS "
        "for details.", uname);
  }

  if (parse_ports(options, 1, msg, &n_ports) < 0)
    return -1;

  if (validate_data_directory(options)<0)
    REJECT("Invalid DataDirectory");

  if (options->Nickname == NULL) {
    if (server_mode(options)) {
        options->Nickname = tor_strdup(UNNAMED_ROUTER_NICKNAME);
    }
  } else {
    if (!is_legal_nickname(options->Nickname)) {
      tor_asprintf(msg,
          "Nickname '%s' is wrong length or contains illegal characters.",
          options->Nickname);
      return -1;
    }
  }

  if (server_mode(options) && !options->ContactInfo)
    log(LOG_NOTICE, LD_CONFIG, "Your ContactInfo config option is not set. "
        "Please consider setting it, so we can contact you if your server is "
        "misconfigured or something else goes wrong.");

  /* Special case on first boot if no Log options are given. */
  if (!options->Logs && !options->RunAsDaemon && !from_setconf) {
    if (quiet_level == 0)
        config_line_append(&options->Logs, "Log", "notice stdout");
    else if (quiet_level == 1)
        config_line_append(&options->Logs, "Log", "warn stdout");
  }

  if (options_init_logs(options, 1)<0) /* Validate the log(s) */
    REJECT("Failed to validate Log options. See logs for details.");

  if (authdir_mode(options)) {
    /* confirm that our address isn't broken, so we can complain now */
    uint32_t tmp;
    if (resolve_my_address(LOG_WARN, options, &tmp, NULL) < 0)
      REJECT("Failed to resolve/guess local address. See logs for details.");
  }

#ifndef _WIN32
  if (options->RunAsDaemon && torrc_fname && path_is_relative(torrc_fname))
    REJECT("Can't use a relative path to torrc when RunAsDaemon is set.");
#endif

  /* XXXX require that the only port not be DirPort? */
  /* XXXX require that at least one port be listened-upon. */
  if (n_ports == 0 && !options->RendConfigLines)
    log(LOG_WARN, LD_CONFIG,
        "SocksPort, TransPort, NATDPort, DNSPort, and ORPort are all "
        "undefined, and there aren't any hidden services configured.  "
        "Tor will still run, but probably won't do anything.");

#ifndef USE_TRANSPARENT
  if (options->TransPort || options->TransListenAddress)
    REJECT("TransPort and TransListenAddress are disabled in this build.");
#endif

  if (options->TokenBucketRefillInterval <= 0
      || options->TokenBucketRefillInterval > 1000) {
    REJECT("TokenBucketRefillInterval must be between 1 and 1000 inclusive.");
  }

  if (options->ExcludeExitNodes || options->ExcludeNodes) {
    options->_ExcludeExitNodesUnion = routerset_new();
    routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeExitNodes);
    routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeNodes);
  }

  if (options->NodeFamilies) {
    options->NodeFamilySets = smartlist_new();
    for (cl = options->NodeFamilies; cl; cl = cl->next) {
      routerset_t *rs = routerset_new();
      if (routerset_parse(rs, cl->value, cl->key) == 0) {
        smartlist_add(options->NodeFamilySets, rs);
      } else {
        routerset_free(rs);
      }
    }
  }

  if (options->ExcludeNodes && options->StrictNodes) {
    COMPLAIN("You have asked to exclude certain relays from all positions "
             "in your circuits. Expect hidden services and other Tor "
             "features to be broken in unpredictable ways.");
  }

  if (options->AuthoritativeDir) {
    if (!options->ContactInfo && !options->TestingTorNetwork)
      REJECT("Authoritative directory servers must set ContactInfo");
    if (options->V1AuthoritativeDir && !options->RecommendedVersions)
      REJECT("V1 authoritative dir servers must set RecommendedVersions.");
    if (!options->RecommendedClientVersions)
      options->RecommendedClientVersions =
        config_lines_dup(options->RecommendedVersions);
    if (!options->RecommendedServerVersions)
      options->RecommendedServerVersions =
        config_lines_dup(options->RecommendedVersions);
    if (options->VersioningAuthoritativeDir &&
        (!options->RecommendedClientVersions ||
         !options->RecommendedServerVersions))
      REJECT("Versioning authoritative dir servers must set "
             "Recommended*Versions.");
    if (options->UseEntryGuards) {
      log_info(LD_CONFIG, "Authoritative directory servers can't set "
               "UseEntryGuards. Disabling.");
      options->UseEntryGuards = 0;
    }
    if (!options->DownloadExtraInfo && authdir_mode_any_main(options)) {
      log_info(LD_CONFIG, "Authoritative directories always try to download "
               "extra-info documents. Setting DownloadExtraInfo.");
      options->DownloadExtraInfo = 1;
    }
    if (!(options->BridgeAuthoritativeDir || options->HSAuthoritativeDir ||
          options->V1AuthoritativeDir || options->V2AuthoritativeDir ||
          options->V3AuthoritativeDir))
      REJECT("AuthoritativeDir is set, but none of "
             "(Bridge/HS/V1/V2/V3)AuthoritativeDir is set.");
    /* If we have a v3bandwidthsfile and it's broken, complain on startup */
    if (options->V3BandwidthsFile && !old_options) {
      dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL);
    }
  }

  if (options->AuthoritativeDir && !options->DirPort)
    REJECT("Running as authoritative directory, but no DirPort set.");

  if (options->AuthoritativeDir && !options->ORPort)
    REJECT("Running as authoritative directory, but no ORPort set.");

  if (options->AuthoritativeDir && options->ClientOnly)
    REJECT("Running as authoritative directory, but ClientOnly also set.");

  if (options->FetchDirInfoExtraEarly && !options->FetchDirInfoEarly)
    REJECT("FetchDirInfoExtraEarly requires that you also set "
           "FetchDirInfoEarly");

  if (options->HSAuthoritativeDir && proxy_mode(options))
    REJECT("Running as authoritative v0 HS directory, but also configured "
           "as a client.");

  if (options->ConnLimit <= 0) {
    tor_asprintf(msg,
        "ConnLimit must be greater than 0, but was set to %d",
        options->ConnLimit);
    return -1;
  }

  if (options->MaxClientCircuitsPending <= 0 ||
      options->MaxClientCircuitsPending > MAX_MAX_CLIENT_CIRCUITS_PENDING) {
    tor_asprintf(msg,
                 "MaxClientCircuitsPending must be between 1 and %d, but "
                 "was set to %d", MAX_MAX_CLIENT_CIRCUITS_PENDING,
                 options->MaxClientCircuitsPending);
    return -1;
  }

  if (validate_ports_csv(options->FirewallPorts, "FirewallPorts", msg) < 0)
    return -1;

  if (validate_ports_csv(options->LongLivedPorts, "LongLivedPorts", msg) < 0)
    return -1;

  if (validate_ports_csv(options->RejectPlaintextPorts,
                         "RejectPlaintextPorts", msg) < 0)
    return -1;

  if (validate_ports_csv(options->WarnPlaintextPorts,
                         "WarnPlaintextPorts", msg) < 0)
    return -1;

  if (options->FascistFirewall && !options->ReachableAddresses) {
    if (options->FirewallPorts && smartlist_len(options->FirewallPorts)) {
      /* We already have firewall ports set, so migrate them to
       * ReachableAddresses, which will set ReachableORAddresses and
       * ReachableDirAddresses if they aren't set explicitly. */
      smartlist_t *instead = smartlist_new();
      config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
      new_line->key = tor_strdup("ReachableAddresses");
      /* If we're configured with the old format, we need to prepend some
       * open ports. */
      SMARTLIST_FOREACH(options->FirewallPorts, const char *, portno,
      {
        int p = atoi(portno);
        if (p<0) continue;
        smartlist_add_asprintf(instead, "*:%d", p);
      });
      new_line->value = smartlist_join_strings(instead,",",0,NULL);
      /* These have been deprecated since 0.1.1.5-alpha-cvs */
      log(LOG_NOTICE, LD_CONFIG,
          "Converting FascistFirewall and FirewallPorts "
          "config options to new format: \"ReachableAddresses %s\"",
          new_line->value);
      options->ReachableAddresses = new_line;
      SMARTLIST_FOREACH(instead, char *, cp, tor_free(cp));
      smartlist_free(instead);
    } else {
      /* We do not have FirewallPorts set, so add 80 to
       * ReachableDirAddresses, and 443 to ReachableORAddresses. */
      if (!options->ReachableDirAddresses) {
        config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
        new_line->key = tor_strdup("ReachableDirAddresses");
        new_line->value = tor_strdup("*:80");
        options->ReachableDirAddresses = new_line;
        log(LOG_NOTICE, LD_CONFIG, "Converting FascistFirewall config option "
            "to new format: \"ReachableDirAddresses *:80\"");
      }
      if (!options->ReachableORAddresses) {
        config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
        new_line->key = tor_strdup("ReachableORAddresses");
        new_line->value = tor_strdup("*:443");
        options->ReachableORAddresses = new_line;
        log(LOG_NOTICE, LD_CONFIG, "Converting FascistFirewall config option "
            "to new format: \"ReachableORAddresses *:443\"");
      }
    }
  }

  for (i=0; i<3; i++) {
    config_line_t **linep =
      (i==0) ? &options->ReachableAddresses :
        (i==1) ? &options->ReachableORAddresses :
                 &options->ReachableDirAddresses;
    if (!*linep)
      continue;
    /* We need to end with a reject *:*, not an implicit accept *:* */
    for (;;) {
      if (!strcmp((*linep)->value, "reject *:*")) /* already there */
        break;
      linep = &((*linep)->next);
      if (!*linep) {
        *linep = tor_malloc_zero(sizeof(config_line_t));
        (*linep)->key = tor_strdup(
          (i==0) ?  "ReachableAddresses" :
            (i==1) ? "ReachableORAddresses" :
                     "ReachableDirAddresses");
        (*linep)->value = tor_strdup("reject *:*");
        break;
      }
    }
  }

  if ((options->ReachableAddresses ||
       options->ReachableORAddresses ||
       options->ReachableDirAddresses) &&
      server_mode(options))
    REJECT("Servers must be able to freely connect to the rest "
           "of the Internet, so they must not set Reachable*Addresses "
           "or FascistFirewall.");

  if (options->UseBridges &&
      server_mode(options))
    REJECT("Servers must be able to freely connect to the rest "
           "of the Internet, so they must not set UseBridges.");

  /* If both of these are set, we'll end up with funny behavior where we
   * demand enough entrynodes be up and running else we won't build
   * circuits, yet we never actually use them. */
  if (options->UseBridges && options->EntryNodes)
    REJECT("You cannot set both UseBridges and EntryNodes.");

  if (options->EntryNodes && !options->UseEntryGuards)
    log_warn(LD_CONFIG, "EntryNodes is set, but UseEntryGuards is disabled. "
             "EntryNodes will be ignored.");

  options->_AllowInvalid = 0;
  if (options->AllowInvalidNodes) {
    SMARTLIST_FOREACH(options->AllowInvalidNodes, const char *, cp, {
        if (!strcasecmp(cp, "entry"))
          options->_AllowInvalid |= ALLOW_INVALID_ENTRY;
        else if (!strcasecmp(cp, "exit"))
          options->_AllowInvalid |= ALLOW_INVALID_EXIT;
        else if (!strcasecmp(cp, "middle"))
          options->_AllowInvalid |= ALLOW_INVALID_MIDDLE;
        else if (!strcasecmp(cp, "introduction"))
          options->_AllowInvalid |= ALLOW_INVALID_INTRODUCTION;
        else if (!strcasecmp(cp, "rendezvous"))
          options->_AllowInvalid |= ALLOW_INVALID_RENDEZVOUS;
        else {
          tor_asprintf(msg,
              "Unrecognized value '%s' in AllowInvalidNodes", cp);
          return -1;
        }
      });
  }

  if (!options->SafeLogging ||
      !strcasecmp(options->SafeLogging, "0")) {
    options->_SafeLogging = SAFELOG_SCRUB_NONE;
  } else if (!strcasecmp(options->SafeLogging, "relay")) {
    options->_SafeLogging = SAFELOG_SCRUB_RELAY;
  } else if (!strcasecmp(options->SafeLogging, "1")) {
    options->_SafeLogging = SAFELOG_SCRUB_ALL;
  } else {
    tor_asprintf(msg,
                     "Unrecognized value '%s' in SafeLogging",
                     escaped(options->SafeLogging));
    return -1;
  }

  if (compute_publishserverdescriptor(options) < 0) {
    tor_asprintf(msg, "Unrecognized value in PublishServerDescriptor");
    return -1;
  }

  if ((options->BridgeRelay
        || options->_PublishServerDescriptor & BRIDGE_DIRINFO)
      && (options->_PublishServerDescriptor
          & (V1_DIRINFO|V2_DIRINFO|V3_DIRINFO))) {
    REJECT("Bridges are not supposed to publish router descriptors to the "
           "directory authorities. Please correct your "
           "PublishServerDescriptor line.");
  }

  if (options->BridgeRelay && options->DirPort) {
    log_warn(LD_CONFIG, "Can't set a DirPort on a bridge relay; disabling "
             "DirPort");
    config_free_lines(options->DirPort);
    options->DirPort = NULL;
  }

  if (options->MinUptimeHidServDirectoryV2 < 0) {
    log_warn(LD_CONFIG, "MinUptimeHidServDirectoryV2 option must be at "
                        "least 0 seconds. Changing to 0.");
    options->MinUptimeHidServDirectoryV2 = 0;
  }

  if (options->RendPostPeriod < MIN_REND_POST_PERIOD) {
    log_warn(LD_CONFIG, "RendPostPeriod option is too short; "
             "raising to %d seconds.", MIN_REND_POST_PERIOD);
    options->RendPostPeriod = MIN_REND_POST_PERIOD;
  }

  if (options->RendPostPeriod > MAX_DIR_PERIOD) {
    log_warn(LD_CONFIG, "RendPostPeriod is too large; clipping to %ds.",
             MAX_DIR_PERIOD);
    options->RendPostPeriod = MAX_DIR_PERIOD;
  }

  if (options->Tor2webMode && options->LearnCircuitBuildTimeout) {
    /* LearnCircuitBuildTimeout and Tor2webMode are incompatible in
     * two ways:
     *
     * - LearnCircuitBuildTimeout results in a low CBT, which
     *   Tor2webMode's use of one-hop rendezvous circuits lowers
     *   much further, producing *far* too many timeouts.
     *
     * - The adaptive CBT code does not update its timeout estimate
     *   using build