aboutsummaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
Diffstat (limited to 'src/or')
-rw-r--r--src/or/Makefile.nmake56
-rw-r--r--src/or/buffers.c2
-rw-r--r--src/or/circuitbuild.c25
-rw-r--r--src/or/circuitbuild.h3
-rw-r--r--src/or/command.c3
-rw-r--r--src/or/config.c91
-rw-r--r--src/or/config.h3
-rw-r--r--src/or/connection.c3
-rw-r--r--src/or/connection_edge.c40
-rw-r--r--src/or/connection_edge.h3
-rw-r--r--src/or/connection_or.c23
-rw-r--r--src/or/control.c15
-rw-r--r--src/or/dirserv.c9
-rw-r--r--src/or/dirserv.h1
-rw-r--r--src/or/dirvote.c10
-rw-r--r--src/or/dns.c4
-rw-r--r--src/or/main.c8
-rw-r--r--src/or/networkstatus.c4
-rw-r--r--src/or/or.h5
-rw-r--r--src/or/rendmid.c13
-rw-r--r--src/or/rephist.c63
-rw-r--r--src/or/rephist.h3
-rw-r--r--src/or/router.c73
-rw-r--r--src/or/router.h1
-rw-r--r--src/or/routerlist.c11
-rw-r--r--src/or/routerparse.c27
-rw-r--r--src/or/routerparse.h2
-rw-r--r--src/or/transports.c79
28 files changed, 419 insertions, 161 deletions
diff --git a/src/or/Makefile.nmake b/src/or/Makefile.nmake
index 919edbbf22..3181e79c20 100644
--- a/src/or/Makefile.nmake
+++ b/src/or/Makefile.nmake
@@ -1,28 +1,28 @@
-all: tor.exe
-
-CFLAGS = /I ..\win32 /I ..\..\..\build-alpha\include /I ..\common
-
-LIBS = ..\..\..\build-alpha\lib\libevent.a \
- ..\..\..\build-alpha\lib\libcrypto.a \
- ..\..\..\build-alpha\lib\libssl.a \
- ..\..\..\build-alpha\lib\libz.a \
- ws2_32.lib advapi32.lib shell32.lib
-
-LIBTOR_OBJECTS = buffers.obj circuitbuild.obj circuitlist.obj circuituse.obj \
- command.obj config.obj connection.obj connection_edge.obj \
- connection_or.obj control.obj cpuworker.obj directory.obj \
- dirserv.obj dirvote.obj dns.obj dnsserv.obj geoip.obj \
- hibernate.obj main.obj microdesc.obj networkstatus.obj \
- nodelist.obj onion.obj policies.obj reasons.obj relay.obj \
- rendclient.obj rendcommon.obj rendmid.obj rendservice.obj \
- rephist.obj router.obj routerlist.obj routerparse.obj status.obj \
- config_codedigest.obj ntmain.obj
-
-libtor.lib: $(LIBTOR_OBJECTS)
- lib $(LIBTOR_OBJECTS) /out:libtor.lib
-
-tor.exe: libtor.lib tor_main.obj
- $(CC) $(CFLAGS) $(LIBS) libtor.lib ..\common\*.lib tor_main.obj
-
-clean:
- del $(LIBTOR_OBJECTS) *.lib tor.exe
+all: tor.exe
+
+CFLAGS = /I ..\win32 /I ..\..\..\build-alpha\include /I ..\common
+
+LIBS = ..\..\..\build-alpha\lib\libevent.a \
+ ..\..\..\build-alpha\lib\libcrypto.a \
+ ..\..\..\build-alpha\lib\libssl.a \
+ ..\..\..\build-alpha\lib\libz.a \
+ ws2_32.lib advapi32.lib shell32.lib
+
+LIBTOR_OBJECTS = buffers.obj circuitbuild.obj circuitlist.obj circuituse.obj \
+ command.obj config.obj connection.obj connection_edge.obj \
+ connection_or.obj control.obj cpuworker.obj directory.obj \
+ dirserv.obj dirvote.obj dns.obj dnsserv.obj geoip.obj \
+ hibernate.obj main.obj microdesc.obj networkstatus.obj \
+ nodelist.obj onion.obj policies.obj reasons.obj relay.obj \
+ rendclient.obj rendcommon.obj rendmid.obj rendservice.obj \
+ rephist.obj router.obj routerlist.obj routerparse.obj status.obj \
+ config_codedigest.obj ntmain.obj
+
+libtor.lib: $(LIBTOR_OBJECTS)
+ lib $(LIBTOR_OBJECTS) /out:libtor.lib
+
+tor.exe: libtor.lib tor_main.obj
+ $(CC) $(CFLAGS) $(LIBS) libtor.lib ..\common\*.lib tor_main.obj
+
+clean:
+ del $(LIBTOR_OBJECTS) *.lib tor.exe
diff --git a/src/or/buffers.c b/src/or/buffers.c
index d60e54e87a..aa3e01fd9d 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -1011,7 +1011,7 @@ fetch_from_buf(char *string, size_t string_len, buf_t *buf)
/** True iff the cell command <b>command</b> is one that implies a
* variable-length cell in Tor link protocol <b>linkproto</b>. */
-static inline int
+static INLINE int
cell_command_is_var_length(uint8_t command, int linkproto)
{
/* If linkproto is v2 (2), CELL_VERSIONS is the only variable-length cells
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 5481838ccb..82ff327135 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -2847,6 +2847,10 @@ choose_good_exit_server_general(int need_uptime, int need_capacity)
if (node)
break;
smartlist_clear(supporting);
+ /* If we reach this point, we can't actually support any unhandled
+ * predicted ports, so clear all the remaining ones. */
+ if (smartlist_len(needed_ports))
+ rep_hist_remove_predicted_ports(needed_ports);
}
SMARTLIST_FOREACH(needed_ports, uint16_t *, cp, tor_free(cp));
smartlist_free(needed_ports);
@@ -3733,7 +3737,9 @@ entry_guard_free(entry_guard_t *e)
/** Remove any entry guard which was selected by an unknown version of Tor,
* or which was selected by a version of Tor that's known to select
- * entry guards badly. */
+ * entry guards badly, or which was selected more 2 months ago. */
+/* XXXX The "obsolete guards" and "chosen long ago guards" things should
+ * probably be different functions. */
static int
remove_obsolete_entry_guards(time_t now)
{
@@ -3862,6 +3868,8 @@ entry_guards_compute_status(const or_options_t *options, time_t now)
if (remove_dead_entry_guards(now))
changed = 1;
+ if (remove_obsolete_entry_guards(now))
+ changed = 1;
if (changed) {
SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
@@ -4964,6 +4972,21 @@ find_bridge_by_digest(const char *digest)
return NULL;
}
+const char *
+find_transport_name_by_bridge_addrport(const tor_addr_t *addr, uint16_t port)
+{
+ if (!bridge_list)
+ return NULL;
+
+ SMARTLIST_FOREACH_BEGIN(bridge_list, const bridge_info_t *, bridge) {
+ if (tor_addr_eq(&bridge->addr, addr) &&
+ (bridge->port == port))
+ return bridge->transport_name;
+ } SMARTLIST_FOREACH_END(bridge);
+
+ return NULL;
+}
+
/** If <b>addr</b> and <b>port</b> match the address and port of a
* bridge of ours that uses pluggable transports, place its transport
* in <b>transport</b>.
diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h
index a7fd208305..2ef5be8f25 100644
--- a/src/or/circuitbuild.h
+++ b/src/or/circuitbuild.h
@@ -157,6 +157,9 @@ void transport_free(transport_t *transport);
transport_t *transport_new(const tor_addr_t *addr, uint16_t port,
const char *name, int socks_ver);
+const char *find_transport_name_by_bridge_addrport(const tor_addr_t *addr,
+ uint16_t port);
+
int find_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port,
const transport_t **transport);
transport_t *transport_get_by_name(const char *name);
diff --git a/src/or/command.c b/src/or/command.c
index 9b14092fed..4e56edd5db 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -601,7 +601,6 @@ command_process_destroy_cell(cell_t *cell, or_connection_t *conn)
int reason;
circ = circuit_get_by_circid_orconn(cell->circ_id, conn);
- reason = (uint8_t)cell->payload[0];
if (!circ) {
log_info(LD_OR,"unknown circuit %d on connection from %s:%d. Dropping.",
cell->circ_id, conn->_base.address, conn->_base.port);
@@ -609,6 +608,8 @@ command_process_destroy_cell(cell_t *cell, or_connection_t *conn)
}
log_debug(LD_OR,"Received for circID %d.",cell->circ_id);
+ reason = (uint8_t)cell->payload[0];
+
if (!CIRCUIT_IS_ORIGIN(circ) &&
cell->circ_id == TO_OR_CIRCUIT(circ)->p_circ_id) {
/* the destroy came from behind */
diff --git a/src/or/config.c b/src/or/config.c
index bfed4e5db4..27aa8a2f23 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -748,7 +748,7 @@ set_options(or_options_t *new_val, char **msg)
}
/* Issues a CONF_CHANGED event to notify controller of the change. If Tor is
* just starting up then the old_options will be undefined. */
- if (old_options) {
+ if (old_options && old_options != global_options) {
elements = smartlist_new();
for (i=0; options_format.vars[i].name; ++i) {
const config_var_t *var = &options_format.vars[i];
@@ -774,7 +774,9 @@ set_options(or_options_t *new_val, char **msg)
control_event_conf_changed(elements);
smartlist_free(elements);
}
- config_free(&options_format, old_options);
+
+ if (old_options != global_options)
+ config_free(&options_format, old_options);
return 0;
}
@@ -783,6 +785,7 @@ extern const char tor_git_revision[]; /* from tor_main.c */
/** The version of this Tor process, as parsed. */
static char *the_tor_version = NULL;
+static char *the_short_tor_version = NULL;
/** Return the current Tor version. */
const char *
@@ -790,14 +793,31 @@ get_version(void)
{
if (the_tor_version == NULL) {
if (strlen(tor_git_revision)) {
- tor_asprintf(&the_tor_version, "%s (git-%s)", VERSION, tor_git_revision);
+ tor_asprintf(&the_tor_version, "%s (git-%s)", get_short_version(),
+ tor_git_revision);
} else {
- the_tor_version = tor_strdup(VERSION);
+ the_tor_version = tor_strdup(get_short_version());
}
}
return the_tor_version;
}
+/** Return the current Tor version, without any git tag. */
+const char *
+get_short_version(void)
+{
+
+ if (the_short_tor_version == NULL) {
+#ifdef TOR_BUILD_TAG
+ tor_asprintf(&the_short_tor_version, "%s (%s)", VERSION, TOR_BUILD_TAG);
+#else
+ the_short_tor_version = tor_strdup(VERSION);
+#endif
+ }
+ return the_short_tor_version;
+}
+
+
/** Release additional memory allocated in options
*/
static void
@@ -5099,7 +5119,7 @@ parse_client_transport_line(const char *line, int validate_only)
*tmp++ = smartlist_get(items, 2);
smartlist_del_keeporder(items, 2);
}
- *tmp = NULL; /*terminated with NUL pointer, just like execve() likes it*/
+ *tmp = NULL; /*terminated with NULL, just like execve() likes it*/
/* kickstart the thing */
pt_kickstart_client_proxy(transport_list, proxy_argv);
@@ -5222,7 +5242,7 @@ parse_server_transport_line(const char *line, int validate_only)
*tmp++ = smartlist_get(items, 2);
smartlist_del_keeporder(items, 2);
}
- *tmp = NULL; /*terminated with NUL pointer, just like execve() likes it*/
+ *tmp = NULL; /*terminated with NULL, just like execve() likes it*/
/* kickstart the thing */
pt_kickstart_server_proxy(transport_list, proxy_argv);
@@ -6040,6 +6060,65 @@ get_configured_ports(void)
return configured_ports;
}
+/** Return an <address>:<port> string representation of the address
+ * where the first <b>listener_type</b> listener waits for
+ * connections. Return NULL if we couldn't find a listener. The
+ * string is allocated on the heap and it's the responsibility of the
+ * caller to free it after use.
+ *
+ * This function is meant to be used by the pluggable transport proxy
+ * spawning code, please make sure that it fits your purposes before
+ * using it. */
+char *
+get_first_listener_addrport_string(int listener_type)
+{
+ static const char *ipv4_localhost = "127.0.0.1";
+ static const char *ipv6_localhost = "[::1]";
+ const char *address;
+ uint16_t port;
+ char *string = NULL;
+
+ if (!configured_ports)
+ return NULL;
+
+ SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) {
+ if (cfg->no_listen)
+ continue;
+
+ if (cfg->type == listener_type &&
+ tor_addr_family(&cfg->addr) != AF_UNSPEC) {
+
+ /* We found the first listener of the type we are interested in! */
+
+ /* If a listener is listening on INADDR_ANY, assume that it's
+ also listening on 127.0.0.1, and point the transport proxy
+ there: */
+ if (tor_addr_is_null(&cfg->addr))
+ address = tor_addr_is_v4(&cfg->addr) ? ipv4_localhost : ipv6_localhost;
+ else
+ address = fmt_and_decorate_addr(&cfg->addr);
+
+ /* If a listener is configured with port 'auto', we are forced
+ to iterate all listener connections and find out in which
+ port it ended up listening: */
+ if (cfg->port == CFG_AUTO_PORT) {
+ port = router_get_active_listener_port_by_type(listener_type);
+ if (!port)
+ return NULL;
+ } else {
+ port = cfg->port;
+ }
+
+ tor_asprintf(&string, "%s:%u", address, port);
+
+ return string;
+ }
+
+ } SMARTLIST_FOREACH_END(cfg);
+
+ return NULL;
+}
+
/** Return the first advertised port of type <b>listener_type</b> in
<b>address_family</b>. */
int
diff --git a/src/or/config.h b/src/or/config.h
index 0f7c618861..a68a3e3113 100644
--- a/src/or/config.h
+++ b/src/or/config.h
@@ -22,6 +22,7 @@ const char *safe_str(const char *address);
const char *escaped_safe_str_client(const char *address);
const char *escaped_safe_str(const char *address);
const char *get_version(void);
+const char *get_short_version(void);
int config_get_lines(const char *string, config_line_t **result, int extended);
void config_free_lines(config_line_t *front);
@@ -72,6 +73,8 @@ int get_first_advertised_port_by_type_af(int listener_type,
#define get_primary_dir_port() \
(get_first_advertised_port_by_type_af(CONN_TYPE_DIR_LISTENER, AF_INET))
+char *get_first_listener_addrport_string(int listener_type);
+
int options_need_geoip_info(const or_options_t *options,
const char **reason_out);
diff --git a/src/or/connection.c b/src/or/connection.c
index d379533494..0c970cc3b4 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -778,7 +778,8 @@ create_unix_sockaddr(const char *listenaddress, char **readable_address,
"Unix domain sockets not supported, yet we tried to create one.");
*len_out = 0;
tor_assert(0);
-};
+ return NULL;
+}
#endif /* HAVE_SYS_UN_H */
/** Warn that an accept or a connect has failed because we're running up
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 03558e557c..ca4bf3ffe4 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -2000,20 +2000,35 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
if (options->ClientRejectInternalAddresses &&
!conn->use_begindir && !conn->chosen_exit_name && !circ) {
tor_addr_t addr;
- if (tor_addr_parse(&addr, socks->address) >= 0 &&
- tor_addr_is_internal(&addr, 0)) {
+ if (tor_addr_hostname_is_local(socks->address) ||
+ (tor_addr_parse(&addr, socks->address) >= 0 &&
+ tor_addr_is_internal(&addr, 0))) {
/* If this is an explicit private address with no chosen exit node,
* then we really don't want to try to connect to it. That's
* probably an error. */
if (conn->is_transparent_ap) {
- log_warn(LD_NET,
- "Rejecting request for anonymous connection to private "
- "address %s on a TransPort or NATDPort. Possible loop "
- "in your NAT rules?", safe_str_client(socks->address));
+#define WARN_INTERVAL_LOOP 300
+ static ratelim_t loop_warn_limit = RATELIM_INIT(WARN_INTERVAL_LOOP);
+ char *m;
+ if ((m = rate_limit_log(&loop_warn_limit, approx_time()))) {
+ log_warn(LD_NET,
+ "Rejecting request for anonymous connection to private "
+ "address %s on a TransPort or NATDPort. Possible loop "
+ "in your NAT rules?%s", safe_str_client(socks->address),
+ m);
+ tor_free(m);
+ }
} else {
- log_warn(LD_NET,
- "Rejecting SOCKS request for anonymous connection to "
- "private address %s", safe_str_client(socks->address));
+#define WARN_INTERVAL_PRIV 300
+ static ratelim_t priv_warn_limit = RATELIM_INIT(WARN_INTERVAL_PRIV);
+ char *m;
+ if ((m = rate_limit_log(&priv_warn_limit, approx_time()))) {
+ log_warn(LD_NET,
+ "Rejecting SOCKS request for anonymous connection to "
+ "private address %s.%s",
+ safe_str_client(socks->address),m);
+ tor_free(m);
+ }
}
connection_mark_unattached_ap(conn, END_STREAM_REASON_PRIVATE_ADDR);
return -1;
@@ -2304,6 +2319,11 @@ connection_ap_handshake_process_socks(entry_connection_t *conn)
connection_write_to_buf((const char*)socks->reply, socks->replylen,
base_conn);
socks->replylen = 0;
+ if (sockshere == -1) {
+ /* An invalid request just got a reply, no additional
+ * one is necessary. */
+ socks->has_finished = 1;
+ }
}
if (sockshere == 0) {
@@ -2745,7 +2765,7 @@ tell_controller_about_resolved_result(entry_connection_t *conn,
answer_type == RESOLVED_TYPE_HOSTNAME)) {
return; /* we already told the controller. */
} else if (answer_type == RESOLVED_TYPE_IPV4 && answer_len >= 4) {
- char *cp = tor_dup_ip(get_uint32(answer));
+ char *cp = tor_dup_ip(ntohl(get_uint32(answer)));
control_event_address_mapped(conn->socks_request->address,
cp, expires, NULL);
tor_free(cp);
diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h
index 47c9c45b1a..f6db4b4ef9 100644
--- a/src/or/connection_edge.h
+++ b/src/or/connection_edge.h
@@ -79,7 +79,8 @@ int addressmap_have_mapping(const char *address, int update_timeout);
void addressmap_register(const char *address, char *new_address,
time_t expires, addressmap_entry_source_t source,
- int address_wildcard, int new_address_wildcard);
+ const int address_wildcard,
+ const int new_address_wildcard);
int parse_virtual_addr_network(const char *val, int validate_only,
char **msg);
int client_dns_incr_failures(const char *address);
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index 0d3f9d87f2..81df70eb37 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -1051,8 +1051,27 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
conn->_base.proxy_state = PROXY_INFANT;
}
} else {
- log_warn(LD_GENERAL, "Tried to connect through proxy, but proxy address "
- "could not be found.");
+ /* get_proxy_addrport() might fail if we have a Bridge line that
+ references a transport, but no ClientTransportPlugin lines
+ defining its transport proxy. If this is the case, let's try to
+ output a useful log message to the user. */
+ const char *transport_name =
+ find_transport_name_by_bridge_addrport(&TO_CONN(conn)->addr,
+ TO_CONN(conn)->port);
+
+ if (transport_name) {
+ log_warn(LD_GENERAL, "We were supposed to connect to bridge '%s:%u' "
+ "using pluggable transport '%s', but it seems that we can't "
+ "find a pluggable transport proxy supporting '%s'. Please make "
+ "sure that your configuration file is valid.",
+ fmt_addr(&TO_CONN(conn)->addr), TO_CONN(conn)->port,
+ transport_name, transport_name);
+ } else {
+ log_warn(LD_GENERAL, "Tried to connect to '%s:%u' through a proxy, but "
+ "the proxy address could not be found.",
+ fmt_addr(&TO_CONN(conn)->addr), TO_CONN(conn)->port);
+ }
+
connection_free(TO_CONN(conn));
return NULL;
}
diff --git a/src/or/control.c b/src/or/control.c
index 397bb53ab4..ec018ffc23 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -2530,6 +2530,10 @@ handle_control_setcircuitpurpose(control_connection_t *conn,
{
const char *purp = find_element_starting_with(args,1,"PURPOSE=");
+ if (!purp) {
+ connection_write_str_to_buf("552 No purpose given\r\n", conn);
+ goto done;
+ }
new_purpose = circuit_purpose_from_string(purp);
if (new_purpose == CIRCUIT_PURPOSE_UNKNOWN) {
connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp);
@@ -2986,13 +2990,14 @@ handle_control_authchallenge(control_connection_t *conn, uint32_t len,
cp += strlen("SAFECOOKIE");
} else {
connection_write_str_to_buf("513 AUTHCHALLENGE only supports SAFECOOKIE "
- "authentication", conn);
+ "authentication\r\n", conn);
connection_mark_for_close(TO_CONN(conn));
return -1;
}
if (!authentication_cookie_is_set) {
- connection_write_str_to_buf("515 Cookie authentication is disabled", conn);
+ connection_write_str_to_buf("515 Cookie authentication is disabled\r\n",
+ conn);
connection_mark_for_close(TO_CONN(conn));
return -1;
}
@@ -3003,7 +3008,7 @@ handle_control_authchallenge(control_connection_t *conn, uint32_t len,
decode_escaped_string(cp, len - (cp - body),
&client_nonce, &client_nonce_len);
if (newcp == NULL) {
- connection_write_str_to_buf("513 Invalid quoted client nonce",
+ connection_write_str_to_buf("513 Invalid quoted client nonce\r\n",
conn);
connection_mark_for_close(TO_CONN(conn));
return -1;
@@ -3017,7 +3022,7 @@ handle_control_authchallenge(control_connection_t *conn, uint32_t len,
if (base16_decode(client_nonce, client_nonce_len,
cp, client_nonce_encoded_len) < 0) {
- connection_write_str_to_buf("513 Invalid base16 client nonce",
+ connection_write_str_to_buf("513 Invalid base16 client nonce\r\n",
conn);
connection_mark_for_close(TO_CONN(conn));
tor_free(client_nonce);
@@ -3030,7 +3035,7 @@ handle_control_authchallenge(control_connection_t *conn, uint32_t len,
cp += strspn(cp, " \t\n\r");
if (*cp != '\0' ||
cp != body + len) {
- connection_write_str_to_buf("513 Junk at end of AUTHCHALLENGE command",
+ connection_write_str_to_buf("513 Junk at end of AUTHCHALLENGE command\r\n",
conn);
connection_mark_for_close(TO_CONN(conn));
tor_free(client_nonce);
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 1c2579865f..1220c32a50 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -1252,6 +1252,15 @@ directory_caches_v2_dir_info(const or_options_t *options)
return options->DirPort != NULL;
}
+/** Return true iff we want to fetch and keep certificates for authorities
+ * that we don't acknowledge as aurthorities ourself.
+ */
+int
+directory_caches_unknown_auth_certs(const or_options_t *options)
+{
+ return options->DirPort || options->BridgeRelay;
+}
+
/** Return 1 if we want to keep descriptors, networkstatuses, etc around
* and we're willing to serve them to others. Else return 0.
*/
diff --git a/src/or/dirserv.h b/src/or/dirserv.h
index fc48e489e8..3ff08157e0 100644
--- a/src/or/dirserv.h
+++ b/src/or/dirserv.h
@@ -76,6 +76,7 @@ int directory_fetches_dir_info_early(const or_options_t *options);
int directory_fetches_dir_info_later(const or_options_t *options);
int directory_caches_v2_dir_info(const or_options_t *options);
#define directory_caches_v1_dir_info(o) directory_caches_v2_dir_info(o)
+int directory_caches_unknown_auth_certs(const or_options_t *options);
int directory_caches_dir_info(const or_options_t *options);
int directory_permits_begindir_requests(const or_options_t *options);
int directory_permits_controller_requests(const or_options_t *options);
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index cddb658244..20dc8c2649 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -668,10 +668,10 @@ dirvote_compute_params(smartlist_t *votes, int method, int total_authorities)
const char *next_param;
int ok=0;
eq = strchr(param, '=');
- tor_assert(i<n_votes);
+ tor_assert(i<n_votes); /* Make sure we prevented vote-stuffing. */
vals[i++] = (int32_t)
tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL);
- tor_assert(ok);
+ tor_assert(ok); /* Already checked these when parsing. */
if (param_sl_idx+1 == smartlist_len(param_list))
next_param = NULL;
@@ -1005,7 +1005,7 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
/* We cast down the weights to 32 bit ints on the assumption that
* weight_scale is ~= 10000. We need to ensure a rogue authority
* doesn't break this assumption to rig our weights */
- tor_assert(0 < weight_scale && weight_scale < INT32_MAX);
+ tor_assert(0 < weight_scale && weight_scale <= INT32_MAX);
/*
* Provide Wgm=Wgg, Wmm=1, Wem=Wee, Weg=Wed. May later determine
@@ -1233,7 +1233,7 @@ networkstatus_compute_bw_weights_v9(smartlist_t *chunks, int64_t G, int64_t M,
/* We cast down the weights to 32 bit ints on the assumption that
* weight_scale is ~= 10000. We need to ensure a rogue authority
* doesn't break this assumption to rig our weights */
- tor_assert(0 < weight_scale && weight_scale < INT32_MAX);
+ tor_assert(0 < weight_scale && weight_scale <= INT32_MAX);
if (Wgg < 0 || Wgg > weight_scale) {
log_warn(LD_DIR, "Bw %s: Wgg="I64_FORMAT"! G="I64_FORMAT
@@ -2019,7 +2019,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
int ok=0;
char *eq = strchr(bw_weight_param, '=');
if (eq) {
- weight_scale = tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok,
+ weight_scale = tor_parse_long(eq+1, 10, 1, INT32_MAX, &ok,
NULL);
if (!ok) {
log_warn(LD_DIR, "Bad element '%s' in bw weight param",
diff --git a/src/or/dns.c b/src/or/dns.c
index 2b7d3e3506..b349f02f68 100644
--- a/src/or/dns.c
+++ b/src/or/dns.c
@@ -1389,7 +1389,7 @@ evdns_callback(int result, char type, int count, int ttl, void *addresses,
static int
launch_resolve(edge_connection_t *exitconn)
{
- char *addr = tor_strdup(exitconn->_base.address);
+ char *addr;
struct evdns_request *req = NULL;
tor_addr_t a;
int r;
@@ -1408,6 +1408,8 @@ launch_resolve(edge_connection_t *exitconn)
}
}
+ addr = tor_strdup(exitconn->_base.address);
+
r = tor_addr_parse_PTR_name(
&a, exitconn->_base.address, AF_UNSPEC, 0);
diff --git a/src/or/main.c b/src/or/main.c
index 9022f2eb87..8308b3a238 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -1773,8 +1773,16 @@ do_hup(void)
}
options = get_options(); /* they have changed now */
} else {
+ char *msg = NULL;
log_notice(LD_GENERAL, "Not reloading config file: the controller told "
"us not to.");
+ /* Make stuff get rescanned, reloaded, etc. */
+ if (set_options((or_options_t*)options, &msg) < 0) {
+ if (!msg)
+ msg = tor_strdup("Unknown error");
+ log_warn(LD_GENERAL, "Unable to re-set previous options: %s", msg);
+ tor_free(msg);
+ }
}
if (authdir_mode_handles_descs(options, -1)) {
/* reload the approved-routers file */
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 910b99c5c0..3646ee6844 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -1463,8 +1463,10 @@ networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f)
return current_ns_consensus;
else if (f == FLAV_MICRODESC)
return current_md_consensus;
- else
+ else {
tor_assert(0);
+ return NULL;
+ }
}
/** Return the most recent consensus that we have downloaded, or NULL if it is
diff --git a/src/or/or.h b/src/or/or.h
index b8fee649ea..76681c9eea 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -23,11 +23,8 @@
#endif
#ifdef _WIN32
-#ifndef WIN32_WINNT
-#define WIN32_WINNT 0x400
-#endif
#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x400
+#define _WIN32_WINNT 0x0501
#endif
#define WIN32_LEAN_AND_MEAN
#endif
diff --git a/src/or/rendmid.c b/src/or/rendmid.c
index 2742c351b3..894bbb3c54 100644
--- a/src/or/rendmid.c
+++ b/src/or/rendmid.c
@@ -276,13 +276,6 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
or_circuit_t *rend_circ;
char hexid[9];
int reason = END_CIRC_REASON_INTERNAL;
- base16_encode(hexid,9,(char*)request,request_len<4?request_len:4);
-
- if (request_len>=4) {
- log_info(LD_REND,
- "Got request for rendezvous from circuit %d to cookie %s.",
- circ->p_circ_id, hexid);
- }
if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) {
log_info(LD_REND,
@@ -300,6 +293,12 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
goto err;
}
+ base16_encode(hexid, sizeof(hexid), (const char*)request, 4);
+
+ log_info(LD_REND,
+ "Got request for rendezvous from circuit %d to cookie %s.",
+ circ->p_circ_id, hexid);
+
rend_circ = circuit_get_rendezvous((char*)request);
if (!rend_circ) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 0cd60eeb83..0727c6851a 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -1868,6 +1868,26 @@ rep_hist_get_predicted_ports(time_t now)
return out;
}
+/**
+ * Take a list of uint16_t *, and remove every port in the list from the
+ * current list of predicted ports.
+ */
+void
+rep_hist_remove_predicted_ports(const smartlist_t *rmv_ports)
+{
+ /* Let's do this on O(N), not O(N^2). */
+ bitarray_t *remove_ports = bitarray_init_zero(UINT16_MAX);
+ SMARTLIST_FOREACH(rmv_ports, const uint16_t *, p,
+ bitarray_set(remove_ports, *p));
+ SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) {
+ if (bitarray_is_set(remove_ports, pp->port)) {
+ tor_free(pp);
+ SMARTLIST_DEL_CURRENT(predicted_ports_list, pp);
+ }
+ } SMARTLIST_FOREACH_END(pp);
+ bitarray_free(remove_ports);
+}
+
/** The user asked us to do a resolve. Rather than keeping track of
* timings and such of resolves, we fake it for now by treating
* it the same way as a connection to port 80. This way we will continue
@@ -2650,24 +2670,30 @@ rep_hist_format_desc_stats(time_t now)
const char *key;
void *val;
unsigned size;
- int *vals;
+ int *vals, max = 0, q3 = 0, md = 0, q1 = 0, min = 0;
int n = 0;
if (!start_of_served_descs_stats_interval)
return NULL;
- size = digestmap_size(served_descs);
- if (size == 0)
- return NULL;
- vals = tor_malloc(size * sizeof(int));
-
- for (iter = digestmap_iter_init(served_descs); !digestmap_iter_done(iter);
- iter = digestmap_iter_next(served_descs, iter) ) {
- uintptr_t count;
- digestmap_iter_get(iter, &key, &val);
- count = (uintptr_t)val;
- vals[n++] = (int)count;
- (void)key;
+ size = digestmap_size(served_descs);
+ if (size > 0) {
+ vals = tor_malloc(size * sizeof(int));
+ for (iter = digestmap_iter_init(served_descs);
+ !digestmap_iter_done(iter);
+ iter = digestmap_iter_next(served_descs, iter)) {
+ uintptr_t count;
+ digestmap_iter_get(iter, &key, &val);
+ count = (uintptr_t)val;
+ vals[n++] = (int)count;
+ (void)key;
+ }
+ max = find_nth_int(vals, size, size-1);
+ q3 = find_nth_int(vals, size, (3*size-1)/4);
+ md = find_nth_int(vals, size, (size-1)/2);
+ q1 = find_nth_int(vals, size, (size-1)/4);
+ min = find_nth_int(vals, size, 0);
+ tor_free(vals);
}
format_iso_time(t, now);
@@ -2678,14 +2704,8 @@ rep_hist_format_desc_stats(time_t now)
t,
(unsigned) (now - start_of_served_descs_stats_interval),
total_descriptor_downloads,
- size,
- find_nth_int(vals, size, size-1),
- find_nth_int(vals, size, (3*size-1)/4),
- find_nth_int(vals, size, (size-1)/2),
- find_nth_int(vals, size, (size-1)/4),
- find_nth_int(vals, size, 0));
-
- tor_free(vals);
+ size, max, q3, md, q1, min);
+
return result;
}
@@ -2705,6 +2725,7 @@ rep_hist_desc_stats_write(time_t now)
return start_of_served_descs_stats_interval + WRITE_STATS_INTERVAL;
str = rep_hist_format_desc_stats(now);
+ tor_assert(str != NULL);
statsdir = get_datadir_fname("stats");
if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
diff --git a/src/or/rephist.h b/src/or/rephist.h
index 0a3e46ae1a..860713c350 100644
--- a/src/or/rephist.h
+++ b/src/or/rephist.h
@@ -34,7 +34,7 @@ int rep_hist_load_state(or_state_t *state, char **err);
void rep_history_clean(time_t before);
void rep_hist_note_router_reachable(const char *id, const tor_addr_t *at_addr,
- uint16_t at_port, time_t when);
+ const uint16_t at_port, time_t when);
void rep_hist_note_router_unreachable(const char *id, time_t when);
int rep_hist_record_mtbf_data(time_t now, int missing_means_down);
int rep_hist_load_mtbf_data(time_t now);
@@ -49,6 +49,7 @@ const char *rep_hist_get_router_stability_doc(time_t now);
void rep_hist_note_used_port(time_t now, uint16_t port);
smartlist_t *rep_hist_get_predicted_ports(time_t now);
+void rep_hist_remove_predicted_ports(const smartlist_t *rmv_ports);
void rep_hist_note_used_resolve(time_t now);
void rep_hist_note_used_internal(time_t now, int need_uptime,
int need_capacity);
diff --git a/src/or/router.c b/src/or/router.c
index 4cdfd02e56..34e231ae7c 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -1228,6 +1228,22 @@ consider_publishable_server(int force)
}
}
+/** Return the port of the first active listener of type
+ * <b>listener_type</b>. */
+/** XXX not a very good interface. it's not reliable when there are
+ multiple listeners. */
+uint16_t
+router_get_active_listener_port_by_type(int listener_type)
+{
+ /* Iterate all connections, find one of the right kind and return
+ the port. Not very sophisticated or fast, but effective. */
+ const connection_t *c = connection_get_by_type(listener_type);
+ if (c)
+ return c->port;
+
+ return 0;
+}
+
/** 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".
@@ -1238,12 +1254,11 @@ router_get_advertised_or_port(const or_options_t *options)
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;
- }
+ /* If the port is in 'auto' mode, we have to use
+ router_get_listener_port_by_type(). */
+ if (port == CFG_AUTO_PORT)
+ return router_get_active_listener_port_by_type(CONN_TYPE_OR_LISTENER);
+
return port;
}
@@ -1260,12 +1275,10 @@ router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport)
if (!dirport_configured)
return dirport;
- if (dirport_configured == CFG_AUTO_PORT) {
- connection_t *c = connection_get_by_type(CONN_TYPE_DIR_LISTENER);
- if (c)
- return c->port;
- return 0;
- }
+
+ if (dirport_configured == CFG_AUTO_PORT)
+ return router_get_active_listener_port_by_type(CONN_TYPE_DIR_LISTENER);
+
return dirport_configured;
}
@@ -1530,10 +1543,18 @@ router_rebuild_descriptor(int force)
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;
+ tor_addr_family(&p->addr) == AF_INET6) {
+ if (! tor_addr_is_internal(&p->addr, 0)) {
+ ipv6_orport = p;
+ break;
+ } else {
+ char addrbuf[TOR_ADDR_BUF_LEN];
+ log_warn(LD_CONFIG,
+ "Unable to use configured IPv6 address \"%s\" in a "
+ "descriptor. Skipping it. "
+ "Try specifying a globally reachable address explicitly. ",
+ tor_addr_to_str(addrbuf, &p->addr, sizeof(addrbuf), 1));
+ }
}
} SMARTLIST_FOREACH_END(p);
if (ipv6_orport) {
@@ -1647,6 +1668,7 @@ router_rebuild_descriptor(int force)
ei->cache_info.signed_descriptor_len =
strlen(ei->cache_info.signed_descriptor_body);
router_get_extrainfo_hash(ei->cache_info.signed_descriptor_body,
+ ei->cache_info.signed_descriptor_len,
ei->cache_info.signed_descriptor_digest);
}
@@ -1672,12 +1694,15 @@ router_rebuild_descriptor(int force)
ri->purpose =
options->BridgeRelay ? ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
- ri->cache_info.send_unencrypted = 1;
- /* Let bridges serve their own descriptors unencrypted, so they can
- * pass reachability testing. (If they want to be harder to notice,
- * they can always leave the DirPort off). */
- if (ei && !options->BridgeRelay)
- ei->cache_info.send_unencrypted = 1;
+ if (options->BridgeRelay) {
+ /* Bridges shouldn't be able to send their descriptors unencrypted,
+ anyway, since they don't have a DirPort, and always connect to the
+ bridge authority anonymously. But just in case they somehow think of
+ sending them on an unencrypted connection, don't allow them to try. */
+ ri->cache_info.send_unencrypted = ei->cache_info.send_unencrypted = 0;
+ } else {
+ ri->cache_info.send_unencrypted = ei->cache_info.send_unencrypted = 1;
+ }
router_get_router_hash(ri->cache_info.signed_descriptor_body,
strlen(ri->cache_info.signed_descriptor_body),
@@ -1927,7 +1952,7 @@ router_guess_address_from_dir_headers(uint32_t *guess)
void
get_platform_str(char *platform, size_t len)
{
- tor_snprintf(platform, len, "Tor %s on %s", get_version(), get_uname());
+ tor_snprintf(platform, len, "Tor %s on %s", get_short_version(), get_uname());
}
/* XXX need to audit this thing and count fenceposts. maybe
@@ -2351,7 +2376,7 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
}
memset(sig, 0, sizeof(sig));
- if (router_get_extrainfo_hash(s, digest) < 0 ||
+ if (router_get_extrainfo_hash(s, strlen(s), digest) < 0 ||
router_append_dirobj_signature(sig, sizeof(sig), digest, DIGEST_LEN,
ident_key) < 0) {
log_warn(LD_BUG, "Could not append signature to extra-info "
diff --git a/src/or/router.h b/src/or/router.h
index fb914349f3..294736e70c 100644
--- a/src/or/router.h
+++ b/src/or/router.h
@@ -53,6 +53,7 @@ int authdir_mode_publishes_statuses(const or_options_t *options);
int authdir_mode_tests_reachability(const or_options_t *options);
int authdir_mode_bridge(const or_options_t *options);
+uint16_t router_get_active_listener_port_by_type(int listener_type);
uint16_t 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);
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index a64b93f3a9..0abc2e9bcf 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -229,7 +229,7 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store,
"signing key %s", from_store ? "cached" : "downloaded",
ds->nickname, hex_str(cert->signing_key_digest,DIGEST_LEN));
} else {
- int adding = directory_caches_dir_info(get_options());
+ int adding = directory_caches_unknown_auth_certs(get_options());
log_info(LD_DIR, "%s %s certificate for unrecognized directory "
"authority with signing key %s",
adding ? "Adding" : "Not adding",
@@ -480,7 +480,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now)
smartlist_t *missing_digests;
char *resource = NULL;
cert_list_t *cl;
- const int cache = directory_caches_dir_info(get_options());
+ const int cache = directory_caches_unknown_auth_certs(get_options());
if (should_delay_dir_fetches(get_options()))
return;
@@ -2838,6 +2838,13 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri)
ri->cache_info.signed_descriptor_digest,
&(ri->cache_info));
if (sd_old) {
+ int idx = sd_old->routerlist_index;
+ sd_old->routerlist_index = -1;
+ smartlist_del(rl->old_routers, idx);
+ if (idx < smartlist_len(rl->old_routers)) {
+ signed_descriptor_t *d = smartlist_get(rl->old_routers, idx);
+ d->routerlist_index = idx;
+ }
rl->desc_store.bytes_dropped += sd_old->signed_descriptor_len;
sdmap_remove(rl->desc_by_eid_map, sd_old->extra_info_digest);
signed_descriptor_free(sd_old);
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 7cc8b965e6..781c57897d 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -682,12 +682,12 @@ router_get_networkstatus_v3_hash(const char *s, char *digest,
' ', alg);
}
-/** Set <b>digest</b> to the SHA-1 digest of the hash of the extrainfo
- * string in <b>s</b>. Return 0 on success, -1 on failure. */
+/** Set <b>digest</b> to the SHA-1 digest of the hash of the <b>s_len</b>-byte
+ * extrainfo string at <b>s</b>. Return 0 on success, -1 on failure. */
int
-router_get_extrainfo_hash(const char *s, char *digest)
+router_get_extrainfo_hash(const char *s, size_t s_len, char *digest)
{
- return router_get_hash_impl(s, strlen(s), digest, "extra-info",
+ return router_get_hash_impl(s, s_len, digest, "extra-info",
"\nrouter-signature",'\n', DIGEST_SHA1);
}
@@ -1643,7 +1643,7 @@ extrainfo_parse_entry_from_string(const char *s, const char *end,
while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
--end;
- if (router_get_extrainfo_hash(s, digest) < 0) {
+ if (router_get_extrainfo_hash(s, end-s, digest) < 0) {
log_warn(LD_DIR, "Couldn't compute router hash.");
goto err;
}
@@ -2821,6 +2821,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
int i, inorder, n_signatures = 0;
memarea_t *area = NULL, *rs_area = NULL;
consensus_flavor_t flav = FLAV_NS;
+ char *last_kwd=NULL;
tor_assert(s);
@@ -2977,15 +2978,18 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
tok = find_opt_by_keyword(tokens, K_PARAMS);
if (tok) {
+ int any_dups = 0;
inorder = 1;
ns->net_params = smartlist_new();
for (i = 0; i < tok->n_args; ++i) {
int ok=0;
char *eq = strchr(tok->args[i], '=');
+ size_t eq_pos;
if (!eq) {
log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
goto err;
}
+ eq_pos = eq-tok->args[i];
tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL);
if (!ok) {
log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
@@ -2995,12 +2999,24 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
inorder = 0;
}
+ if (last_kwd && eq_pos == strlen(last_kwd) &&
+ fast_memeq(last_kwd, tok->args[i], eq_pos)) {
+ log_warn(LD_DIR, "Duplicate value for %s parameter",
+ escaped(tok->args[i]));
+ any_dups = 1;
+ }
+ tor_free(last_kwd);
+ last_kwd = tor_strndup(tok->args[i], eq_pos);
smartlist_add(ns->net_params, tor_strdup(tok->args[i]));
}
if (!inorder) {
log_warn(LD_DIR, "params not in order");
goto err;
}
+ if (any_dups) {
+ log_warn(LD_DIR, "Duplicate in parameters");
+ goto err;
+ }
}
ns->voters = smartlist_new();
@@ -3339,6 +3355,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
}
if (rs_area)
memarea_drop_all(rs_area);
+ tor_free(last_kwd);
return ns;
}
diff --git a/src/or/routerparse.h b/src/or/routerparse.h
index b274d2196c..6486a09c73 100644
--- a/src/or/routerparse.h
+++ b/src/or/routerparse.h
@@ -19,7 +19,7 @@ int router_get_networkstatus_v2_hash(const char *s, char *digest);
int router_get_networkstatus_v3_hash(const char *s, char *digest,
digest_algorithm_t algorithm);
int router_get_networkstatus_v3_hashes(const char *s, digests_t *digests);
-int router_get_extrainfo_hash(const char *s, char *digest);
+int router_get_extrainfo_hash(const char *s, size_t s_len, char *digest);
#define DIROBJ_MAX_SIG_LEN 256
int router_append_dirobj_signature(char *buf, size_t buf_len,
const char *digest,
diff --git a/src/or/transports.c b/src/or/transports.c
index 564603e1fe..a20decfc03 100644
--- a/src/or/transports.c
+++ b/src/or/transports.c
@@ -119,10 +119,6 @@ static INLINE void free_execve_args(char **arg);
#define PROTO_CMETHODS_DONE "CMETHODS DONE"
#define PROTO_SMETHODS_DONE "SMETHODS DONE"
-/* The smallest valid managed proxy protocol line that can
- appear. It's the size of "VERSION 1" */
-#define SMALLEST_MANAGED_LINE_SIZE 9
-
/** Number of environment variables for managed proxy clients/servers. */
#define ENVIRON_SIZE_CLIENT 3
#define ENVIRON_SIZE_SERVER 7 /* XXX known to be too high, but that's ok */
@@ -340,11 +336,12 @@ pt_configure_remaining_proxies(void)
/* This proxy is marked by a SIGHUP. Check whether we need to
restart it. */
if (proxy_needs_restart(mp)) {
- log_info(LD_GENERAL, "Preparing managed proxy for restart.");
+ log_info(LD_GENERAL, "Preparing managed proxy '%s' for restart.",
+ mp->argv[0]);
proxy_prepare_for_restart(mp);
} else { /* it doesn't need to be restarted. */
- log_info(LD_GENERAL, "Nothing changed for managed proxy after HUP: "
- "not restarting.");
+ log_info(LD_GENERAL, "Nothing changed for managed proxy '%s' after "
+ "HUP: not restarting.", mp->argv[0]);
}
continue;
@@ -387,7 +384,8 @@ configure_proxy(managed_proxy_t *mp)
pos = tor_read_all_handle(tor_process_get_stdout_pipe(mp->process_handle),
stdout_buf, sizeof(stdout_buf) - 1, NULL);
if (pos < 0) {
- log_notice(LD_GENERAL, "Failed to read data from managed proxy");
+ log_notice(LD_GENERAL, "Failed to read data from managed proxy '%s'.",
+ mp->argv[0]);
mp->conf_state = PT_PROTO_BROKEN;
goto done;
}
@@ -449,11 +447,13 @@ configure_proxy(managed_proxy_t *mp)
} else if (r == IO_STREAM_EAGAIN) { /* check back later */
return;
} else if (r == IO_STREAM_CLOSED || r == IO_STREAM_TERM) { /* snap! */
- log_notice(LD_GENERAL, "Managed proxy stream closed. "
- "Most probably application stopped running");
+ log_warn(LD_GENERAL, "Our communication channel with the managed proxy "
+ "'%s' closed. Most probably application stopped running.",
+ mp->argv[0]);
mp->conf_state = PT_PROTO_BROKEN;
} else { /* unknown stream status */
- log_notice(LD_GENERAL, "Unknown stream status while configuring proxy.");
+ log_warn(LD_BUG, "Unknown stream status '%d' while configuring managed "
+ "proxy '%s'.", (int)r, mp->argv[0]);
}
/* if the proxy finished configuring, exit the loop. */
@@ -586,8 +586,8 @@ handle_finished_proxy(managed_proxy_t *mp)
case PT_PROTO_ACCEPTING_METHODS:
case PT_PROTO_COMPLETED:
default:
- log_warn(LD_CONFIG, "Unexpected managed proxy state in "
- "handle_finished_proxy().");
+ log_warn(LD_CONFIG, "Unexpected state '%d' of managed proxy '%s'.",
+ (int)mp->conf_state, mp->argv[0]);
tor_assert(0);
}
@@ -612,11 +612,13 @@ handle_methods_done(const managed_proxy_t *mp)
tor_assert(mp->transports);
if (smartlist_len(mp->transports) == 0)
- log_notice(LD_GENERAL, "Proxy was spawned successfully, "
- "but it didn't laucn any pluggable transport listeners!");
+ log_notice(LD_GENERAL, "Managed proxy '%s' was spawned successfully, "
+ "but it didn't launch any pluggable transport listeners!",
+ mp->argv[0]);
- log_info(LD_CONFIG, "%s managed proxy configuration completed!",
- mp->is_server ? "Server" : "Client");
+ log_info(LD_CONFIG, "%s managed proxy '%s' configuration completed!",
+ mp->is_server ? "Server" : "Client",
+ mp->argv[0]);
}
/** Handle a configuration protocol <b>line</b> received from a
@@ -624,13 +626,8 @@ handle_methods_done(const managed_proxy_t *mp)
void
handle_proxy_line(const char *line, managed_proxy_t *mp)
{
- log_debug(LD_GENERAL, "Got a line from managed proxy: %s", line);
-
- if (strlen(line) < SMALLEST_MANAGED_LINE_SIZE) {
- log_warn(LD_GENERAL, "Managed proxy configuration line is too small. "
- "Discarding");
- goto err;
- }
+ log_info(LD_GENERAL, "Got a line from managed proxy '%s': (%s)",
+ mp->argv[0], line);
if (!strcmpstart(line, PROTO_ENV_ERROR)) {
if (mp->conf_state != PT_PROTO_LAUNCHED)
@@ -705,12 +702,13 @@ handle_proxy_line(const char *line, managed_proxy_t *mp)
return;
}
- log_warn(LD_CONFIG, "Unknown line received by managed proxy. (%s)", line);
+ log_notice(LD_GENERAL, "Unknown line received by managed proxy (%s).", line);
+ return;
err:
mp->conf_state = PT_PROTO_BROKEN;
log_warn(LD_CONFIG, "Managed proxy at '%s' failed the configuration protocol"
- " and will be destroyed.", mp->argv ? mp->argv[0] : "");
+ " and will be destroyed.", mp->argv[0]);
}
/** Parses an ENV-ERROR <b>line</b> and warns the user accordingly. */
@@ -957,8 +955,6 @@ get_bindaddr_for_server_proxy(const managed_proxy_t *mp)
static process_environment_t *
create_managed_proxy_environment(const managed_proxy_t *mp)
{
- const or_options_t *options = get_options();
-
/* Environment variables to be added to or set in mp's environment. */
smartlist_t *envs = smartlist_new();
/* XXXX The next time someone touches this code, shorten the name of
@@ -993,8 +989,12 @@ create_managed_proxy_environment(const managed_proxy_t *mp)
}
if (mp->is_server) {
- smartlist_add_asprintf(envs, "TOR_PT_ORPORT=127.0.0.1:%s",
- options->ORPort->value);
+ {
+ char *orport_tmp =
+ get_first_listener_addrport_string(CONN_TYPE_OR_LISTENER);
+ smartlist_add_asprintf(envs, "TOR_PT_ORPORT=%s", orport_tmp);
+ tor_free(orport_tmp);
+ }
{
char *bindaddr_tmp = get_bindaddr_for_server_proxy(mp);
@@ -1027,8 +1027,11 @@ create_managed_proxy_environment(const managed_proxy_t *mp)
}
/** Create and return a new managed proxy for <b>transport</b> using
- * <b>proxy_argv</b>. If <b>is_server</b> is true, it's a server
- * managed proxy. */
+ * <b>proxy_argv</b>. Also, add it to the global managed proxy list. If
+ * <b>is_server</b> is true, it's a server managed proxy. Takes ownership of
+ * <b>proxy_argv</b>.
+ *
+ * Requires that proxy_argv have at least one element. */
static managed_proxy_t *
managed_proxy_create(const smartlist_t *transport_list,
char **proxy_argv, int is_server)
@@ -1056,7 +1059,13 @@ managed_proxy_create(const smartlist_t *transport_list,
/** Register proxy with <b>proxy_argv</b>, supporting transports in
* <b>transport_list</b>, to the managed proxy subsystem.
- * If <b>is_server</b> is true, then the proxy is a server proxy. */
+ * If <b>is_server</b> is true, then the proxy is a server proxy.
+ *
+ * Takes ownership of proxy_argv.
+ *
+ * Requires that proxy_argv be a NULL-terminated array of command-line
+ * elements, containing at least one element.
+ **/
void
pt_kickstart_proxy(const smartlist_t *transport_list,
char **proxy_argv, int is_server)
@@ -1064,6 +1073,10 @@ pt_kickstart_proxy(const smartlist_t *transport_list,
managed_proxy_t *mp=NULL;
transport_t *old_transport = NULL;
+ if (!proxy_argv || !proxy_argv[0]) {
+ return;
+ }
+
mp = get_managed_proxy_by_argv_and_type(proxy_argv, is_server);
if (!mp) { /* we haven't seen this proxy before */