aboutsummaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
Diffstat (limited to 'src/or')
-rw-r--r--src/or/circuitbuild.c196
-rw-r--r--src/or/circuitbuild.h28
-rw-r--r--src/or/connection.c1
-rw-r--r--src/or/router.c8
-rw-r--r--src/or/transports.c373
-rw-r--r--src/or/transports.h49
6 files changed, 357 insertions, 298 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 714bbca34..1c1f4ebdc 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -4970,199 +4970,6 @@ bridge_free(bridge_info_t *bridge)
tor_free(bridge);
}
-/** A list of pluggable transports found in torrc. */
-static smartlist_t *transport_list = NULL;
-
-/** Mark every entry of the transport list to be removed on our next call to
- * sweep_transport_list unless it has first been un-marked. */
-void
-mark_transport_list(void)
-{
- if (!transport_list)
- transport_list = smartlist_new();
- SMARTLIST_FOREACH(transport_list, transport_t *, t,
- t->marked_for_removal = 1);
-}
-
-/** Remove every entry of the transport list that was marked with
- * mark_transport_list if it has not subsequently been un-marked. */
-void
-sweep_transport_list(void)
-{
- if (!transport_list)
- transport_list = smartlist_new();
- SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, t) {
- if (t->marked_for_removal) {
- SMARTLIST_DEL_CURRENT(transport_list, t);
- transport_free(t);
- }
- } SMARTLIST_FOREACH_END(t);
-}
-
-/** Initialize the pluggable transports list to empty, creating it if
- * needed. */
-void
-clear_transport_list(void)
-{
- if (!transport_list)
- transport_list = smartlist_new();
- SMARTLIST_FOREACH(transport_list, transport_t *, t, transport_free(t));
- smartlist_clear(transport_list);
-}
-
-/** Free the pluggable transport struct <b>transport</b>. */
-void
-transport_free(transport_t *transport)
-{
- if (!transport)
- return;
-
- tor_free(transport->name);
- tor_free(transport);
-}
-
-/** Returns the transport in our transport list that has the name <b>name</b>.
- * Else returns NULL. */
-transport_t *
-transport_get_by_name(const char *name)
-{
- tor_assert(name);
-
- if (!transport_list)
- return NULL;
-
- SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, transport) {
- if (!strcmp(transport->name, name))
- return transport;
- } SMARTLIST_FOREACH_END(transport);
-
- return NULL;
-}
-
-/** Returns a transport_t struct for a transport proxy supporting the
- protocol <b>name</b> listening at <b>addr</b>:<b>port</b> using
- SOCKS version <b>socks_ver</b>. */
-transport_t *
-transport_new(const tor_addr_t *addr, uint16_t port,
- const char *name, int socks_ver)
-{
- transport_t *t = tor_malloc_zero(sizeof(transport_t));
-
- tor_addr_copy(&t->addr, addr);
- t->port = port;
- t->name = tor_strdup(name);
- t->socks_version = socks_ver;
-
- return t;
-}
-
-/** Resolve any conflicts that the insertion of transport <b>t</b>
- * might cause.
- * Return 0 if <b>t</b> is OK and should be registered, 1 if there is
- * a transport identical to <b>t</b> already registered and -1 if
- * <b>t</b> cannot be added due to conflicts. */
-static int
-transport_resolve_conflicts(transport_t *t)
-{
- /* This is how we resolve transport conflicts:
-
- If there is already a transport with the same name and addrport,
- we either have duplicate torrc lines OR we are here post-HUP and
- this transport was here pre-HUP as well. In any case, mark the
- old transport so that it doesn't get removed and ignore the new
- one. Our caller has to free the new transport so we return '1' to
- signify this.
-
- If there is already a transport with the same name but different
- addrport:
- * if it's marked for removal, it means that it either has a lower
- priority than 't' in torrc (otherwise the mark would have been
- cleared by the paragraph above), or it doesn't exist at all in
- the post-HUP torrc. We destroy the old transport and register 't'.
- * if it's *not* marked for removal, it means that it was newly
- added in the post-HUP torrc or that it's of higher priority, in
- this case we ignore 't'. */
- transport_t *t_tmp = transport_get_by_name(t->name);
- if (t_tmp) { /* same name */
- if (tor_addr_eq(&t->addr, &t_tmp->addr) && (t->port == t_tmp->port)) {
- /* same name *and* addrport */
- t_tmp->marked_for_removal = 0;
- return 1;
- } else { /* same name but different addrport */
- if (t_tmp->marked_for_removal) { /* marked for removal */
- log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' "
- "but there was already a transport marked for deletion at "
- "'%s:%u'. We deleted the old transport and registered the "
- "new one.", t->name, fmt_addr(&t->addr), t->port,
- fmt_addr(&t_tmp->addr), t_tmp->port);
- smartlist_remove(transport_list, t_tmp);
- transport_free(t_tmp);
- } else { /* *not* marked for removal */
- log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' "
- "but the same transport already exists at '%s:%u'. "
- "Skipping.", t->name, fmt_addr(&t->addr), t->port,
- fmt_addr(&t_tmp->addr), t_tmp->port);
- return -1;
- }
- }
- }
-
- return 0;
-}
-
-/** Add transport <b>t</b> to the internal list of pluggable
- * transports.
- * Returns 0 if the transport was added correctly, 1 if the same
- * transport was already registered (in this case the caller must
- * free the transport) and -1 if there was an error. */
-int
-transport_add(transport_t *t)
-{
- int r;
- tor_assert(t);
-
- r = transport_resolve_conflicts(t);
-
- switch (r) {
- case 0: /* should register transport */
- if (!transport_list)
- transport_list = smartlist_new();
- smartlist_add(transport_list, t);
- return 0;
- default: /* let our caller know the return code */
- return r;
- }
-}
-
-/** Remember a new pluggable transport proxy at <b>addr</b>:<b>port</b>.
- * <b>name</b> is set to the name of the protocol this proxy uses.
- * <b>socks_ver</b> is set to the SOCKS version of the proxy. */
-int
-transport_add_from_config(const tor_addr_t *addr, uint16_t port,
- const char *name, int socks_ver)
-{
- transport_t *t = transport_new(addr, port, name, socks_ver);
-
- int r = transport_add(t);
-
- switch (r) {
- case -1:
- default:
- log_notice(LD_GENERAL, "Could not add transport %s at %s:%u. Skipping.",
- t->name, fmt_addr(&t->addr), t->port);
- transport_free(t);
- return -1;
- case 1:
- log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.",
- t->name, fmt_addr(&t->addr), t->port);
- transport_free(t); /* falling */
- return 0;
- case 0:
- log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.",
- t->name, fmt_addr(&t->addr), t->port);
- return 0;
- }
-}
/** Return a bridge pointer if <b>ri</b> is one of our known bridges
* (either by comparing keys if possible, else by comparing addr/port).
@@ -5800,10 +5607,7 @@ entry_guards_free_all(void)
entry_guards = NULL;
}
clear_bridge_list();
- clear_transport_list();
smartlist_free(bridge_list);
- smartlist_free(transport_list);
bridge_list = NULL;
- transport_list = NULL;
}
diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h
index 984d04a99..a7beccebb 100644
--- a/src/or/circuitbuild.h
+++ b/src/or/circuitbuild.h
@@ -12,21 +12,6 @@
#ifndef _TOR_CIRCUITBUILD_H
#define _TOR_CIRCUITBUILD_H
-/** Represents a pluggable transport proxy used by a bridge. */
-typedef struct {
- /** SOCKS version: One of PROXY_SOCKS4, PROXY_SOCKS5. */
- int socks_version;
- /** Name of pluggable transport protocol */
- char *name;
- /** Address of proxy */
- tor_addr_t addr;
- /** Port of proxy */
- uint16_t port;
- /** Boolean: We are re-parsing our transport list, and we are going to remove
- * this one if we don't find it in the list of configured transports. */
- unsigned marked_for_removal : 1;
-} transport_t;
-
char *circuit_list_path(origin_circuit_t *circ, int verbose);
char *circuit_list_path_for_controller(origin_circuit_t *circ);
void circuit_log_path(int severity, unsigned int domain,
@@ -82,8 +67,6 @@ int getinfo_helper_entry_guards(control_connection_t *conn,
void mark_bridge_list(void);
void sweep_bridge_list(void);
-void mark_transport_list(void);
-void sweep_transport_list(void);
int routerinfo_is_a_configured_bridge(const routerinfo_t *ri);
int node_is_a_configured_bridge(const node_t *node);
@@ -151,21 +134,12 @@ void circuit_build_times_network_circ_success(circuit_build_times_t *cbt);
/* DOCDOC circuit_build_times_get_bw_scale */
int circuit_build_times_get_bw_scale(networkstatus_t *ns);
-void clear_transport_list(void);
-int transport_add_from_config(const tor_addr_t *addr, uint16_t port,
- const char *name, int socks_ver);
-int transport_add(transport_t *t);
-void transport_free(transport_t *transport);
-transport_t *transport_new(const tor_addr_t *addr, uint16_t port,
- const char *name, int socks_ver);
-
/* DOCDOC find_transport_name_by_bridge_addrport */
const char *find_transport_name_by_bridge_addrport(const tor_addr_t *addr,
uint16_t port);
-
+typedef struct transport_t transport_t;
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);
#endif
diff --git a/src/or/connection.c b/src/or/connection.c
index 95101ef65..6c9b03b0b 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -34,6 +34,7 @@
#include "rendcommon.h"
#include "rephist.h"
#include "router.h"
+#include "transports.h"
#include "routerparse.h"
#ifdef USE_BUFFEREVENTS
diff --git a/src/or/router.c b/src/or/router.c
index 352c456f1..df44a76d8 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -27,6 +27,7 @@
#include "router.h"
#include "routerlist.h"
#include "routerparse.h"
+#include "transports.h"
/**
* \file router.c
@@ -2344,6 +2345,13 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
}
}
+ /* Add information about the pluggable transports we support. */
+ if (options->ServerTransportPlugin) {
+ char *pluggable_transports = pt_get_extra_info_descriptor_string();
+ if (pluggable_transports)
+ smartlist_add(chunks, pluggable_transports);
+ }
+
if (should_record_bridge_info(options) && write_stats_to_extrainfo) {
const char *bridge_stats = geoip_get_bridge_stats_extrainfo(now);
if (bridge_stats) {
diff --git a/src/or/transports.c b/src/or/transports.c
index 4ba239562..dd07a917e 100644
--- a/src/or/transports.c
+++ b/src/or/transports.c
@@ -39,13 +39,17 @@
* transport_t structs.
*
* When the managed proxy stops spitting METHOD lines (signified by a
- * '{S,C}METHODS DONE' message) we register all the transports
- * collected to the circuitbuild.c subsystem. At this point, the
- * pointers to transport_t can be transformed into dangling pointers
- * at any point by the circuitbuild.c subsystem, and so we replace all
- * transport_t pointers with strings describing the transport names.
- * We can still go from a transport name to a transport_t using the
- * fact that each transport name uniquely identifies a transport_t.
+ * '{S,C}METHODS DONE' message) we pass copies of its transports to
+ * the bridge subsystem. We keep copies of the 'transport_t's on the
+ * managed proxy to be able to associate the proxy with its
+ * transports, and we pass copies to the bridge subsystem so that
+ * transports can be associated with bridges.
+ * [ XXX We should try see whether the two copies are really needed
+ * and maybe cut it into a single copy of the 'transport_t' shared
+ * between the managed proxy and the bridge subsystem. Preliminary
+ * analysis shows that both copies are needed with the current code
+ * logic, because of race conditions that can cause dangling
+ * pointers. ]
*
* <b>In even more detail, this is what happens when a SIGHUP
* occurs:</b>
@@ -127,6 +131,219 @@ static INLINE void free_execve_args(char **arg);
protocol version. */
#define PROTO_VERSION_ONE 1
+/** A list of pluggable transports found in torrc. */
+static smartlist_t *transport_list = NULL;
+
+/** Returns a transport_t struct for a transport proxy supporting the
+ protocol <b>name</b> listening at <b>addr</b>:<b>port</b> using
+ SOCKS version <b>socks_ver</b>. */
+static transport_t *
+transport_new(const tor_addr_t *addr, uint16_t port,
+ const char *name, int socks_ver)
+{
+ transport_t *t = tor_malloc_zero(sizeof(transport_t));
+
+ tor_addr_copy(&t->addr, addr);
+ t->port = port;
+ t->name = tor_strdup(name);
+ t->socks_version = socks_ver;
+
+ return t;
+}
+
+/** Free the pluggable transport struct <b>transport</b>. */
+void
+transport_free(transport_t *transport)
+{
+ if (!transport)
+ return;
+
+ tor_free(transport->name);
+ tor_free(transport);
+}
+
+/** Mark every entry of the transport list to be removed on our next call to
+ * sweep_transport_list unless it has first been un-marked. */
+void
+mark_transport_list(void)
+{
+ if (!transport_list)
+ transport_list = smartlist_new();
+ SMARTLIST_FOREACH(transport_list, transport_t *, t,
+ t->marked_for_removal = 1);
+}
+
+/** Remove every entry of the transport list that was marked with
+ * mark_transport_list if it has not subsequently been un-marked. */
+void
+sweep_transport_list(void)
+{
+ if (!transport_list)
+ transport_list = smartlist_new();
+ SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, t) {
+ if (t->marked_for_removal) {
+ SMARTLIST_DEL_CURRENT(transport_list, t);
+ transport_free(t);
+ }
+ } SMARTLIST_FOREACH_END(t);
+}
+
+/** Initialize the pluggable transports list to empty, creating it if
+ * needed. */
+static void
+clear_transport_list(void)
+{
+ if (!transport_list)
+ transport_list = smartlist_new();
+ SMARTLIST_FOREACH(transport_list, transport_t *, t, transport_free(t));
+ smartlist_clear(transport_list);
+}
+
+/** Return a deep copy of <b>transport</b>. */
+static transport_t *
+transport_copy(const transport_t *transport)
+{
+ transport_t *new_transport = NULL;
+
+ tor_assert(transport);
+
+ new_transport = tor_malloc_zero(sizeof(transport_t));
+
+ new_transport->socks_version = transport->socks_version;
+ new_transport->name = tor_strdup(transport->name);
+ tor_addr_copy(&new_transport->addr, &transport->addr);
+ new_transport->port = transport->port;
+ new_transport->marked_for_removal = transport->marked_for_removal;
+
+ return new_transport;
+}
+
+/** Returns the transport in our transport list that has the name <b>name</b>.
+ * Else returns NULL. */
+transport_t *
+transport_get_by_name(const char *name)
+{
+ tor_assert(name);
+
+ if (!transport_list)
+ return NULL;
+
+ SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, transport) {
+ if (!strcmp(transport->name, name))
+ return transport;
+ } SMARTLIST_FOREACH_END(transport);
+
+ return NULL;
+}
+
+/** Resolve any conflicts that the insertion of transport <b>t</b>
+ * might cause.
+ * Return 0 if <b>t</b> is OK and should be registered, 1 if there is
+ * a transport identical to <b>t</b> already registered and -1 if
+ * <b>t</b> cannot be added due to conflicts. */
+static int
+transport_resolve_conflicts(const transport_t *t)
+{
+ /* This is how we resolve transport conflicts:
+
+ If there is already a transport with the same name and addrport,
+ we either have duplicate torrc lines OR we are here post-HUP and
+ this transport was here pre-HUP as well. In any case, mark the
+ old transport so that it doesn't get removed and ignore the new
+ one. Our caller has to free the new transport so we return '1' to
+ signify this.
+
+ If there is already a transport with the same name but different
+ addrport:
+ * if it's marked for removal, it means that it either has a lower
+ priority than 't' in torrc (otherwise the mark would have been
+ cleared by the paragraph above), or it doesn't exist at all in
+ the post-HUP torrc. We destroy the old transport and register 't'.
+ * if it's *not* marked for removal, it means that it was newly
+ added in the post-HUP torrc or that it's of higher priority, in
+ this case we ignore 't'. */
+ transport_t *t_tmp = transport_get_by_name(t->name);
+ if (t_tmp) { /* same name */
+ if (tor_addr_eq(&t->addr, &t_tmp->addr) && (t->port == t_tmp->port)) {
+ /* same name *and* addrport */
+ t_tmp->marked_for_removal = 0;
+ return 1;
+ } else { /* same name but different addrport */
+ if (t_tmp->marked_for_removal) { /* marked for removal */
+ log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' "
+ "but there was already a transport marked for deletion at "
+ "'%s:%u'. We deleted the old transport and registered the "
+ "new one.", t->name, fmt_addr(&t->addr), t->port,
+ fmt_addr(&t_tmp->addr), t_tmp->port);
+ smartlist_remove(transport_list, t_tmp);
+ transport_free(t_tmp);
+ } else { /* *not* marked for removal */
+ log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' "
+ "but the same transport already exists at '%s:%u'. "
+ "Skipping.", t->name, fmt_addr(&t->addr), t->port,
+ fmt_addr(&t_tmp->addr), t_tmp->port);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/** Add transport <b>t</b> to the internal list of pluggable
+ * transports.
+ * Returns 0 if the transport was added correctly, 1 if the same
+ * transport was already registered (in this case the caller must
+ * free the transport) and -1 if there was an error. */
+static int
+transport_add(transport_t *t)
+{
+ int r;
+ tor_assert(t);
+
+ r = transport_resolve_conflicts(t);
+
+ switch (r) {
+ case 0: /* should register transport */
+ if (!transport_list)
+ transport_list = smartlist_new();
+ smartlist_add(transport_list, t);
+ return 0;
+ default: /* let our caller know the return code */
+ return r;
+ }
+}
+
+/** Remember a new pluggable transport proxy at <b>addr</b>:<b>port</b>.
+ * <b>name</b> is set to the name of the protocol this proxy uses.
+ * <b>socks_ver</b> is set to the SOCKS version of the proxy. */
+int
+transport_add_from_config(const tor_addr_t *addr, uint16_t port,
+ const char *name, int socks_ver)
+{
+ transport_t *t = transport_new(addr, port, name, socks_ver);
+
+ int r = transport_add(t);
+
+ switch (r) {
+ case -1:
+ default:
+ log_notice(LD_GENERAL, "Could not add transport %s at %s:%u. Skipping.",
+ t->name, fmt_addr(&t->addr), t->port);
+ transport_free(t);
+ return -1;
+ case 1:
+ log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.",
+ t->name, fmt_addr(&t->addr), t->port);
+ transport_free(t); /* falling */
+ return 0;
+ case 0:
+ log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.",
+ t->name, fmt_addr(&t->addr), t->port);
+ return 0;
+ }
+}
+
/** List of unconfigured managed proxies. */
static smartlist_t *managed_proxy_list = NULL;
/** Number of still unconfigured proxies. */
@@ -217,11 +434,11 @@ proxy_needs_restart(const managed_proxy_t *mp)
{
/* mp->transport_to_launch is populated with the names of the
transports that must be launched *after* the SIGHUP.
- mp->transports is populated with the names of the transports that
- were launched *before* the SIGHUP.
+ mp->transports is populated with the transports that were
+ launched *before* the SIGHUP.
- If the two lists contain the same strings, we don't need to
- restart the proxy, since it already does what we want. */
+ Check if all the transports that need to be launched are already
+ launched: */
tor_assert(smartlist_len(mp->transports_to_launch) > 0);
tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
@@ -229,11 +446,11 @@ proxy_needs_restart(const managed_proxy_t *mp)
if (smartlist_len(mp->transports_to_launch) != smartlist_len(mp->transports))
goto needs_restart;
- SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t_t_l) {
- if (!smartlist_string_isin(mp->transports, t_t_l))
+ SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
+ if (!smartlist_string_isin(mp->transports_to_launch, t->name))
goto needs_restart;
- } SMARTLIST_FOREACH_END(t_t_l);
+ } SMARTLIST_FOREACH_END(t);
return 0;
@@ -245,6 +462,7 @@ proxy_needs_restart(const managed_proxy_t *mp)
* preparations and then flag its state so that it will be relaunched
* in the next tick. */
static void
+
proxy_prepare_for_restart(managed_proxy_t *mp)
{
transport_t *t_tmp = NULL;
@@ -255,16 +473,17 @@ proxy_prepare_for_restart(managed_proxy_t *mp)
tor_process_handle_destroy(mp->process_handle, 1);
mp->process_handle = NULL;
- /* destroy all its old transports. we no longer use them. */
- SMARTLIST_FOREACH_BEGIN(mp->transports, const char *, t_name) {
- t_tmp = transport_get_by_name(t_name);
+ /* destroy all its registered transports, since we will no longer
+ use them. */
+ SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
+ t_tmp = transport_get_by_name(t->name);
if (t_tmp)
t_tmp->marked_for_removal = 1;
- } SMARTLIST_FOREACH_END(t_name);
+ } SMARTLIST_FOREACH_END(t);
sweep_transport_list();
- /* free the transport names in mp->transports */
- SMARTLIST_FOREACH(mp->transports, char *, t_name, tor_free(t_name));
+ /* free the transport in mp->transports */
+ SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
smartlist_clear(mp->transports);
/* flag it as an infant proxy so that it gets launched on next tick */
@@ -315,6 +534,7 @@ launch_managed_proxy(managed_proxy_t *mp)
void
pt_configure_remaining_proxies(void)
{
+ int at_least_a_proxy_config_finished = 0;
smartlist_t *tmp = smartlist_new();
log_debug(LD_CONFIG, "Configuring remaining managed proxies (%d)!",
@@ -352,11 +572,17 @@ pt_configure_remaining_proxies(void)
if (!proxy_configuration_finished(mp))
configure_proxy(mp);
+ if (proxy_configuration_finished(mp))
+ at_least_a_proxy_config_finished = 1;
+
} SMARTLIST_FOREACH_END(mp);
smartlist_free(tmp);
check_if_restarts_needed = 0;
assert_unconfigured_count_ok();
+
+ if (at_least_a_proxy_config_finished)
+ mark_my_descriptor_dirty("configured managed proxies");
}
#ifdef _WIN32
@@ -468,68 +694,48 @@ configure_proxy(managed_proxy_t *mp)
/** Register server managed proxy <b>mp</b> transports to state */
static void
-register_server_proxy(managed_proxy_t *mp)
+register_server_proxy(const managed_proxy_t *mp)
{
- /* After we register this proxy's transports, we switch its
- mp->transports to a list containing strings of its transport
- names. (See transports.h) */
- smartlist_t *sm_tmp = smartlist_new();
-
tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
+
SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
save_transport_to_state(t->name, &t->addr, t->port);
log_notice(LD_GENERAL, "Registered server transport '%s' at '%s:%d'",
t->name, fmt_addr(&t->addr), (int)t->port);
- smartlist_add(sm_tmp, tor_strdup(t->name));
} SMARTLIST_FOREACH_END(t);
-
- /* Since server proxies don't register their transports in the
- circuitbuild.c subsystem, it's our duty to free them when we
- switch mp->transports to strings. */
- SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
- smartlist_free(mp->transports);
-
- mp->transports = sm_tmp;
}
/** Register all the transports supported by client managed proxy
* <b>mp</b> to the bridge subsystem. */
static void
-register_client_proxy(managed_proxy_t *mp)
+register_client_proxy(const managed_proxy_t *mp)
{
int r;
- /* After we register this proxy's transports, we switch its
- mp->transports to a list containing strings of its transport
- names. (See transports.h) */
- smartlist_t *sm_tmp = smartlist_new();
tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
+
SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
- r = transport_add(t);
+ transport_t *transport_tmp = transport_copy(t);
+ r = transport_add(transport_tmp);
switch (r) {
case -1:
log_notice(LD_GENERAL, "Could not add transport %s. Skipping.", t->name);
- transport_free(t);
+ transport_free(transport_tmp);
break;
case 0:
log_info(LD_GENERAL, "Succesfully registered transport %s", t->name);
- smartlist_add(sm_tmp, tor_strdup(t->name));
break;
case 1:
log_info(LD_GENERAL, "Succesfully registered transport %s", t->name);
- smartlist_add(sm_tmp, tor_strdup(t->name));
- transport_free(t);
+ transport_free(transport_tmp);
break;
}
} SMARTLIST_FOREACH_END(t);
-
- smartlist_free(mp->transports);
- mp->transports = sm_tmp;
}
/** Register the transports of managed proxy <b>mp</b>. */
static INLINE void
-register_proxy(managed_proxy_t *mp)
+register_proxy(const managed_proxy_t *mp)
{
if (mp->is_server)
register_server_proxy(mp);
@@ -542,10 +748,7 @@ static void
managed_proxy_destroy(managed_proxy_t *mp,
int also_terminate_process)
{
- if (mp->conf_state != PT_PROTO_COMPLETED)
- SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
- else
- SMARTLIST_FOREACH(mp->transports, char *, t_name, tor_free(t_name));
+ SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
/* free the transports smartlist */
smartlist_free(mp->transports);
@@ -1181,6 +1384,64 @@ pt_prepare_proxy_list_for_config_read(void)
tor_assert(unconfigured_proxies_n == 0);
}
+/** Return the pluggable transport string that we should display in
+ * our extra-info descriptor. If we shouldn't display such a string,
+ * or we have nothing to display, return NULL. The string is
+ * allocated on the heap and it's the responsibility of the caller to
+ * free it. */
+char *
+pt_get_extra_info_descriptor_string(void)
+{
+ char *the_string = NULL;
+ smartlist_t *string_chunks = NULL;
+
+ if (!managed_proxy_list)
+ return NULL;
+
+ string_chunks = smartlist_new();
+
+ /* For each managed proxy, add its transports to the chunks list. */
+ SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
+ if ((!mp->is_server) || (mp->conf_state != PT_PROTO_COMPLETED))
+ continue;
+
+ tor_assert(mp->transports);
+
+ SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
+ /* If the transport proxy returned "0.0.0.0" as its address, and
+ * we know our external IP address, use it. Otherwise, use the
+ * returned address. */
+ const char *addr_str = fmt_addr(&t->addr);
+ uint32_t external_ip_address = 0;
+ if (tor_addr_is_null(&t->addr) &&
+ router_pick_published_address(get_options(),
+ &external_ip_address) >= 0) {
+ /* returned addr was 0.0.0.0 and we found our external IP
+ address: use it. */
+ addr_str = fmt_addr32(external_ip_address);
+ }
+
+ smartlist_add_asprintf(string_chunks,
+ "transport %s %s:%u",
+ t->name, addr_str, t->port);
+ } SMARTLIST_FOREACH_END(t);
+
+ } SMARTLIST_FOREACH_END(mp);
+
+ if (smartlist_len(string_chunks) == 0) {
+ smartlist_free(string_chunks);
+ return NULL;
+ }
+
+ /* Join all the chunks into the final string. */
+ the_string = smartlist_join_strings(string_chunks, "\n", 1, NULL);
+
+ SMARTLIST_FOREACH(string_chunks, char *, s, tor_free(s));
+ smartlist_free(string_chunks);
+
+ return the_string;
+}
+
/** The tor config was read.
* Destroy all managed proxies that were marked by a previous call to
* prepare_proxy_list_for_config_read() and are not used by the new
@@ -1204,6 +1465,12 @@ sweep_proxy_list(void)
void
pt_free_all(void)
{
+ if (transport_list) {
+ clear_transport_list();
+ smartlist_free(transport_list);
+ transport_list = NULL;
+ }
+
if (managed_proxy_list) {
/* If the proxy is in PT_PROTO_COMPLETED, it has registered its
transports and it's the duty of the circuitbuild.c subsystem to
diff --git a/src/or/transports.h b/src/or/transports.h
index 02f159a5d..3fd97f8c2 100644
--- a/src/or/transports.h
+++ b/src/or/transports.h
@@ -11,6 +11,30 @@
#ifndef TOR_TRANSPORTS_H
#define TOR_TRANSPORTS_H
+/** Represents a pluggable transport used by a bridge. */
+typedef struct transport_t {
+ /** SOCKS version: One of PROXY_SOCKS4, PROXY_SOCKS5. */
+ int socks_version;
+ /** Name of pluggable transport protocol */
+ char *name;
+ /** The IP address where the transport bound and is waiting for
+ * connections. */
+ tor_addr_t addr;
+ /** Port of proxy */
+ uint16_t port;
+ /** Boolean: We are re-parsing our transport list, and we are going to remove
+ * this one if we don't find it in the list of configured transports. */
+ unsigned marked_for_removal : 1;
+} transport_t;
+
+void mark_transport_list(void);
+void sweep_transport_list(void);
+int transport_add_from_config(const tor_addr_t *addr, uint16_t port,
+ const char *name, int socks_ver);
+void transport_free(transport_t *transport);
+
+transport_t *transport_get_by_name(const char *name);
+
void pt_kickstart_proxy(const smartlist_t *transport_list, char **proxy_argv,
int is_server);
@@ -23,6 +47,8 @@ void pt_configure_remaining_proxies(void);
int pt_proxies_configuration_pending(void);
+char *pt_get_extra_info_descriptor_string(void);
+
void pt_free_all(void);
void pt_prepare_proxy_list_for_config_read(void);
@@ -68,28 +94,7 @@ typedef struct {
smartlist_t *transports_to_launch;
/* The 'transports' list contains all the transports this proxy has
- launched.
-
- Before a managed_proxy_t reaches the PT_PROTO_COMPLETED phase,
- this smartlist contains a 'transport_t' for every transport it
- has launched.
-
- When the managed_proxy_t reaches the PT_PROTO_COMPLETED phase, it
- registers all its transports to the circuitbuild.c subsystem. At
- that point the 'transport_t's are owned by the circuitbuild.c
- subsystem.
-
- To avoid carrying dangling 'transport_t's in this smartlist,
- right before the managed_proxy_t reaches the PT_PROTO_COMPLETED
- phase we replace all 'transport_t's with strings of their
- transport names.
-
- So, tl;dr:
- When (conf_state != PT_PROTO_COMPLETED) this list carries
- (transport_t *).
- When (conf_state == PT_PROTO_COMPLETED) this list carries
- (char *).
- */
+ launched. */
smartlist_t *transports;
} managed_proxy_t;