mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Merge branch 'ipv6_bridges_squashed'
This commit is contained in:
commit
8cc8b016c8
7
changes/bug3786
Normal file
7
changes/bug3786
Normal file
@ -0,0 +1,7 @@
|
||||
o Major features:
|
||||
- Implement support for clients connecting to private bridges over
|
||||
IPv6. Bridges still need at least one IPv4 address in order to
|
||||
connect to other relays. Currently, adding Bridge lines with
|
||||
both an IPv4 and an IPv6 address to the same bridge will most
|
||||
probably result in the IPv6 address not being used. Implements
|
||||
parts of proposal 186.
|
@ -31,6 +31,13 @@ typedef struct tor_addr_t
|
||||
} addr;
|
||||
} tor_addr_t;
|
||||
|
||||
/** Holds an IP address and a TCP/UDP port. */
|
||||
typedef struct tor_addr_port_t
|
||||
{
|
||||
tor_addr_t addr;
|
||||
uint16_t port;
|
||||
} tor_addr_port_t;
|
||||
|
||||
static INLINE const struct in6_addr *tor_addr_to_in6(const tor_addr_t *a);
|
||||
static INLINE uint32_t tor_addr_to_ipv4n(const tor_addr_t *a);
|
||||
static INLINE uint32_t tor_addr_to_ipv4h(const tor_addr_t *a);
|
||||
|
@ -3012,7 +3012,7 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit)
|
||||
log_warn(LD_CIRC,"failed to choose an exit server");
|
||||
return -1;
|
||||
}
|
||||
exit = extend_info_from_node(node);
|
||||
exit = extend_info_from_node(node, 0);
|
||||
tor_assert(exit);
|
||||
}
|
||||
state->chosen_exit = exit;
|
||||
@ -3254,14 +3254,19 @@ onion_extend_cpath(origin_circuit_t *circ)
|
||||
} else if (cur_len == 0) { /* picking first node */
|
||||
const node_t *r = choose_good_entry_server(purpose, state);
|
||||
if (r) {
|
||||
info = extend_info_from_node(r);
|
||||
/* If we're extending to a bridge, use the preferred address
|
||||
rather than the primary, for potentially extending to an IPv6
|
||||
bridge. */
|
||||
int use_pref_addr = (r->ri != NULL &&
|
||||
r->ri->purpose == ROUTER_PURPOSE_BRIDGE);
|
||||
info = extend_info_from_node(r, use_pref_addr);
|
||||
tor_assert(info);
|
||||
}
|
||||
} else {
|
||||
const node_t *r =
|
||||
choose_good_middle_server(purpose, state, circ->cpath, cur_len);
|
||||
if (r) {
|
||||
info = extend_info_from_node(r);
|
||||
info = extend_info_from_node(r, 0);
|
||||
tor_assert(info);
|
||||
}
|
||||
}
|
||||
@ -3320,28 +3325,36 @@ extend_info_alloc(const char *nickname, const char *digest,
|
||||
return info;
|
||||
}
|
||||
|
||||
/** Allocate and return a new extend_info_t that can be used to build a
|
||||
* circuit to or through the router <b>r</b>. */
|
||||
/** Allocate and return a new extend_info_t that can be used to build
|
||||
* a circuit to or through the router <b>r</b>. Use the primary
|
||||
* address of the router unless <b>for_direct_connect</b> is true, in
|
||||
* which case the preferred address is used instead. */
|
||||
extend_info_t *
|
||||
extend_info_from_router(const routerinfo_t *r)
|
||||
extend_info_from_router(const routerinfo_t *r, int for_direct_connect)
|
||||
{
|
||||
tor_addr_t addr;
|
||||
tor_addr_port_t ap;
|
||||
tor_assert(r);
|
||||
tor_addr_from_ipv4h(&addr, r->addr);
|
||||
|
||||
if (for_direct_connect)
|
||||
router_get_pref_orport(r, &ap);
|
||||
else
|
||||
router_get_prim_orport(r, &ap);
|
||||
return extend_info_alloc(r->nickname, r->cache_info.identity_digest,
|
||||
r->onion_pkey, &addr, r->or_port);
|
||||
r->onion_pkey, &ap.addr, ap.port);
|
||||
}
|
||||
|
||||
/** Allocate and return a new extend_info that can be used to build a ircuit
|
||||
* to or through the node <b>node</b>. May return NULL if there is not
|
||||
* enough info about <b>node</b> to extend to it--for example, if there
|
||||
* is no routerinfo_t or microdesc_t.
|
||||
/** Allocate and return a new extend_info that can be used to build a
|
||||
* ircuit to or through the node <b>node</b>. Use the primary address
|
||||
* of the node unless <b>for_direct_connect</b> is true, in which case
|
||||
* the preferred address is used instead. May return NULL if there is
|
||||
* not enough info about <b>node</b> to extend to it--for example, if
|
||||
* there is no routerinfo_t or microdesc_t.
|
||||
**/
|
||||
extend_info_t *
|
||||
extend_info_from_node(const node_t *node)
|
||||
extend_info_from_node(const node_t *node, int for_direct_connect)
|
||||
{
|
||||
if (node->ri) {
|
||||
return extend_info_from_router(node->ri);
|
||||
return extend_info_from_router(node->ri, for_direct_connect);
|
||||
} else if (node->rs && node->md) {
|
||||
tor_addr_t addr;
|
||||
tor_addr_from_ipv4h(&addr, node->rs->addr);
|
||||
@ -4841,10 +4854,11 @@ get_configured_bridge_by_addr_port_digest(const tor_addr_t *addr,
|
||||
static bridge_info_t *
|
||||
get_configured_bridge_by_routerinfo(const routerinfo_t *ri)
|
||||
{
|
||||
tor_addr_t addr;
|
||||
tor_addr_from_ipv4h(&addr, ri->addr);
|
||||
return get_configured_bridge_by_addr_port_digest(&addr,
|
||||
ri->or_port, ri->cache_info.identity_digest);
|
||||
tor_addr_port_t ap;
|
||||
|
||||
router_get_pref_orport(ri, &ap);
|
||||
return get_configured_bridge_by_addr_port_digest(&ap.addr, ap.port,
|
||||
ri->cache_info.identity_digest);
|
||||
}
|
||||
|
||||
/** Return 1 if <b>ri</b> is one of our known bridges, else 0. */
|
||||
@ -4858,18 +4872,31 @@ routerinfo_is_a_configured_bridge(const routerinfo_t *ri)
|
||||
int
|
||||
node_is_a_configured_bridge(const node_t *node)
|
||||
{
|
||||
tor_addr_t addr;
|
||||
uint16_t orport;
|
||||
if (!node)
|
||||
return 0;
|
||||
if (node_get_addr(node, &addr) < 0)
|
||||
return 0;
|
||||
orport = node_get_orport(node);
|
||||
if (orport == 0)
|
||||
return 0;
|
||||
int retval = 0; /* Negative. */
|
||||
smartlist_t *orports = NULL;
|
||||
|
||||
return get_configured_bridge_by_addr_port_digest(
|
||||
&addr, orport, node->identity) != NULL;
|
||||
if (!node)
|
||||
goto out;
|
||||
|
||||
orports = node_get_all_orports(node);
|
||||
if (orports == NULL)
|
||||
goto out;
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(orports, tor_addr_port_t *, orport) {
|
||||
if (get_configured_bridge_by_addr_port_digest(&orport->addr, orport->port,
|
||||
node->identity) != NULL) {
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(orport);
|
||||
|
||||
out:
|
||||
if (orports != NULL) {
|
||||
SMARTLIST_FOREACH(orports, tor_addr_port_t *, p, tor_free(p));
|
||||
smartlist_free(orports);
|
||||
orports = NULL;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/** We made a connection to a router at <b>addr</b>:<b>port</b>
|
||||
@ -5123,18 +5150,52 @@ rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node)
|
||||
routerinfo_t *ri = node->ri;
|
||||
tor_addr_from_ipv4h(&addr, ri->addr);
|
||||
|
||||
if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
|
||||
bridge->port == ri->or_port) {
|
||||
if ((!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
|
||||
bridge->port == ri->or_port) ||
|
||||
(!tor_addr_compare(&bridge->addr, &ri->ipv6_addr, CMP_EXACT) &&
|
||||
bridge->port == ri->ipv6_orport)) {
|
||||
/* they match, so no need to do anything */
|
||||
} else {
|
||||
ri->addr = tor_addr_to_ipv4h(&bridge->addr);
|
||||
tor_free(ri->address);
|
||||
ri->address = tor_dup_ip(ri->addr);
|
||||
ri->or_port = bridge->port;
|
||||
log_info(LD_DIR,
|
||||
"Adjusted bridge routerinfo for '%s' to match configured "
|
||||
"address %s:%d.",
|
||||
ri->nickname, ri->address, ri->or_port);
|
||||
if (tor_addr_family(&bridge->addr) == AF_INET) {
|
||||
ri->addr = tor_addr_to_ipv4h(&bridge->addr);
|
||||
tor_free(ri->address);
|
||||
ri->address = tor_dup_ip(ri->addr);
|
||||
ri->or_port = bridge->port;
|
||||
log_info(LD_DIR,
|
||||
"Adjusted bridge routerinfo for '%s' to match configured "
|
||||
"address %s:%d.",
|
||||
ri->nickname, ri->address, ri->or_port);
|
||||
} else if (tor_addr_family(&bridge->addr) == AF_INET6) {
|
||||
tor_addr_copy(&ri->ipv6_addr, &bridge->addr);
|
||||
ri->ipv6_orport = bridge->port;
|
||||
log_info(LD_DIR,
|
||||
"Adjusted bridge routerinfo for '%s' to match configured "
|
||||
"address %s:%d.",
|
||||
ri->nickname, fmt_addr(&ri->ipv6_addr), ri->ipv6_orport);
|
||||
} else {
|
||||
log_err(LD_BUG, "Address family not supported: %d.",
|
||||
tor_addr_family(&bridge->addr));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Indicate that we prefer connecting to this bridge over the
|
||||
protocol that the bridge address indicates. Last bridge
|
||||
descriptor handled wins. */
|
||||
ri->ipv6_preferred = tor_addr_family(&bridge->addr) == AF_INET6;
|
||||
|
||||
/* XXXipv6 we lack support for falling back to another address for
|
||||
the same relay, warn the user */
|
||||
if (!tor_addr_is_null(&ri->ipv6_addr))
|
||||
{
|
||||
tor_addr_port_t ap;
|
||||
router_get_pref_orport(ri, &ap);
|
||||
log_notice(LD_CONFIG,
|
||||
"Bridge '%s' has both an IPv4 and an IPv6 address. "
|
||||
"Will prefer using its %s address (%s:%d).",
|
||||
ri->nickname,
|
||||
ri->ipv6_preferred ? "IPv6" : "IPv4",
|
||||
fmt_addr(&ap.addr), ap.port);
|
||||
}
|
||||
}
|
||||
if (node->rs) {
|
||||
@ -5179,8 +5240,8 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
|
||||
rewrite_node_address_for_bridge(bridge, node);
|
||||
add_an_entry_guard(node, 1, 1);
|
||||
|
||||
log_notice(LD_DIR, "new bridge descriptor '%s' (%s)", ri->nickname,
|
||||
from_cache ? "cached" : "fresh");
|
||||
log_notice(LD_DIR, "new bridge descriptor '%s' (%s): %s", ri->nickname,
|
||||
from_cache ? "cached" : "fresh", router_describe(ri));
|
||||
/* set entry->made_contact so if it goes down we don't drop it from
|
||||
* our entry node list */
|
||||
entry_guard_register_connect_status(ri->cache_info.identity_digest,
|
||||
|
@ -59,8 +59,10 @@ void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop);
|
||||
extend_info_t *extend_info_alloc(const char *nickname, const char *digest,
|
||||
crypto_pk_env_t *onion_key,
|
||||
const tor_addr_t *addr, uint16_t port);
|
||||
extend_info_t *extend_info_from_router(const routerinfo_t *r);
|
||||
extend_info_t *extend_info_from_node(const node_t *node);
|
||||
extend_info_t *extend_info_from_router(const routerinfo_t *r,
|
||||
int for_direct_connect);
|
||||
extend_info_t *extend_info_from_node(const node_t *node,
|
||||
int for_direct_connect);
|
||||
extend_info_t *extend_info_dup(extend_info_t *info);
|
||||
void extend_info_free(extend_info_t *info);
|
||||
const node_t *build_state_get_exit_node(cpath_build_state_t *state);
|
||||
|
@ -1439,7 +1439,10 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
|
||||
int opt = conn->chosen_exit_optional;
|
||||
r = node_get_by_nickname(conn->chosen_exit_name, 1);
|
||||
if (r && node_has_descriptor(r)) {
|
||||
extend_info = extend_info_from_node(r);
|
||||
/* We might want to connect to an IPv6 bridge for loading
|
||||
descriptors so we use the preferred address rather than
|
||||
the primary. */
|
||||
extend_info = extend_info_from_node(r, conn->want_onehop ? 1 : 0);
|
||||
} else {
|
||||
log_debug(LD_DIR, "considering %d, %s",
|
||||
want_onehop, conn->chosen_exit_name);
|
||||
|
568
src/or/config.c
568
src/or/config.c
@ -220,7 +220,7 @@ static config_var_t _option_vars[] = {
|
||||
V(ConstrainedSockSize, MEMUNIT, "8192"),
|
||||
V(ContactInfo, STRING, NULL),
|
||||
V(ControlListenAddress, LINELIST, NULL),
|
||||
V(ControlPort, PORT, "0"),
|
||||
V(ControlPort, LINELIST, NULL),
|
||||
V(ControlPortFileGroupReadable,BOOL, "0"),
|
||||
V(ControlPortWriteToFile, FILENAME, NULL),
|
||||
V(ControlSocket, LINELIST, NULL),
|
||||
@ -237,7 +237,7 @@ static config_var_t _option_vars[] = {
|
||||
V(DirListenAddress, LINELIST, NULL),
|
||||
OBSOLETE("DirFetchPeriod"),
|
||||
V(DirPolicy, LINELIST, NULL),
|
||||
V(DirPort, PORT, "0"),
|
||||
V(DirPort, LINELIST, NULL),
|
||||
V(DirPortFrontPage, FILENAME, NULL),
|
||||
OBSOLETE("DirPostPeriod"),
|
||||
OBSOLETE("DirRecordUsageByCountry"),
|
||||
@ -343,7 +343,7 @@ static config_var_t _option_vars[] = {
|
||||
V(NumCPUs, UINT, "0"),
|
||||
V(NumEntryGuards, UINT, "3"),
|
||||
V(ORListenAddress, LINELIST, NULL),
|
||||
V(ORPort, PORT, "0"),
|
||||
V(ORPort, LINELIST, NULL),
|
||||
V(OutboundBindAddress, STRING, NULL),
|
||||
OBSOLETE("PathlenCoinWeight"),
|
||||
V(PerConnBWBurst, MEMUNIT, "0"),
|
||||
@ -600,8 +600,11 @@ static int parse_dir_server_line(const char *line,
|
||||
dirinfo_type_t required_type,
|
||||
int validate_only);
|
||||
static void port_cfg_free(port_cfg_t *port);
|
||||
static int parse_client_ports(const or_options_t *options, int validate_only,
|
||||
static int parse_ports(const or_options_t *options, int validate_only,
|
||||
char **msg_out, int *n_ports_out);
|
||||
static int check_server_ports(const smartlist_t *ports,
|
||||
const or_options_t *options);
|
||||
|
||||
static int validate_data_directory(or_options_t *options);
|
||||
static int write_configuration_file(const char *fname,
|
||||
const or_options_t *options);
|
||||
@ -614,9 +617,6 @@ static int or_state_validate(or_state_t *old_options, or_state_t *options,
|
||||
static int or_state_load(void);
|
||||
static int options_init_logs(or_options_t *options, int validate_only);
|
||||
|
||||
static int is_listening_on_low_port(int port_option,
|
||||
const config_line_t *listen_options);
|
||||
|
||||
static uint64_t config_parse_memunit(const char *s, int *ok);
|
||||
static int config_parse_msec_interval(const char *s, int *ok);
|
||||
static int config_parse_interval(const char *s, int *ok);
|
||||
@ -675,8 +675,8 @@ static or_state_t *global_state = NULL;
|
||||
static config_line_t *global_cmdline_options = NULL;
|
||||
/** Contents of most recently read DirPortFrontPage file. */
|
||||
static char *global_dirfrontpagecontents = NULL;
|
||||
/** List of port_cfg_t for client-level (SOCKS, DNS, Trans, NATD) ports. */
|
||||
static smartlist_t *configured_client_ports = NULL;
|
||||
/** List of port_cfg_t for all configured ports. */
|
||||
static smartlist_t *configured_ports = NULL;
|
||||
|
||||
/** Return the contents of our frontpage string, or NULL if not configured. */
|
||||
const char *
|
||||
@ -821,11 +821,11 @@ config_free_all(void)
|
||||
config_free_lines(global_cmdline_options);
|
||||
global_cmdline_options = NULL;
|
||||
|
||||
if (configured_client_ports) {
|
||||
SMARTLIST_FOREACH(configured_client_ports,
|
||||
if (configured_ports) {
|
||||
SMARTLIST_FOREACH(configured_ports,
|
||||
port_cfg_t *, p, tor_free(p));
|
||||
smartlist_free(configured_client_ports);
|
||||
configured_client_ports = NULL;
|
||||
smartlist_free(configured_ports);
|
||||
configured_ports = NULL;
|
||||
}
|
||||
|
||||
tor_free(torrc_fname);
|
||||
@ -1075,7 +1075,7 @@ options_act_reversible(const or_options_t *old_options, char **msg)
|
||||
#endif
|
||||
|
||||
if (running_tor) {
|
||||
int n_client_ports=0;
|
||||
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) {
|
||||
@ -1091,10 +1091,10 @@ options_act_reversible(const or_options_t *old_options, char **msg)
|
||||
libevent_initialized = 1;
|
||||
}
|
||||
|
||||
/* Adjust the client port configuration so we can launch listeners. */
|
||||
if (parse_client_ports(options, 0, msg, &n_client_ports)) {
|
||||
/* 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 client port config");
|
||||
*msg = tor_strdup("Unexpected problem parsing port config");
|
||||
goto rollback;
|
||||
}
|
||||
|
||||
@ -1555,7 +1555,7 @@ options_act(const or_options_t *old_options)
|
||||
int was_relay = 0;
|
||||
if (options->BridgeRelay) {
|
||||
time_t int_start = time(NULL);
|
||||
if (old_options->ORPort == options->ORPort) {
|
||||
if (config_lines_eq(old_options->ORPort, options->ORPort)) {
|
||||
int_start += RELAY_BRIDGE_STATS_DELAY;
|
||||
was_relay = 1;
|
||||
}
|
||||
@ -3034,37 +3034,6 @@ options_init(or_options_t *options)
|
||||
config_init(&options_format, options);
|
||||
}
|
||||
|
||||
/* Check if the port number given in <b>port_option</b> in combination with
|
||||
* the specified port in <b>listen_options</b> will result in Tor actually
|
||||
* opening a low port (meaning a port lower than 1024). Return 1 if
|
||||
* it is, or 0 if it isn't or the concept of a low port isn't applicable for
|
||||
* the platform we're on. */
|
||||
static int
|
||||
is_listening_on_low_port(int port_option,
|
||||
const config_line_t *listen_options)
|
||||
{
|
||||
#ifdef MS_WINDOWS
|
||||
(void) port_option;
|
||||
(void) listen_options;
|
||||
return 0; /* No port is too low for windows. */
|
||||
#else
|
||||
const config_line_t *l;
|
||||
uint16_t p;
|
||||
if (port_option == 0)
|
||||
return 0; /* We're not listening */
|
||||
if (listen_options == NULL)
|
||||
return (port_option < 1024);
|
||||
|
||||
for (l = listen_options; l; l = l->next) {
|
||||
addr_port_lookup(LOG_WARN, l->value, NULL, NULL, &p);
|
||||
if (p<1024) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Set all vars in the configuration object <b>options</b> to their default
|
||||
* values. */
|
||||
static void
|
||||
@ -3290,7 +3259,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
int i;
|
||||
config_line_t *cl;
|
||||
const char *uname = get_uname();
|
||||
int n_client_ports=0;
|
||||
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
|
||||
@ -3308,13 +3277,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
"for details.", uname);
|
||||
}
|
||||
|
||||
if (options->ORPort == 0 && options->ORListenAddress != NULL)
|
||||
REJECT("ORPort must be defined if ORListenAddress is defined.");
|
||||
|
||||
if (options->DirPort == 0 && options->DirListenAddress != NULL)
|
||||
REJECT("DirPort must be defined if DirListenAddress is defined.");
|
||||
|
||||
if (parse_client_ports(options, 1, msg, &n_client_ports) < 0)
|
||||
if (parse_ports(options, 1, msg, &n_ports) < 0)
|
||||
return -1;
|
||||
|
||||
if (validate_data_directory(options)<0)
|
||||
@ -3361,7 +3324,9 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
REJECT("Can't use a relative path to torrc when RunAsDaemon is set.");
|
||||
#endif
|
||||
|
||||
if (n_client_ports == 0 && options->ORPort == 0 && !options->RendConfigLines)
|
||||
/* 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. "
|
||||
@ -3377,19 +3342,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
REJECT("TokenBucketRefillInterval must be between 1 and 1000 inclusive.");
|
||||
}
|
||||
|
||||
if (options->AccountingMax &&
|
||||
(is_listening_on_low_port(options->ORPort, options->ORListenAddress) ||
|
||||
is_listening_on_low_port(options->DirPort, options->DirListenAddress)))
|
||||
{
|
||||
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.");
|
||||
}
|
||||
|
||||
if (options->ExcludeExitNodes || options->ExcludeNodes) {
|
||||
options->_ExcludeExitNodesUnion = routerset_new();
|
||||
routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeExitNodes);
|
||||
@ -3643,7 +3595,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
if (options->BridgeRelay && options->DirPort) {
|
||||
log_warn(LD_CONFIG, "Can't set a DirPort on a bridge relay; disabling "
|
||||
"DirPort");
|
||||
options->DirPort = 0;
|
||||
config_free_lines(options->DirPort);
|
||||
options->DirPort = NULL;
|
||||
}
|
||||
|
||||
if (options->MinUptimeHidServDirectoryV2 < 0) {
|
||||
@ -3866,39 +3819,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
}
|
||||
}
|
||||
|
||||
if (options->ControlListenAddress) {
|
||||
int all_are_local = 1;
|
||||
config_line_t *ln;
|
||||
for (ln = options->ControlListenAddress; ln; ln = ln->next) {
|
||||
if (strcmpstart(ln->value, "127."))
|
||||
all_are_local = 0;
|
||||
}
|
||||
if (!all_are_local) {
|
||||
if (!options->HashedControlPassword &&
|
||||
!options->HashedControlSessionPassword &&
|
||||
!options->CookieAuthentication) {
|
||||
log_warn(LD_CONFIG,
|
||||
"You have a ControlListenAddress set to accept "
|
||||
"unauthenticated connections from a non-local address. "
|
||||
"This means that programs not running on your computer "
|
||||
"can reconfigure your Tor, without even having to guess a "
|
||||
"password. That's so bad that I'm closing your ControlPort "
|
||||
"for you. If you need to control your Tor remotely, try "
|
||||
"enabling authentication and using a tool like stunnel or "
|
||||
"ssh to encrypt remote access.");
|
||||
options->ControlPort = 0;
|
||||
} else {
|
||||
log_warn(LD_CONFIG, "You have a ControlListenAddress set to accept "
|
||||
"connections from a non-local address. This means that "
|
||||
"programs not running on your computer can reconfigure your "
|
||||
"Tor. That's pretty bad, since the controller "
|
||||
"protocol isn't encrypted! Maybe you should just listen on "
|
||||
"127.0.0.1 and use a tool like stunnel or ssh to encrypt "
|
||||
"remote connections to your control port.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options->ControlPort && !options->HashedControlPassword &&
|
||||
!options->HashedControlSessionPassword &&
|
||||
!options->CookieAuthentication) {
|
||||
@ -4121,8 +4041,9 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
}
|
||||
});
|
||||
|
||||
if (options->BridgeRelay == 1 && options->ORPort == 0)
|
||||
REJECT("BridgeRelay is 1, ORPort is 0. This is an invalid combination.");
|
||||
if (options->BridgeRelay == 1 && ! options->ORPort)
|
||||
REJECT("BridgeRelay is 1, ORPort is not set. This is an invalid "
|
||||
"combination.");
|
||||
|
||||
return 0;
|
||||
#undef REJECT
|
||||
@ -4213,7 +4134,7 @@ options_transition_affects_workers(const or_options_t *old_options,
|
||||
{
|
||||
if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) ||
|
||||
old_options->NumCPUs != new_options->NumCPUs ||
|
||||
old_options->ORPort != new_options->ORPort ||
|
||||
!config_lines_eq(old_options->ORPort, new_options->ORPort) ||
|
||||
old_options->ServerDNSSearchDomains !=
|
||||
new_options->ServerDNSSearchDomains ||
|
||||
old_options->_SafeLogging != new_options->_SafeLogging ||
|
||||
@ -4243,8 +4164,8 @@ options_transition_affects_descriptor(const or_options_t *old_options,
|
||||
!config_lines_eq(old_options->ExitPolicy,new_options->ExitPolicy) ||
|
||||
old_options->ExitPolicyRejectPrivate !=
|
||||
new_options->ExitPolicyRejectPrivate ||
|
||||
old_options->ORPort != new_options->ORPort ||
|
||||
old_options->DirPort != new_options->DirPort ||
|
||||
!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 !=
|
||||
@ -5380,12 +5301,53 @@ warn_nonlocal_client_ports(const smartlist_t *ports, const char *portname)
|
||||
} SMARTLIST_FOREACH_END(port);
|
||||
}
|
||||
|
||||
#define CL_PORT_NO_OPTIONS (1u<<0)
|
||||
/** DOCDOC */
|
||||
static void
|
||||
warn_nonlocal_controller_ports(smartlist_t *ports, unsigned forbid)
|
||||
{
|
||||
int warned = 0;
|
||||
SMARTLIST_FOREACH_BEGIN(ports, port_cfg_t *, port) {
|
||||
if (port->type != CONN_TYPE_CONTROL_LISTENER)
|
||||
continue;
|
||||
if (port->is_unix_addr)
|
||||
continue;
|
||||
if (!tor_addr_is_loopback(&port->addr)) {
|
||||
if (forbid) {
|
||||
if (!warned)
|
||||
log_warn(LD_CONFIG,
|
||||
"You have a ControlPort set to accept "
|
||||
"unauthenticated connections from a non-local address. "
|
||||
"This means that programs not running on your computer "
|
||||
"can reconfigure your Tor, without even having to guess a "
|
||||
"password. That's so bad that I'm closing your ControlPort "
|
||||
"for you. If you need to control your Tor remotely, try "
|
||||
"enabling authentication and using a tool like stunnel or "
|
||||
"ssh to encrypt remote access.");
|
||||
warned = 1;
|
||||
port_cfg_free(port);
|
||||
SMARTLIST_DEL_CURRENT(ports, port);
|
||||
} else {
|
||||
log_warn(LD_CONFIG, "You have a ControlPort set to accept "
|
||||
"connections from a non-local address. This means that "
|
||||
"programs not running on your computer can reconfigure your "
|
||||
"Tor. That's pretty bad, since the controller "
|
||||
"protocol isn't encrypted! Maybe you should just listen on "
|
||||
"127.0.0.1 and use a tool like stunnel or ssh to encrypt "
|
||||
"remote connections to your control port.");
|
||||
return; /* No point in checking the rest */
|
||||
}
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(port);
|
||||
}
|
||||
|
||||
#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)
|
||||
|
||||
/**
|
||||
* Parse port configuration for a single client port type.
|
||||
* Parse port configuration for a single port type.
|
||||
*
|
||||
* Read entries of the "FooPort" type from the list <b>ports</b>, and
|
||||
* entries of the "FooListenAddress" type from the list
|
||||
@ -5405,17 +5367,22 @@ warn_nonlocal_client_ports(const smartlist_t *ports, const char *portname)
|
||||
* isolation options in the FooPort entries.
|
||||
*
|
||||
* If CL_PORT_WARN_NONLOCAL is set in <b>flags</b>, warn if any of the
|
||||
* ports are not on a local address.
|
||||
* ports are not on a local address. If CL_PORT_FORBID_NONLOCAL is set,
|
||||
* this is a contrl port with no password set: don't even allow it.
|
||||
*
|
||||
* Unless CL_PORT_ALLOW_EXTRA_LISTENADDR is set in <b>flags</b>, warn
|
||||
* if FooListenAddress is set but FooPort is 0.
|
||||
*
|
||||
* If CL_PORT_SERVER_OPTIONS is set in <b>flags</b>, do not allow stream
|
||||
* isolation options in the FooPort entries; instead allow the
|
||||
* server-port option set.
|
||||
*
|
||||
* On success, if <b>out</b> is given, add a new port_cfg_t entry to
|
||||
* <b>out</b> for every port that the client should listen on. Return 0
|
||||
* on success, -1 on failure.
|
||||
*/
|
||||
static int
|
||||
parse_client_port_config(smartlist_t *out,
|
||||
parse_port_config(smartlist_t *out,
|
||||
const config_line_t *ports,
|
||||
const config_line_t *listenaddrs,
|
||||
const char *portname,
|
||||
@ -5426,8 +5393,11 @@ parse_client_port_config(smartlist_t *out,
|
||||
{
|
||||
smartlist_t *elts;
|
||||
int retval = -1;
|
||||
const unsigned allow_client_options = !(flags & CL_PORT_NO_OPTIONS);
|
||||
const unsigned is_control = (listener_type == CONN_TYPE_CONTROL_LISTENER);
|
||||
const unsigned allow_no_options = flags & CL_PORT_NO_OPTIONS;
|
||||
const unsigned use_server_options = flags & CL_PORT_SERVER_OPTIONS;
|
||||
const unsigned warn_nonlocal = flags & CL_PORT_WARN_NONLOCAL;
|
||||
const unsigned forbid_nonlocal = flags & CL_PORT_FORBID_NONLOCAL;
|
||||
const unsigned allow_spurious_listenaddr =
|
||||
flags & CL_PORT_ALLOW_EXTRA_LISTENADDR;
|
||||
|
||||
@ -5463,6 +5433,17 @@ parse_client_port_config(smartlist_t *out,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (use_server_options && out) {
|
||||
/* Add a no_listen port. */
|
||||
port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t));
|
||||
cfg->type = listener_type;
|
||||
cfg->port = mainport;
|
||||
tor_addr_make_unspec(&cfg->addr); /* Server ports default to 0.0.0.0 */
|
||||
cfg->no_listen = 1;
|
||||
cfg->ipv4_only = 1;
|
||||
smartlist_add(out, cfg);
|
||||
}
|
||||
|
||||
for (; listenaddrs; listenaddrs = listenaddrs->next) {
|
||||
tor_addr_t addr;
|
||||
uint16_t port = 0;
|
||||
@ -5478,12 +5459,17 @@ parse_client_port_config(smartlist_t *out,
|
||||
tor_addr_copy(&cfg->addr, &addr);
|
||||
cfg->session_group = SESSION_GROUP_UNSET;
|
||||
cfg->isolation_flags = ISO_DEFAULT;
|
||||
cfg->no_advertise = 1;
|
||||
smartlist_add(out, cfg);
|
||||
}
|
||||
}
|
||||
|
||||
if (warn_nonlocal && out)
|
||||
warn_nonlocal_client_ports(out, portname);
|
||||
if (warn_nonlocal && out) {
|
||||
if (is_control)
|
||||
warn_nonlocal_controller_ports(out, forbid_nonlocal);
|
||||
else
|
||||
warn_nonlocal_client_ports(out, portname);
|
||||
}
|
||||
return 0;
|
||||
} /* end if (listenaddrs) */
|
||||
|
||||
@ -5515,6 +5501,8 @@ parse_client_port_config(smartlist_t *out,
|
||||
char *addrport;
|
||||
uint16_t ptmp=0;
|
||||
int ok;
|
||||
int no_listen = 0, no_advertise = 0, all_addrs = 0,
|
||||
ipv4_only = 0, ipv6_only = 0;
|
||||
|
||||
smartlist_split_string(elts, ports->value, NULL,
|
||||
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
|
||||
@ -5523,7 +5511,7 @@ parse_client_port_config(smartlist_t *out,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!allow_client_options && smartlist_len(elts) > 1) {
|
||||
if (allow_no_options && smartlist_len(elts) > 1) {
|
||||
log_warn(LD_CONFIG, "Too many options on %sPort line", portname);
|
||||
goto err;
|
||||
}
|
||||
@ -5562,56 +5550,107 @@ parse_client_port_config(smartlist_t *out,
|
||||
}
|
||||
|
||||
/* Now parse the rest of the options, if any. */
|
||||
SMARTLIST_FOREACH_BEGIN(elts, char *, elt) {
|
||||
int no = 0, isoflag = 0;
|
||||
const char *elt_orig = elt;
|
||||
if (elt_sl_idx == 0)
|
||||
continue; /* Skip addr:port */
|
||||
if (!strcasecmpstart(elt, "SessionGroup=")) {
|
||||
int group = (int)tor_parse_long(elt+strlen("SessionGroup="),
|
||||
10, 0, INT_MAX, &ok, NULL);
|
||||
if (!ok) {
|
||||
log_warn(LD_CONFIG, "Invalid %sPort option '%s'",
|
||||
if (use_server_options) {
|
||||
/* This is a server port; parse advertising options */
|
||||
SMARTLIST_FOREACH_BEGIN(elts, char *, elt) {
|
||||
if (elt_sl_idx == 0)
|
||||
continue; /* Skip addr:port */
|
||||
|
||||
if (!strcasecmp(elt, "NoAdvertise")) {
|
||||
no_advertise = 1;
|
||||
} else if (!strcasecmp(elt, "NoListen")) {
|
||||
no_listen = 1;
|
||||
#if 0
|
||||
/* not implemented yet. */
|
||||
} else if (!strcasecmp(elt, "AllAddrs")) {
|
||||
|
||||
all_addrs = 1;
|
||||
#endif
|
||||
} else if (!strcasecmp(elt, "IPv4Only")) {
|
||||
ipv4_only = 1;
|
||||
} else if (!strcasecmp(elt, "IPv6Only")) {
|
||||
ipv6_only = 1;
|
||||
} else {
|
||||
log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'",
|
||||
portname, escaped(elt));
|
||||
goto err;
|
||||
}
|
||||
if (sessiongroup >= 0) {
|
||||
log_warn(LD_CONFIG, "Multiple SessionGroup options on %sPort",
|
||||
portname);
|
||||
goto err;
|
||||
} SMARTLIST_FOREACH_END(elt);
|
||||
|
||||
if (no_advertise && no_listen) {
|
||||
log_warn(LD_CONFIG, "Tried to set both NoListen and NoAdvertise "
|
||||
"on %sPort line '%s'",
|
||||
portname, escaped(ports->value));
|
||||
goto err;
|
||||
}
|
||||
if (ipv4_only && ipv6_only) {
|
||||
log_warn(LD_CONFIG, "Tried to set both IPv4Only and IPv6Only "
|
||||
"on %sPort line '%s'",
|
||||
portname, escaped(ports->value));
|
||||
goto err;
|
||||
}
|
||||
if (ipv4_only && tor_addr_family(&addr) == AF_INET6) {
|
||||
log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv6",
|
||||
portname);
|
||||
goto err;
|
||||
}
|
||||
if (ipv6_only && tor_addr_family(&addr) == AF_INET) {
|
||||
log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv4",
|
||||
portname);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
/* This is a client port; parse isolation options */
|
||||
SMARTLIST_FOREACH_BEGIN(elts, char *, elt) {
|
||||
int no = 0, isoflag = 0;
|
||||
const char *elt_orig = elt;
|
||||
if (elt_sl_idx == 0)
|
||||
continue; /* Skip addr:port */
|
||||
if (!strcasecmpstart(elt, "SessionGroup=")) {
|
||||
int group = (int)tor_parse_long(elt+strlen("SessionGroup="),
|
||||
10, 0, INT_MAX, &ok, NULL);
|
||||
if (!ok) {
|
||||
log_warn(LD_CONFIG, "Invalid %sPort option '%s'",
|
||||
portname, escaped(elt));
|
||||
goto err;
|
||||
}
|
||||
if (sessiongroup >= 0) {
|
||||
log_warn(LD_CONFIG, "Multiple SessionGroup options on %sPort",
|
||||
portname);
|
||||
goto err;
|
||||
}
|
||||
sessiongroup = group;
|
||||
continue;
|
||||
}
|
||||
sessiongroup = group;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcasecmpstart(elt, "No")) {
|
||||
no = 1;
|
||||
elt += 2;
|
||||
}
|
||||
if (!strcasecmpend(elt, "s"))
|
||||
elt[strlen(elt)-1] = '\0'; /* kill plurals. */
|
||||
if (!strcasecmpstart(elt, "No")) {
|
||||
no = 1;
|
||||
elt += 2;
|
||||
}
|
||||
if (!strcasecmpend(elt, "s"))
|
||||
elt[strlen(elt)-1] = '\0'; /* kill plurals. */
|
||||
|
||||
if (!strcasecmp(elt, "IsolateDestPort")) {
|
||||
isoflag = ISO_DESTPORT;
|
||||
} else if (!strcasecmp(elt, "IsolateDestAddr")) {
|
||||
isoflag = ISO_DESTADDR;
|
||||
} else if (!strcasecmp(elt, "IsolateSOCKSAuth")) {
|
||||
isoflag = ISO_SOCKSAUTH;
|
||||
} else if (!strcasecmp(elt, "IsolateClientProtocol")) {
|
||||
isoflag = ISO_CLIENTPROTO;
|
||||
} else if (!strcasecmp(elt, "IsolateClientAddr")) {
|
||||
isoflag = ISO_CLIENTADDR;
|
||||
} else {
|
||||
log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'",
|
||||
portname, escaped(elt_orig));
|
||||
}
|
||||
if (!strcasecmp(elt, "IsolateDestPort")) {
|
||||
isoflag = ISO_DESTPORT;
|
||||
} else if (!strcasecmp(elt, "IsolateDestAddr")) {
|
||||
isoflag = ISO_DESTADDR;
|
||||
} else if (!strcasecmp(elt, "IsolateSOCKSAuth")) {
|
||||
isoflag = ISO_SOCKSAUTH;
|
||||
} else if (!strcasecmp(elt, "IsolateClientProtocol")) {
|
||||
isoflag = ISO_CLIENTPROTO;
|
||||
} else if (!strcasecmp(elt, "IsolateClientAddr")) {
|
||||
isoflag = ISO_CLIENTADDR;
|
||||
} else {
|
||||
log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'",
|
||||
portname, escaped(elt_orig));
|
||||
}
|
||||
|
||||
if (no) {
|
||||
isolation &= ~isoflag;
|
||||
} else {
|
||||
isolation |= isoflag;
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(elt);
|
||||
if (no) {
|
||||
isolation &= ~isoflag;
|
||||
} else {
|
||||
isolation |= isoflag;
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(elt);
|
||||
}
|
||||
|
||||
if (out && port) {
|
||||
port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t));
|
||||
@ -5620,14 +5659,24 @@ parse_client_port_config(smartlist_t *out,
|
||||
tor_addr_copy(&cfg->addr, &addr);
|
||||
cfg->session_group = sessiongroup;
|
||||
cfg->isolation_flags = isolation;
|
||||
cfg->no_listen = no_listen;
|
||||
cfg->no_listen = no_advertise;
|
||||
cfg->all_addrs = all_addrs;
|
||||
cfg->ipv4_only = ipv4_only;
|
||||
cfg->ipv6_only = ipv6_only;
|
||||
|
||||
smartlist_add(out, cfg);
|
||||
}
|
||||
SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
|
||||
smartlist_clear(elts);
|
||||
}
|
||||
|
||||
if (warn_nonlocal && out)
|
||||
warn_nonlocal_client_ports(out, portname);
|
||||
if (warn_nonlocal && out) {
|
||||
if (is_control)
|
||||
warn_nonlocal_controller_ports(out, forbid_nonlocal);
|
||||
else
|
||||
warn_nonlocal_client_ports(out, portname);
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
err:
|
||||
@ -5636,6 +5685,27 @@ parse_client_port_config(smartlist_t *out,
|
||||
return retval;
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
static int
|
||||
parse_socket_config(smartlist_t *out, const config_line_t *cfg,
|
||||
int listener_type)
|
||||
{
|
||||
|
||||
if (!out)
|
||||
return 0;
|
||||
|
||||
for ( ; cfg; cfg = cfg->next) {
|
||||
size_t len = strlen(cfg->value);
|
||||
port_cfg_t *port = tor_malloc_zero(sizeof(port_cfg_t) + len + 1);
|
||||
port->is_unix_addr = 1;
|
||||
memcpy(port->unix_addr, cfg->value, len+1);
|
||||
port->type = listener_type;
|
||||
smartlist_add(out, port);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Parse all client port types (Socks, DNS, Trans, NATD) from
|
||||
* <b>options</b>. On success, set *<b>n_ports_out</b> to the number of
|
||||
* ports that are listed and return 0. On failure, set *<b>msg</b> to a
|
||||
@ -5645,8 +5715,8 @@ parse_client_port_config(smartlist_t *out,
|
||||
* new list of ports parsed from <b>options</b>.
|
||||
**/
|
||||
static int
|
||||
parse_client_ports(const or_options_t *options, int validate_only,
|
||||
char **msg, int *n_ports_out)
|
||||
parse_ports(const or_options_t *options, int validate_only,
|
||||
char **msg, int *n_ports_out)
|
||||
{
|
||||
smartlist_t *ports;
|
||||
int retval = -1;
|
||||
@ -5655,7 +5725,7 @@ parse_client_ports(const or_options_t *options, int validate_only,
|
||||
|
||||
*n_ports_out = 0;
|
||||
|
||||
if (parse_client_port_config(ports,
|
||||
if (parse_port_config(ports,
|
||||
options->SocksPort, options->SocksListenAddress,
|
||||
"Socks", CONN_TYPE_AP_LISTENER,
|
||||
"127.0.0.1", 9050,
|
||||
@ -5663,7 +5733,7 @@ parse_client_ports(const or_options_t *options, int validate_only,
|
||||
*msg = tor_strdup("Invalid SocksPort/SocksListenAddress configuration");
|
||||
goto err;
|
||||
}
|
||||
if (parse_client_port_config(ports,
|
||||
if (parse_port_config(ports,
|
||||
options->DNSPort, options->DNSListenAddress,
|
||||
"DNS", CONN_TYPE_AP_DNS_LISTENER,
|
||||
"127.0.0.1", 0,
|
||||
@ -5671,7 +5741,7 @@ parse_client_ports(const or_options_t *options, int validate_only,
|
||||
*msg = tor_strdup("Invalid DNSPort/DNSListenAddress configuration");
|
||||
goto err;
|
||||
}
|
||||
if (parse_client_port_config(ports,
|
||||
if (parse_port_config(ports,
|
||||
options->TransPort, options->TransListenAddress,
|
||||
"Trans", CONN_TYPE_AP_TRANS_LISTENER,
|
||||
"127.0.0.1", 0,
|
||||
@ -5679,7 +5749,7 @@ parse_client_ports(const or_options_t *options, int validate_only,
|
||||
*msg = tor_strdup("Invalid TransPort/TransListenAddress configuration");
|
||||
goto err;
|
||||
}
|
||||
if (parse_client_port_config(ports,
|
||||
if (parse_port_config(ports,
|
||||
options->NATDPort, options->NATDListenAddress,
|
||||
"NATD", CONN_TYPE_AP_NATD_LISTENER,
|
||||
"127.0.0.1", 0,
|
||||
@ -5687,16 +5757,63 @@ parse_client_ports(const or_options_t *options, int validate_only,
|
||||
*msg = tor_strdup("Invalid NatdPort/NatdListenAddress configuration");
|
||||
goto err;
|
||||
}
|
||||
{
|
||||
unsigned control_port_flags = CL_PORT_NO_OPTIONS | CL_PORT_WARN_NONLOCAL;
|
||||
const int any_passwords = (options->HashedControlPassword ||
|
||||
options->HashedControlSessionPassword ||
|
||||
options->CookieAuthentication);
|
||||
if (! any_passwords)
|
||||
control_port_flags |= CL_PORT_FORBID_NONLOCAL;
|
||||
|
||||
if (parse_port_config(ports,
|
||||
options->ControlPort, options->ControlListenAddress,
|
||||
"Control", CONN_TYPE_CONTROL_LISTENER,
|
||||
"127.0.0.1", 0,
|
||||
control_port_flags) < 0) {
|
||||
*msg = tor_strdup("Invalid ControlPort/ControlListenAddress "
|
||||
"configuration");
|
||||
goto err;
|
||||
}
|
||||
if (parse_socket_config(ports,
|
||||
options->ControlSocket,
|
||||
CONN_TYPE_CONTROL_LISTENER) < 0) {
|
||||
*msg = tor_strdup("Invalid ControlSocket configuration");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (! options->ClientOnly) {
|
||||
if (parse_port_config(ports,
|
||||
options->ORPort, options->ORListenAddress,
|
||||
"OR", CONN_TYPE_OR_LISTENER,
|
||||
"0.0.0.0", 0,
|
||||
CL_PORT_SERVER_OPTIONS) < 0) {
|
||||
*msg = tor_strdup("Invalid ORPort/ORListenAddress configuration");
|
||||
goto err;
|
||||
}
|
||||
if (parse_port_config(ports,
|
||||
options->DirPort, options->DirListenAddress,
|
||||
"Dir", CONN_TYPE_DIR_LISTENER,
|
||||
"0.0.0.0", 0,
|
||||
CL_PORT_SERVER_OPTIONS) < 0) {
|
||||
*msg = tor_strdup("Invalid DirPort/DirListenAddress configuration");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (check_server_ports(ports, options) < 0) {
|
||||
*msg = tor_strdup("Misconfigured server ports");
|
||||
goto err;
|
||||
}
|
||||
|
||||
*n_ports_out = smartlist_len(ports);
|
||||
|
||||
if (!validate_only) {
|
||||
if (configured_client_ports) {
|
||||
SMARTLIST_FOREACH(configured_client_ports,
|
||||
if (configured_ports) {
|
||||
SMARTLIST_FOREACH(configured_ports,
|
||||
port_cfg_t *, p, port_cfg_free(p));
|
||||
smartlist_free(configured_client_ports);
|
||||
smartlist_free(configured_ports);
|
||||
}
|
||||
configured_client_ports = ports;
|
||||
configured_ports = ports;
|
||||
ports = NULL; /* prevent free below. */
|
||||
}
|
||||
|
||||
@ -5709,14 +5826,107 @@ parse_client_ports(const or_options_t *options, int validate_only,
|
||||
return retval;
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
static int
|
||||
check_server_ports(const smartlist_t *ports,
|
||||
const or_options_t *options)
|
||||
{
|
||||
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 MS_WINDOWS
|
||||
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;
|
||||
}
|
||||
|
||||
/** Return a list of port_cfg_t for client ports parsed from the
|
||||
* options. */
|
||||
const smartlist_t *
|
||||
get_configured_client_ports(void)
|
||||
get_configured_ports(void)
|
||||
{
|
||||
if (!configured_client_ports)
|
||||
configured_client_ports = smartlist_create();
|
||||
return configured_client_ports;
|
||||
if (!configured_ports)
|
||||
configured_ports = smartlist_create();
|
||||
return configured_ports;
|
||||
}
|
||||
|
||||
/** Return the first advertised port of type <b>listener_type</b> in
|
||||
<b>address_family</b>. */
|
||||
int
|
||||
get_first_advertised_port_by_type_af(int listener_type, int address_family)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/** Adjust the value of options->DataDirectory, or fill it in if it's
|
||||
@ -6094,7 +6304,7 @@ init_libevent(const or_options_t *options)
|
||||
suppress_libevent_log_msg(NULL);
|
||||
|
||||
tor_check_libevent_version(tor_libevent_get_method(),
|
||||
get_options()->ORPort != 0,
|
||||
get_options()->ORPort != NULL,
|
||||
&badness);
|
||||
if (badness) {
|
||||
const char *v = tor_libevent_get_version_str();
|
||||
|
@ -64,7 +64,13 @@ or_state_t *get_or_state(void);
|
||||
int did_last_state_file_write_fail(void);
|
||||
int or_state_save(time_t now);
|
||||
|
||||
const smartlist_t *get_configured_client_ports(void);
|
||||
const smartlist_t *get_configured_ports(void);
|
||||
int get_first_advertised_port_by_type_af(int listener_type,
|
||||
int address_family);
|
||||
#define get_primary_or_port() \
|
||||
(get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER, AF_INET))
|
||||
#define get_primary_dir_port() \
|
||||
(get_first_advertised_port_by_type_af(CONN_TYPE_DIR_LISTENER, AF_INET))
|
||||
|
||||
int options_need_geoip_info(const or_options_t *options,
|
||||
const char **reason_out);
|
||||
|
@ -880,7 +880,8 @@ connection_create_listener(const struct sockaddr *listensockaddr,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (listensockaddr->sa_family == AF_INET) {
|
||||
if (listensockaddr->sa_family == AF_INET ||
|
||||
listensockaddr->sa_family == AF_INET6) {
|
||||
int is_tcp = (type != CONN_TYPE_AP_DNS_LISTENER);
|
||||
if (is_tcp)
|
||||
start_reading = 1;
|
||||
@ -890,7 +891,7 @@ connection_create_listener(const struct sockaddr *listensockaddr,
|
||||
log_notice(LD_NET, "Opening %s on %s:%d",
|
||||
conn_type_to_string(type), fmt_addr(&addr), usePort);
|
||||
|
||||
s = tor_open_socket(PF_INET,
|
||||
s = tor_open_socket(tor_addr_family(&addr),
|
||||
is_tcp ? SOCK_STREAM : SOCK_DGRAM,
|
||||
is_tcp ? IPPROTO_TCP: IPPROTO_UDP);
|
||||
if (!SOCKET_OK(s)) {
|
||||
@ -1814,6 +1815,9 @@ retry_listener_ports(smartlist_t *old_conns,
|
||||
(conn->socket_family == AF_UNIX && ! wanted->is_unix_addr))
|
||||
continue;
|
||||
|
||||
if (wanted->no_listen)
|
||||
continue; /* We don't want to open a listener for this one */
|
||||
|
||||
if (wanted->is_unix_addr) {
|
||||
if (conn->socket_family == AF_UNIX &&
|
||||
!strcmp(wanted->unix_addr, conn->address)) {
|
||||
@ -1852,6 +1856,8 @@ retry_listener_ports(smartlist_t *old_conns,
|
||||
connection_t *conn;
|
||||
int real_port = port->port == CFG_AUTO_PORT ? 0 : port->port;
|
||||
tor_assert(real_port <= UINT16_MAX);
|
||||
if (port->no_listen)
|
||||
continue;
|
||||
|
||||
if (port->is_unix_addr) {
|
||||
listensockaddr = (struct sockaddr *)
|
||||
@ -1888,82 +1894,6 @@ retry_listener_ports(smartlist_t *old_conns,
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch any configured listener connections of type <b>type</b>. (A
|
||||
* listener is configured if <b>port_option</b> is non-zero. If any
|
||||
* ListenAddress configuration options are given in <b>cfg</b>, create a
|
||||
* connection binding to each one. Otherwise, create a single
|
||||
* connection binding to the address <b>default_addr</b>.)
|
||||
*
|
||||
* We assume that we're starting with a list of existing listener connection_t
|
||||
* pointers in <b>old_conns</b>: we do not launch listeners that are already
|
||||
* in that list. Instead, we just remove them from the list.
|
||||
*
|
||||
* All new connections we launch are added to <b>new_conns</b>.
|
||||
*/
|
||||
static int
|
||||
retry_listeners(smartlist_t *old_conns,
|
||||
int type, const config_line_t *cfg,
|
||||
int port_option, const char *default_addr,
|
||||
smartlist_t *new_conns,
|
||||
int is_sockaddr_un)
|
||||
{
|
||||
smartlist_t *ports = smartlist_create();
|
||||
tor_addr_t dflt_addr;
|
||||
int retval = 0;
|
||||
|
||||
if (default_addr) {
|
||||
tor_addr_parse(&dflt_addr, default_addr);
|
||||
} else {
|
||||
tor_addr_make_unspec(&dflt_addr);
|
||||
}
|
||||
|
||||
if (port_option) {
|
||||
if (!cfg) {
|
||||
port_cfg_t *port = tor_malloc_zero(sizeof(port_cfg_t));
|
||||
tor_addr_copy(&port->addr, &dflt_addr);
|
||||
port->port = port_option;
|
||||
port->type = type;
|
||||
smartlist_add(ports, port);
|
||||
} else {
|
||||
const config_line_t *c;
|
||||
for (c = cfg; c; c = c->next) {
|
||||
port_cfg_t *port;
|
||||
tor_addr_t addr;
|
||||
uint16_t portval = 0;
|
||||
if (is_sockaddr_un) {
|
||||
size_t len = strlen(c->value);
|
||||
port = tor_malloc_zero(sizeof(port_cfg_t) + len + 1);
|
||||
port->is_unix_addr = 1;
|
||||
memcpy(port->unix_addr, c->value, len+1);
|
||||
} else {
|
||||
if (tor_addr_port_lookup(c->value, &addr, &portval) < 0) {
|
||||
log_warn(LD_CONFIG, "Can't parse/resolve %s %s",
|
||||
c->key, c->value);
|
||||
retval = -1;
|
||||
continue;
|
||||
}
|
||||
port = tor_malloc_zero(sizeof(port_cfg_t));
|
||||
tor_addr_copy(&port->addr, &addr);
|
||||
}
|
||||
port->type = type;
|
||||
port->port = portval ? portval : port_option;
|
||||
smartlist_add(ports, port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (retval == -1)
|
||||
goto cleanup;
|
||||
|
||||
retval = retry_listener_ports(old_conns, ports, new_conns);
|
||||
|
||||
cleanup:
|
||||
SMARTLIST_FOREACH(ports, port_cfg_t *, p, tor_free(p));
|
||||
smartlist_free(ports);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/** Launch listeners for each port you should have open. Only launch
|
||||
* listeners who are not already open, and only close listeners we no longer
|
||||
* want.
|
||||
@ -1986,37 +1916,9 @@ retry_all_listeners(smartlist_t *replaced_conns,
|
||||
smartlist_add(listeners, conn);
|
||||
} SMARTLIST_FOREACH_END(conn);
|
||||
|
||||
if (! options->ClientOnly && ! options->DisableNetwork) {
|
||||
if (retry_listeners(listeners,
|
||||
CONN_TYPE_OR_LISTENER, options->ORListenAddress,
|
||||
options->ORPort, "0.0.0.0",
|
||||
new_conns, 0) < 0)
|
||||
retval = -1;
|
||||
if (retry_listeners(listeners,
|
||||
CONN_TYPE_DIR_LISTENER, options->DirListenAddress,
|
||||
options->DirPort, "0.0.0.0",
|
||||
new_conns, 0) < 0)
|
||||
retval = -1;
|
||||
}
|
||||
|
||||
if (!options->DisableNetwork) {
|
||||
if (retry_listener_ports(listeners,
|
||||
get_configured_client_ports(),
|
||||
new_conns) < 0)
|
||||
retval = -1;
|
||||
}
|
||||
|
||||
if (retry_listeners(listeners,
|
||||
CONN_TYPE_CONTROL_LISTENER,
|
||||
options->ControlListenAddress,
|
||||
options->ControlPort, "127.0.0.1",
|
||||
new_conns, 0) < 0)
|
||||
retval = -1;
|
||||
if (retry_listeners(listeners,
|
||||
CONN_TYPE_CONTROL_LISTENER,
|
||||
options->ControlSocket,
|
||||
options->ControlSocket ? 1 : 0, NULL,
|
||||
new_conns, 1) < 0)
|
||||
if (retry_listener_ports(listeners,
|
||||
get_configured_ports(),
|
||||
new_conns) < 0)
|
||||
retval = -1;
|
||||
|
||||
/* Any members that were still in 'listeners' don't correspond to
|
||||
@ -2034,6 +1936,7 @@ retry_all_listeners(smartlist_t *replaced_conns,
|
||||
|
||||
smartlist_free(listeners);
|
||||
|
||||
/* XXXprop186 should take all advertised ports into account */
|
||||
if (old_or_port != router_get_advertised_or_port(options) ||
|
||||
old_dir_port != router_get_advertised_dir_port(options, 0)) {
|
||||
/* Our chosen ORPort or DirPort is not what it used to be: the
|
||||
|
@ -2593,7 +2593,7 @@ connection_ap_make_link(connection_t *partner,
|
||||
want_onehop ? "direct" : "anonymized",
|
||||
safe_str_client(address), port);
|
||||
|
||||
conn = entry_connection_new(CONN_TYPE_AP, AF_INET);
|
||||
conn = entry_connection_new(CONN_TYPE_AP, tor_addr_family(&partner->addr));
|
||||
base_conn = ENTRY_TO_CONN(conn);
|
||||
base_conn->linked = 1; /* so that we can add it safely below. */
|
||||
|
||||
@ -3199,7 +3199,7 @@ connection_exit_connect_dir(edge_connection_t *exitconn)
|
||||
|
||||
exitconn->_base.state = EXIT_CONN_STATE_OPEN;
|
||||
|
||||
dirconn = dir_connection_new(AF_INET);
|
||||
dirconn = dir_connection_new(tor_addr_family(&exitconn->_base.addr));
|
||||
|
||||
tor_addr_copy(&dirconn->_base.addr, &exitconn->_base.addr);
|
||||
dirconn->_base.port = 0;
|
||||
|
@ -630,7 +630,9 @@ connection_or_update_token_buckets(smartlist_t *conns,
|
||||
|
||||
/** If we don't necessarily know the router we're connecting to, but we
|
||||
* have an addr/port/id_digest, then fill in as much as we can. Start
|
||||
* by checking to see if this describes a router we know. */
|
||||
* by checking to see if this describes a router we know.
|
||||
* <b>started_here</b> is 1 if we are the initiator of <b>conn</b> and
|
||||
* 0 if it's an incoming connection. */
|
||||
void
|
||||
connection_or_init_conn_from_address(or_connection_t *conn,
|
||||
const tor_addr_t *addr, uint16_t port,
|
||||
@ -645,10 +647,11 @@ connection_or_init_conn_from_address(or_connection_t *conn,
|
||||
tor_addr_copy(&conn->_base.addr, addr);
|
||||
tor_addr_copy(&conn->real_addr, addr);
|
||||
if (r) {
|
||||
tor_addr_t node_addr;
|
||||
node_get_addr(r, &node_addr);
|
||||
/* XXXX proposal 118 will make this more complex. */
|
||||
if (tor_addr_eq(&conn->_base.addr, &node_addr))
|
||||
tor_addr_port_t node_ap;
|
||||
node_get_pref_orport(r, &node_ap);
|
||||
/* XXXX proposal 186 is making this more complex. For now, a conn
|
||||
is canonical when it uses the _preferred_ address. */
|
||||
if (tor_addr_eq(&conn->_base.addr, &node_ap.addr))
|
||||
conn->is_canonical = 1;
|
||||
if (!started_here) {
|
||||
/* Override the addr/port, so our log messages will make sense.
|
||||
@ -661,12 +664,12 @@ connection_or_init_conn_from_address(or_connection_t *conn,
|
||||
* right IP address and port 56244, that wouldn't be as helpful. now we
|
||||
* log the "right" port too, so we know if it's moria1 or moria2.
|
||||
*/
|
||||
tor_addr_copy(&conn->_base.addr, &node_addr);
|
||||
conn->_base.port = node_get_orport(r);
|
||||
tor_addr_copy(&conn->_base.addr, &node_ap.addr);
|
||||
conn->_base.port = node_ap.port;
|
||||
}
|
||||
conn->nickname = tor_strdup(node_get_nickname(r));
|
||||
tor_free(conn->_base.address);
|
||||
conn->_base.address = tor_dup_addr(&node_addr);
|
||||
conn->_base.address = tor_dup_addr(&node_ap.addr);
|
||||
} else {
|
||||
const char *n;
|
||||
/* If we're an authoritative directory server, we may know a
|
||||
@ -1033,7 +1036,7 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
conn = or_connection_new(AF_INET);
|
||||
conn = or_connection_new(tor_addr_family(&addr));
|
||||
|
||||
/* set up conn so it's got all the data we need to remember */
|
||||
connection_or_init_conn_from_address(conn, &addr, port, id_digest, 1);
|
||||
|
@ -2402,7 +2402,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
|
||||
/* now circ refers to something that is ready to be extended */
|
||||
SMARTLIST_FOREACH(nodes, const node_t *, node,
|
||||
{
|
||||
extend_info_t *info = extend_info_from_node(node);
|
||||
extend_info_t *info = extend_info_from_node(node, 0);
|
||||
tor_assert(info); /* True, since node_has_descriptor(node) == true */
|
||||
circuit_append_new_exit(circ, info);
|
||||
extend_info_free(info);
|
||||
|
@ -919,7 +919,7 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
|
||||
return;
|
||||
}
|
||||
|
||||
conn = dir_connection_new(AF_INET);
|
||||
conn = dir_connection_new(tor_addr_family(&addr));
|
||||
|
||||
/* set up conn so it's got all the data we need to remember */
|
||||
tor_addr_copy(&conn->_base.addr, &addr);
|
||||
@ -1619,9 +1619,11 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
|
||||
if (!reason) reason = tor_strdup("[no reason given]");
|
||||
|
||||
log_debug(LD_DIR,
|
||||
"Received response from directory server '%s:%d': %d %s",
|
||||
"Received response from directory server '%s:%d': %d %s "
|
||||
"(purpose: %d)",
|
||||
conn->_base.address, conn->_base.port, status_code,
|
||||
escaped(reason));
|
||||
escaped(reason),
|
||||
conn->_base.purpose);
|
||||
|
||||
/* now check if it's got any hints for us about our IP address. */
|
||||
if (conn->dirconn_direct) {
|
||||
@ -3729,7 +3731,7 @@ download_status_reset(download_status_t *dls)
|
||||
const int *schedule;
|
||||
size_t schedule_len;
|
||||
|
||||
find_dl_schedule_and_len(dls, get_options()->DirPort,
|
||||
find_dl_schedule_and_len(dls, get_options()->DirPort != NULL,
|
||||
&schedule, &schedule_len);
|
||||
|
||||
dls->n_download_failures = 0;
|
||||
|
@ -80,7 +80,7 @@ time_t download_status_increment_failure(download_status_t *dls,
|
||||
* the optional status code <b>sc</b>. */
|
||||
#define download_status_failed(dls, sc) \
|
||||
download_status_increment_failure((dls), (sc), NULL, \
|
||||
get_options()->DirPort, time(NULL))
|
||||
get_options()->DirPort!=NULL, time(NULL))
|
||||
|
||||
void download_status_reset(download_status_t *dls);
|
||||
static int download_status_is_ready(download_status_t *dls, time_t now,
|
||||
|
@ -1212,7 +1212,7 @@ directory_fetches_from_authorities(const or_options_t *options)
|
||||
return 1; /* we don't know our IP address; ask an authority. */
|
||||
refuseunknown = ! router_my_exit_policy_is_reject_star() &&
|
||||
should_refuse_unknown_exits(options);
|
||||
if (options->DirPort == 0 && !refuseunknown)
|
||||
if (options->DirPort == NULL && !refuseunknown)
|
||||
return 0;
|
||||
if (!server_mode(options) || !advertised_server_mode())
|
||||
return 0;
|
||||
@ -1248,7 +1248,7 @@ directory_fetches_dir_info_later(const or_options_t *options)
|
||||
int
|
||||
directory_caches_v2_dir_info(const or_options_t *options)
|
||||
{
|
||||
return options->DirPort != 0;
|
||||
return options->DirPort != NULL;
|
||||
}
|
||||
|
||||
/** Return 1 if we want to keep descriptors, networkstatuses, etc around
|
||||
@ -1273,7 +1273,7 @@ directory_caches_dir_info(const or_options_t *options)
|
||||
int
|
||||
directory_permits_begindir_requests(const or_options_t *options)
|
||||
{
|
||||
return options->BridgeRelay != 0 || options->DirPort != 0;
|
||||
return options->BridgeRelay != 0 || options->DirPort != NULL;
|
||||
}
|
||||
|
||||
/** Return 1 if we want to allow controllers to ask us directory
|
||||
@ -1282,7 +1282,7 @@ directory_permits_begindir_requests(const or_options_t *options)
|
||||
int
|
||||
directory_permits_controller_requests(const or_options_t *options)
|
||||
{
|
||||
return options->DirPort != 0;
|
||||
return options->DirPort != NULL;
|
||||
}
|
||||
|
||||
/** Return 1 if we have no need to fetch new descriptors. This generally
|
||||
|
@ -1511,9 +1511,10 @@ run_scheduled_events(time_t now)
|
||||
options->PortForwarding &&
|
||||
is_server) {
|
||||
#define PORT_FORWARDING_CHECK_INTERVAL 5
|
||||
/* XXXXX this should take a list of ports, not just two! */
|
||||
tor_check_port_forwarding(options->PortForwardingHelper,
|
||||
options->DirPort,
|
||||
options->ORPort,
|
||||
get_primary_dir_port(),
|
||||
get_primary_or_port(),
|
||||
now);
|
||||
time_to_check_port_forwarding = now+PORT_FORWARDING_CHECK_INTERVAL;
|
||||
}
|
||||
|
@ -646,24 +646,70 @@ node_exit_policy_rejects_all(const node_t *node)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Copy the address for <b>node</b> into *<b>addr_out</b>. */
|
||||
int
|
||||
node_get_addr(const node_t *node, tor_addr_t *addr_out)
|
||||
/** Return list of tor_addr_port_t with all OR ports (in the sense IP
|
||||
* addr + TCP port) for <b>node</b>. Caller must free all elements
|
||||
* using tor_free() and free the list using smartlist_free().
|
||||
*
|
||||
* XXX this is potentially a memory fragmentation hog -- if on
|
||||
* critical path consider the option of having the caller allocate the
|
||||
* memory
|
||||
*/
|
||||
smartlist_t *
|
||||
node_get_all_orports(const node_t *node)
|
||||
{
|
||||
smartlist_t *sl = smartlist_create();
|
||||
|
||||
if (node->ri != NULL) {
|
||||
if (node->ri->addr != 0) {
|
||||
tor_addr_port_t *ap = tor_malloc(sizeof(tor_addr_port_t));
|
||||
tor_addr_from_ipv4h(&ap->addr, node->ri->addr);
|
||||
ap->port = node->ri->or_port;
|
||||
smartlist_add(sl, ap);
|
||||
}
|
||||
if (!tor_addr_is_null(&node->ri->ipv6_addr)) {
|
||||
tor_addr_port_t *ap = tor_malloc(sizeof(tor_addr_port_t));
|
||||
tor_addr_copy(&ap->addr, &node->ri->ipv6_addr);
|
||||
ap->port = node->ri->or_port;
|
||||
smartlist_add(sl, ap);
|
||||
}
|
||||
} else if (node->rs != NULL) {
|
||||
tor_addr_port_t *ap = tor_malloc(sizeof(tor_addr_port_t));
|
||||
tor_addr_from_ipv4h(&ap->addr, node->rs->addr);
|
||||
ap->port = node->rs->or_port;
|
||||
smartlist_add(sl, ap);
|
||||
}
|
||||
|
||||
return sl;
|
||||
}
|
||||
|
||||
/** Copy the primary (IPv4) OR port (IP address and TCP port) for
|
||||
* <b>node</b> into *<b>ap_out</b>. */
|
||||
void
|
||||
node_get_prim_orport(const node_t *node, tor_addr_port_t *ap_out)
|
||||
{
|
||||
if (node->ri) {
|
||||
tor_addr_from_ipv4h(addr_out, node->ri->addr);
|
||||
return 0;
|
||||
} else if (node->rs) {
|
||||
tor_addr_from_ipv4h(addr_out, node->rs->addr);
|
||||
return 0;
|
||||
router_get_prim_orport(node->ri, ap_out);
|
||||
}
|
||||
return -1;
|
||||
else if (node->rs) {
|
||||
tor_addr_from_ipv4h(&ap_out->addr, node->rs->addr);
|
||||
ap_out->port = node->rs->or_port;
|
||||
}
|
||||
}
|
||||
|
||||
/** Wrapper around node_get_prim_orport for backward
|
||||
compatibility. */
|
||||
void
|
||||
node_get_addr(const node_t *node, tor_addr_t *addr_out)
|
||||
{
|
||||
tor_addr_port_t ap;
|
||||
node_get_prim_orport(node, &ap);
|
||||
tor_addr_copy(addr_out, &ap.addr);
|
||||
}
|
||||
|
||||
/** Return the host-order IPv4 address for <b>node</b>, or 0 if it doesn't
|
||||
* seem to have one. */
|
||||
uint32_t
|
||||
node_get_addr_ipv4h(const node_t *node)
|
||||
node_get_prim_addr_ipv4h(const node_t *node)
|
||||
{
|
||||
if (node->ri) {
|
||||
return node->ri->addr;
|
||||
@ -673,9 +719,38 @@ node_get_addr_ipv4h(const node_t *node)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Copy a string representation of the IP address for <b>node</b> into the
|
||||
* <b>len</b>-byte buffer at <b>buf</b>.
|
||||
*/
|
||||
/** Copy the preferred OR port (IP address and TCP port) for
|
||||
* <b>node</b> into <b>ap_out</b>. */
|
||||
void
|
||||
node_get_pref_orport(const node_t *node, tor_addr_port_t *ap_out)
|
||||
{
|
||||
if (node->ri) {
|
||||
router_get_pref_orport(node->ri, ap_out);
|
||||
} else if (node->rs) {
|
||||
/* No IPv6 in routerstatus_t yet. XXXprop186 ok for private
|
||||
bridges but needs fixing */
|
||||
tor_addr_from_ipv4h(&ap_out->addr, node->rs->addr);
|
||||
ap_out->port = node->rs->or_port;
|
||||
}
|
||||
}
|
||||
|
||||
/** Copy the preferred IPv6 OR port (address and TCP port) for
|
||||
* <b>node</b> into *<b>ap_out</b>. */
|
||||
void
|
||||
node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out)
|
||||
{
|
||||
if (node->ri) {
|
||||
router_get_pref_ipv6_orport(node->ri, ap_out);
|
||||
} else if (node->rs) {
|
||||
/* No IPv6 in routerstatus_t yet. XXXprop186 ok for private
|
||||
bridges but needs fixing */
|
||||
tor_addr_make_unspec(&ap_out->addr);
|
||||
ap_out->port = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Copy a string representation of an IP address for <b>node</b> into
|
||||
* the <b>len</b>-byte buffer at <b>buf</b>. */
|
||||
void
|
||||
node_get_address_string(const node_t *node, char *buf, size_t len)
|
||||
{
|
||||
@ -701,18 +776,6 @@ node_get_declared_uptime(const node_t *node)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Return <b>node</b>'s declared or_port */
|
||||
uint16_t
|
||||
node_get_orport(const node_t *node)
|
||||
{
|
||||
if (node->ri)
|
||||
return node->ri->or_port;
|
||||
else if (node->rs)
|
||||
return node->rs->or_port;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return <b>node</b>'s platform string, or NULL if we don't know it. */
|
||||
const char *
|
||||
node_get_platform(const node_t *node)
|
||||
|
@ -37,10 +37,13 @@ int node_get_purpose(const node_t *node);
|
||||
(node_get_purpose((node)) == ROUTER_PURPOSE_BRIDGE)
|
||||
int node_is_me(const node_t *node);
|
||||
int node_exit_policy_rejects_all(const node_t *node);
|
||||
int node_get_addr(const node_t *node, tor_addr_t *addr_out);
|
||||
uint32_t node_get_addr_ipv4h(const node_t *node);
|
||||
smartlist_t *node_get_all_orports(const node_t *node);
|
||||
void node_get_prim_orport(const node_t *node, tor_addr_port_t *addr_port_out);
|
||||
void node_get_pref_orport(const node_t *node, tor_addr_port_t *addr_port_out);
|
||||
void node_get_pref_ipv6_orport(const node_t *node,
|
||||
tor_addr_port_t *addr_port_out);
|
||||
uint32_t node_get_prim_addr_ipv4h(const node_t *node);
|
||||
int node_allows_single_hop_exits(const node_t *node);
|
||||
uint16_t node_get_orport(const node_t *node);
|
||||
const char *node_get_nickname(const node_t *node);
|
||||
const char *node_get_platform(const node_t *node);
|
||||
void node_get_address_string(const node_t *node, char *cp, size_t len);
|
||||
@ -50,6 +53,10 @@ const smartlist_t *node_get_declared_family(const node_t *node);
|
||||
|
||||
smartlist_t *nodelist_get_list(void);
|
||||
|
||||
/* Temporary during transition to multiple addresses. */
|
||||
void node_get_addr(const node_t *node, tor_addr_t *addr_out);
|
||||
#define node_get_addr_ipv4h(n) node_get_prim_addr_ipv4h((n))
|
||||
|
||||
/* XXXX These need to move out of routerlist.c */
|
||||
void nodelist_refresh_countries(void);
|
||||
void node_set_country(node_t *node);
|
||||
|
22
src/or/or.h
22
src/or/or.h
@ -1722,6 +1722,13 @@ typedef struct {
|
||||
uint16_t or_port; /**< Port for TLS connections. */
|
||||
uint16_t dir_port; /**< Port for HTTP directory connections. */
|
||||
|
||||
/* DOCDOC */
|
||||
/* XXXXX187 Actually these should probably be part of a list of addresses,
|
||||
* not just a special case. Use abstractions to access these; don't do it
|
||||
* directly. */
|
||||
tor_addr_t ipv6_addr;
|
||||
uint16_t ipv6_orport;
|
||||
|
||||
crypto_pk_env_t *onion_pkey; /**< Public RSA key for onions. */
|
||||
crypto_pk_env_t *identity_pkey; /**< Public RSA key for signing. */
|
||||
|
||||
@ -1753,6 +1760,8 @@ typedef struct {
|
||||
/** True if, after we have added this router, we should re-launch
|
||||
* tests for it. */
|
||||
unsigned int needs_retest_if_added:1;
|
||||
/** True if ipv6_addr:ipv6_orport is preferred. */
|
||||
unsigned int ipv6_preferred:1;
|
||||
|
||||
/** Tor can use this router for general positions in circuits; we got it
|
||||
* from a directory server as usual, or we're an authority and a server
|
||||
@ -2833,6 +2842,13 @@ typedef struct port_cfg_t {
|
||||
int session_group; /**< A session group, or -1 if this port is not in a
|
||||
* session group. */
|
||||
|
||||
/* Server port types (or, dir) only: */
|
||||
unsigned int no_advertise : 1;
|
||||
unsigned int no_listen : 1;
|
||||
unsigned int all_addrs : 1;
|
||||
unsigned int ipv4_only : 1;
|
||||
unsigned int ipv6_only : 1;
|
||||
|
||||
/* Unix sockets only: */
|
||||
/** Path for an AF_UNIX address */
|
||||
char unix_addr[FLEXIBLE_ARRAY_MEMBER];
|
||||
@ -2948,17 +2964,17 @@ typedef struct {
|
||||
int DirAllowPrivateAddresses;
|
||||
char *User; /**< Name of user to run Tor as. */
|
||||
char *Group; /**< Name of group to run Tor as. */
|
||||
int ORPort; /**< Port to listen on for OR connections. */
|
||||
config_line_t *ORPort; /**< Ports to listen on for OR connections. */
|
||||
config_line_t *SocksPort; /**< Ports to listen on for SOCKS connections. */
|
||||
/** Ports to listen on for transparent pf/netfilter connections. */
|
||||
config_line_t *TransPort;
|
||||
config_line_t *NATDPort; /**< Ports to listen on for transparent natd
|
||||
* connections. */
|
||||
int ControlPort; /**< Port to listen on for control connections. */
|
||||
config_line_t *ControlPort; /**< Port to listen on for control connections. */
|
||||
config_line_t *ControlSocket; /**< List of Unix Domain Sockets to listen on
|
||||
* for control connections. */
|
||||
int ControlSocketsGroupWritable; /**< Boolean: Are control sockets g+rw? */
|
||||
int DirPort; /**< Port to listen on for directory connections. */
|
||||
config_line_t *DirPort; /**< Port to listen on for directory connections. */
|
||||
config_line_t *DNSPort; /**< Port to listen on for DNS requests. */
|
||||
int AssumeReachable; /**< Whether to publish our descriptor regardless. */
|
||||
int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */
|
||||
|
@ -1059,7 +1059,7 @@ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry,
|
||||
smartlist_del(usable_nodes, i);
|
||||
goto again;
|
||||
}
|
||||
new_extend_info = extend_info_from_node(node);
|
||||
new_extend_info = extend_info_from_node(node, 0);
|
||||
if (!new_extend_info) {
|
||||
log_info(LD_REND, "We don't have a descriptor for the intro-point relay "
|
||||
"'%s'; trying another.",
|
||||
|
@ -1142,7 +1142,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
|
||||
goto err;
|
||||
}
|
||||
|
||||
extend_info = extend_info_from_node(node);
|
||||
extend_info = extend_info_from_node(node, 0);
|
||||
}
|
||||
|
||||
if (len != REND_COOKIE_LEN+DH_KEY_LEN) {
|
||||
@ -2151,7 +2151,7 @@ rend_services_introduce(void)
|
||||
intro_point_set_changed = 1;
|
||||
smartlist_add(intro_nodes, (void*)node);
|
||||
intro = tor_malloc_zero(sizeof(rend_intro_point_t));
|
||||
intro->extend_info = extend_info_from_node(node);
|
||||
intro->extend_info = extend_info_from_node(node, 0);
|
||||
intro->intro_key = crypto_new_pk_env();
|
||||
tor_assert(!crypto_pk_generate_key(intro->intro_key));
|
||||
intro->time_published = -1;
|
||||
|
113
src/or/router.c
113
src/or/router.c
@ -893,7 +893,8 @@ consider_testing_reachability(int test_or, int test_dir)
|
||||
log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.",
|
||||
!orport_reachable ? "reachability" : "bandwidth",
|
||||
me->address, me->or_port);
|
||||
ei = extend_info_from_router(me);
|
||||
/* XXX IPv6 self testing IPv6 orports will need pref_addr */
|
||||
ei = extend_info_from_router(me, 0);
|
||||
circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
|
||||
CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
|
||||
extend_info_free(ei);
|
||||
@ -1083,7 +1084,7 @@ int
|
||||
server_mode(const or_options_t *options)
|
||||
{
|
||||
if (options->ClientOnly) return 0;
|
||||
return (options->ORPort != 0 || options->ORListenAddress);
|
||||
return (options->ORPort || options->ORListenAddress);
|
||||
}
|
||||
|
||||
/** Return true iff we are trying to be a non-bridge server.
|
||||
@ -1134,7 +1135,14 @@ int
|
||||
proxy_mode(const or_options_t *options)
|
||||
{
|
||||
(void)options;
|
||||
return smartlist_len(get_configured_client_ports()) > 0;
|
||||
SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) {
|
||||
if (p->type == CONN_TYPE_AP_LISTENER ||
|
||||
p->type == CONN_TYPE_AP_TRANS_LISTENER ||
|
||||
p->type == CONN_TYPE_AP_DNS_LISTENER ||
|
||||
p->type == CONN_TYPE_AP_NATD_LISTENER)
|
||||
return 1;
|
||||
} SMARTLIST_FOREACH_END(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Decide if we're a publishable server. We are a publishable server if:
|
||||
@ -1193,17 +1201,21 @@ consider_publishable_server(int force)
|
||||
|
||||
/** Return the port that we should advertise as our ORPort; this is either
|
||||
* the one configured in the ORPort option, or the one we actually bound to
|
||||
* if ORPort is "auto". */
|
||||
* if ORPort is "auto".
|
||||
*/
|
||||
uint16_t
|
||||
router_get_advertised_or_port(const or_options_t *options)
|
||||
{
|
||||
if (options->ORPort == CFG_AUTO_PORT) {
|
||||
int port = get_primary_or_port();
|
||||
(void)options;
|
||||
|
||||
if (port == CFG_AUTO_PORT) {
|
||||
connection_t *c = connection_get_by_type(CONN_TYPE_OR_LISTENER);
|
||||
if (c)
|
||||
return c->port;
|
||||
return 0;
|
||||
}
|
||||
return options->ORPort;
|
||||
return port;
|
||||
}
|
||||
|
||||
/** Return the port that we should advertise as our DirPort;
|
||||
@ -1214,15 +1226,18 @@ router_get_advertised_or_port(const or_options_t *options)
|
||||
uint16_t
|
||||
router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport)
|
||||
{
|
||||
if (!options->DirPort)
|
||||
int dirport_configured = get_primary_dir_port();
|
||||
(void)options;
|
||||
|
||||
if (!dirport_configured)
|
||||
return dirport;
|
||||
if (options->DirPort == CFG_AUTO_PORT) {
|
||||
if (dirport_configured == CFG_AUTO_PORT) {
|
||||
connection_t *c = connection_get_by_type(CONN_TYPE_DIR_LISTENER);
|
||||
if (c)
|
||||
return c->port;
|
||||
return 0;
|
||||
}
|
||||
return options->DirPort;
|
||||
return dirport_configured;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1479,6 +1494,24 @@ router_rebuild_descriptor(int force)
|
||||
ri->cache_info.published_on = time(NULL);
|
||||
ri->onion_pkey = crypto_pk_dup_key(get_onion_key()); /* must invoke from
|
||||
* main thread */
|
||||
if (options->BridgeRelay) {
|
||||
/* For now, only bridges advertise an ipv6 or-address. And only one. */
|
||||
const port_cfg_t *ipv6_orport = NULL;
|
||||
SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) {
|
||||
if (p->type == CONN_TYPE_OR_LISTENER &&
|
||||
! p->no_advertise &&
|
||||
! p->ipv4_only &&
|
||||
tor_addr_family(&p->addr) == AF_INET6 &&
|
||||
! tor_addr_is_internal(&p->addr, 1)) {
|
||||
ipv6_orport = p;
|
||||
break;
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(p);
|
||||
if (ipv6_orport) {
|
||||
tor_addr_copy(&ri->ipv6_addr, &ipv6_orport->addr);
|
||||
ri->ipv6_orport = ipv6_orport->port;
|
||||
}
|
||||
}
|
||||
ri->identity_pkey = crypto_pk_dup_key(get_server_identity_key());
|
||||
if (crypto_pk_get_digest(ri->identity_pkey,
|
||||
ri->cache_info.identity_digest)<0) {
|
||||
@ -1888,6 +1921,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
|
||||
int result=0;
|
||||
addr_policy_t *tmpe;
|
||||
char *family_line;
|
||||
char *extra_or_address = NULL;
|
||||
const or_options_t *options = get_options();
|
||||
|
||||
/* Make sure the identity key matches the one in the routerinfo. */
|
||||
@ -1940,9 +1974,22 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
|
||||
router->cache_info.extra_info_digest, DIGEST_LEN);
|
||||
}
|
||||
|
||||
if (router->ipv6_orport &&
|
||||
tor_addr_family(&router->ipv6_addr) == AF_INET6) {
|
||||
char addr[TOR_ADDR_BUF_LEN];
|
||||
const char *a;
|
||||
a = tor_addr_to_str(addr, &router->ipv6_addr, sizeof(addr), 1);
|
||||
if (a) {
|
||||
tor_asprintf(&extra_or_address,
|
||||
"or-address %s:%d\n", a, router->ipv6_orport);
|
||||
log_notice(LD_OR, "My line is <%s>", extra_or_address);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate the easy portion of the router descriptor. */
|
||||
result = tor_snprintf(s, maxlen,
|
||||
"router %s %s %d 0 %d\n"
|
||||
"%s"
|
||||
"platform %s\n"
|
||||
"opt protocols Link 1 2 Circuit 1\n"
|
||||
"published %s\n"
|
||||
@ -1957,6 +2004,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
|
||||
router->address,
|
||||
router->or_port,
|
||||
decide_to_advertise_dirport(options, router->dir_port),
|
||||
extra_or_address ? extra_or_address : "",
|
||||
router->platform,
|
||||
published,
|
||||
fingerprint,
|
||||
@ -1977,6 +2025,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
|
||||
tor_free(family_line);
|
||||
tor_free(onion_pkey);
|
||||
tor_free(identity_pkey);
|
||||
tor_free(extra_or_address);
|
||||
|
||||
if (result < 0) {
|
||||
log_warn(LD_BUG,"descriptor snprintf #1 ran out of room!");
|
||||
@ -2072,6 +2121,52 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
|
||||
return (int)written+1;
|
||||
}
|
||||
|
||||
/** Copy the primary (IPv4) OR port (IP address and TCP port) for
|
||||
* <b>router</b> into *<b>ap_out</b>. */
|
||||
void
|
||||
router_get_prim_orport(const routerinfo_t *router, tor_addr_port_t *ap_out)
|
||||
{
|
||||
tor_assert(ap_out != NULL);
|
||||
tor_addr_from_ipv4h(&ap_out->addr, router->addr);
|
||||
ap_out->port = router->or_port;
|
||||
}
|
||||
|
||||
/** Return 1 if we prefer the IPv6 address and OR TCP port of
|
||||
* <b>router</b>, else 0.
|
||||
*
|
||||
* We prefer the IPv6 address if the router has one and
|
||||
* i) the routerinfo_t says so
|
||||
* or
|
||||
* ii) the router has no IPv4 address. */
|
||||
int
|
||||
router_ipv6_preferred(const routerinfo_t *router)
|
||||
{
|
||||
return (!tor_addr_is_null(&router->ipv6_addr)
|
||||
&& (router->ipv6_preferred || router->addr == 0));
|
||||
}
|
||||
|
||||
/** Copy the preferred OR port (IP address and TCP port) for
|
||||
* <b>router</b> into *<b>addr_out</b>. */
|
||||
void
|
||||
router_get_pref_orport(const routerinfo_t *router, tor_addr_port_t *ap_out)
|
||||
{
|
||||
if (router_ipv6_preferred(router))
|
||||
router_get_pref_ipv6_orport(router, ap_out);
|
||||
else
|
||||
router_get_prim_orport(router, ap_out);
|
||||
}
|
||||
|
||||
/** Copy the preferred IPv6 OR port (IP address and TCP port) for
|
||||
* <b>router</b> into *<b>ap_out</b>. */
|
||||
void
|
||||
router_get_pref_ipv6_orport(const routerinfo_t *router,
|
||||
tor_addr_port_t *ap_out)
|
||||
{
|
||||
tor_assert(ap_out != NULL);
|
||||
tor_addr_copy(&ap_out->addr, &router->ipv6_addr);
|
||||
ap_out->port = router->ipv6_orport;
|
||||
}
|
||||
|
||||
/** Load the contents of <b>filename</b>, find the last line starting with
|
||||
* <b>end_line</b>, ensure that its timestamp is not more than 25 hours in
|
||||
* the past or more than 1 hour in the future with respect to <b>now</b>,
|
||||
|
@ -85,6 +85,13 @@ int router_pick_published_address(const or_options_t *options, uint32_t *addr);
|
||||
int router_rebuild_descriptor(int force);
|
||||
int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
|
||||
crypto_pk_env_t *ident_key);
|
||||
void router_get_prim_orport(const routerinfo_t *router,
|
||||
tor_addr_port_t *addr_port_out);
|
||||
void router_get_pref_orport(const routerinfo_t *router,
|
||||
tor_addr_port_t *addr_port_out);
|
||||
void router_get_pref_ipv6_orport(const routerinfo_t *router,
|
||||
tor_addr_port_t *addr_port_out);
|
||||
int router_ipv6_preferred(const routerinfo_t *router);
|
||||
int extrainfo_dump_to_string(char **s, extrainfo_t *extrainfo,
|
||||
crypto_pk_env_t *ident_key);
|
||||
int is_legal_nickname(const char *s);
|
||||
|
@ -64,6 +64,7 @@ typedef enum {
|
||||
K_DIR_OPTIONS,
|
||||
K_CLIENT_VERSIONS,
|
||||
K_SERVER_VERSIONS,
|
||||
K_OR_ADDRESS,
|
||||
K_P,
|
||||
K_R,
|
||||
K_S,
|
||||
@ -286,6 +287,7 @@ static token_rule_t routerdesc_token_table[] = {
|
||||
|
||||
T01("family", K_FAMILY, ARGS, NO_OBJ ),
|
||||
T01("caches-extra-info", K_CACHES_EXTRA_INFO, NO_ARGS, NO_OBJ ),
|
||||
T0N("or-address", K_OR_ADDRESS, GE(1), NO_OBJ ),
|
||||
|
||||
T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
|
||||
T1( "bandwidth", K_BANDWIDTH, GE(3), NO_OBJ ),
|
||||
@ -541,6 +543,7 @@ static int router_get_hashes_impl(const char *s, size_t s_len,
|
||||
const char *start_str, const char *end_str,
|
||||
char end_char);
|
||||
static void token_clear(directory_token_t *tok);
|
||||
static smartlist_t *find_all_by_keyword(smartlist_t *s, directory_keyword k);
|
||||
static smartlist_t *find_all_exitpolicy(smartlist_t *s);
|
||||
static directory_token_t *_find_by_keyword(smartlist_t *s,
|
||||
directory_keyword keyword,
|
||||
@ -1506,6 +1509,27 @@ router_parse_entry_from_string(const char *s, const char *end,
|
||||
"older Tors.");
|
||||
goto err;
|
||||
}
|
||||
{
|
||||
smartlist_t *or_addresses = find_all_by_keyword(tokens, K_OR_ADDRESS);
|
||||
if (or_addresses) {
|
||||
SMARTLIST_FOREACH_BEGIN(or_addresses, directory_token_t *, t) {
|
||||
tor_addr_t a;
|
||||
maskbits_t bits;
|
||||
uint16_t port_min, port_max;
|
||||
/* XXXX Prop186 the full spec allows much more than this. */
|
||||
if (tor_addr_parse_mask_ports(t->args[0], &a, &bits, &port_min,
|
||||
&port_max) == AF_INET6 &&
|
||||
bits == 128 &&
|
||||
port_min == port_max) {
|
||||
/* Okay, this is one we can understand. */
|
||||
tor_addr_copy(&router->ipv6_addr, &a);
|
||||
router->ipv6_orport = port_min;
|
||||
break;
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(t);
|
||||
smartlist_free(or_addresses);
|
||||
}
|
||||
}
|
||||
exit_policy_tokens = find_all_exitpolicy(tokens);
|
||||
if (!smartlist_len(exit_policy_tokens)) {
|
||||
log_warn(LD_DIR, "No exit policy tokens in descriptor.");
|
||||
@ -4134,6 +4158,20 @@ _find_by_keyword(smartlist_t *s, directory_keyword keyword,
|
||||
return tok;
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
static smartlist_t *
|
||||
find_all_by_keyword(smartlist_t *s, directory_keyword k)
|
||||
{
|
||||
smartlist_t *out = NULL;
|
||||
SMARTLIST_FOREACH(s, directory_token_t *, t,
|
||||
if (t->tp == k) {
|
||||
if (!out)
|
||||
out = smartlist_create();
|
||||
smartlist_add(out, t);
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
/** Return a newly allocated smartlist of all accept or reject tokens in
|
||||
* <b>s</b>.
|
||||
*/
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "circuitbuild.h"
|
||||
#include "transports.h"
|
||||
#include "util.h"
|
||||
#include "router.h"
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
static void set_managed_proxy_environment(LPVOID *envp,
|
||||
@ -1079,7 +1080,8 @@ set_managed_proxy_environment(char ***envp, const managed_proxy_t *mp)
|
||||
bindaddr = get_bindaddr_for_proxy(mp);
|
||||
|
||||
/* XXX temp */
|
||||
tor_asprintf(tmp++, "TOR_PT_ORPORT=127.0.0.1:%d", options->ORPort);
|
||||
tor_asprintf(tmp++, "TOR_PT_ORPORT=127.0.0.1:%d",
|
||||
router_get_advertised_or_port(options));
|
||||
tor_asprintf(tmp++, "TOR_PT_SERVER_BINDADDR=%s", bindaddr);
|
||||
tor_asprintf(tmp++, "TOR_PT_SERVER_TRANSPORTS=%s", transports_to_launch);
|
||||
/* XXX temp*/
|
||||
|
@ -96,6 +96,8 @@ test_dir_formats(void)
|
||||
r1->cache_info.published_on = 0;
|
||||
r1->or_port = 9000;
|
||||
r1->dir_port = 9003;
|
||||
tor_addr_parse(&r1->ipv6_addr, "1:2:3:4::");
|
||||
r1->ipv6_orport = 9999;
|
||||
r1->onion_pkey = crypto_pk_dup_key(pk1);
|
||||
r1->identity_pkey = crypto_pk_dup_key(pk2);
|
||||
r1->bandwidthrate = 1000;
|
||||
@ -141,6 +143,7 @@ test_dir_formats(void)
|
||||
test_assert(router_dump_router_to_string(buf, 2048, r1, pk2)>0);
|
||||
|
||||
strlcpy(buf2, "router Magri 18.244.0.1 9000 0 9003\n"
|
||||
"or-address [1:2:3:4::]:9999\n"
|
||||
"platform Tor "VERSION" on ", sizeof(buf2));
|
||||
strlcat(buf2, get_uname(), sizeof(buf2));
|
||||
strlcat(buf2, "\n"
|
||||
|
Loading…
Reference in New Issue
Block a user