Commit 5f0a8dcd authored by Nick Mathewson's avatar Nick Mathewson 🎨
Browse files

Initial hacking for proposal 186.

This code handles the new ORPort options, and incidentally makes all
remaining port types use the new port configuration systems.

There are some rough edges!  It doesn't do well in the case where your
Address says one thing but you say to Advertise another ORPort.  It
doesn't handle AllAddrs.  It doesn't actually advertise anything besides
the first listed advertised IPv4 ORPort and DirPort.  It doesn't do
port forwarding to them either.

It's not tested either, it needs more documentation, and it probably
forgets to put the milk back in the refrigerator.
parent 628b735f
This diff is collapsed.
......@@ -64,7 +64,12 @@ 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_v4_port_by_type(int listener_type);
#define get_primary_or_port() \
(get_first_advertised_v4_port_by_type(CONN_TYPE_OR_LISTENER))
#define get_primary_dir_port() \
(get_first_advertised_v4_port_by_type(CONN_TYPE_DIR_LISTENER))
int options_need_geoip_info(const or_options_t *options,
const char **reason_out);
......
......@@ -1814,6 +1814,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 +1855,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 +1893,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 +1915,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
......
......@@ -3729,7 +3729,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;
}
......
......@@ -2833,6 +2833,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 +2955,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? */
......
......@@ -1083,7 +1083,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 +1134,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 +1200,22 @@ 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".
* DOCDOC
*/
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;
}
/*
......
......@@ -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*/
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment