#include "core/mainloop/mainloop.h"
+#include "feature/client/transports.h"
#include "feature/control/control_events.h"
#include "feature/dirauth/authmode.h"
}
/* In case we don't have a configured address, log that we will be using the
- * one discovered from the dirauth. */
+ * one discovered from the dirauth, and, if running a bridge, use the new IP
+ * for the bridge lines. */
const int idx = af_to_idx(tor_addr_family(addr));
if (tor_addr_is_null(&last_resolved_addrs[idx]) &&
!tor_addr_eq(&last_suggested_addrs[idx], addr)) {
log_notice(LD_CONFIG, "External address seen and suggested by a "
"directory authority: %s", fmt_addr(addr));
+ tor_addr_copy(&last_suggested_addrs[idx], addr);
+ pt_update_bridge_lines();
+ } else {
+ tor_addr_copy(&last_suggested_addrs[idx], addr);
}
- tor_addr_copy(&last_suggested_addrs[idx], addr);
}
/** Copy the last resolved address of family into addr_out.
t->name, fmt_addrport(&t->addr, t->port));
control_event_transport_launched("server", t->name, &t->addr, t->port);
} SMARTLIST_FOREACH_END(t);
+ pt_update_bridge_lines();
}
/** Register all the transports supported by client managed proxy
return the_string;
}
+/** Log the bridge lines that clients can use to connect. */
+void
+pt_update_bridge_lines(void)
+{
+ char fingerprint[FINGERPRINT_LEN+1];
+ smartlist_t *string_chunks = NULL;
+
+ if (!server_identity_key_is_set() || !managed_proxy_list)
+ return;
+
+ if (crypto_pk_get_fingerprint(get_server_identity_key(), fingerprint, 0)<0) {
+ log_err(LD_BUG, "Error computing fingerprint");
+ return;
+ }
+
+ string_chunks = smartlist_new();
+
+ SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
+ if (!mp->is_server)
+ continue;
+
+ tor_assert(mp->transports);
+
+ SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
+ char *transport_args = NULL;
+ const char *saddr = NULL;
+
+ /* If the transport proxy returned "0.0.0.0" as its address, display
+ * our external address if we know it, or a placeholder if we don't */
+ if (tor_addr_is_null(&t->addr)) {
+ tor_addr_t addr;
+ /* Attempt to find the IPv4 and then attempt to find the IPv6 if we
+ * can't find it. */
+ bool found = relay_find_addr_to_publish(get_options(), AF_INET,
+ RELAY_FIND_ADDR_NO_FLAG,
+ &addr);
+ if (!found) {
+ found = relay_find_addr_to_publish(get_options(), AF_INET6,
+ RELAY_FIND_ADDR_NO_FLAG, &addr);
+ }
+ if (found && !tor_addr_is_null(&addr)) {
+ saddr = fmt_and_decorate_addr(&addr);
+ } else {
+ saddr = "<IP ADDRESS>";
+ }
+ } else {
+ saddr = fmt_and_decorate_addr(&t->addr);
+ }
+
+ /* If this transport has any arguments with it, prepend a space
+ * to them so that we can add them to the transport line, and replace
+ * commas with spaces to make it a valid bridge line. */
+ if (t->extra_info_args) {
+ tor_asprintf(&transport_args, " %s", t->extra_info_args);
+ for (int i = 0; transport_args[i]; i++) {
+ if (transport_args[i] == ',') {
+ transport_args[i] = ' ';
+ }
+ }
+ }
+
+ smartlist_add_asprintf(string_chunks, "Bridge %s %s:%d %s%s",
+ t->name, saddr, t->port, fingerprint,
+ transport_args ? transport_args : "");
+ tor_free(transport_args);
+ } SMARTLIST_FOREACH_END(t);
+ } SMARTLIST_FOREACH_END(mp);
+
+ /* If we have any valid bridgelines, join them into a single string, and
+ * save them to disk. Don't create an empty file. */
+ if (smartlist_len(string_chunks) != 0) {
+ char *str = smartlist_join_strings(string_chunks, "\n", 1, NULL);
+ char *fname = get_datadir_fname("bridgelines");
+ if (write_str_to_file_if_not_equal(fname, str)) {
+ log_warn(LD_FS, "Couldn't save bridge lines to disk");
+ } else {
+ log_info(LD_FS, "Saved bridge lines to disk");
+ }
+ tor_free(fname);
+ tor_free(str);
+ }
+
+ SMARTLIST_FOREACH(string_chunks, char *, s, tor_free(s));
+ smartlist_free(string_chunks);
+}
+
/** Stringify the SOCKS arguments in <b>socks_args</b> according to
* 180_pluggable_transport.txt. The string is allocated on the heap
* and it's the responsibility of the caller to free it after use. */