/** Expected identity digest, or all zero bytes if we don't know what the
* digest should be. */
char identity[DIGEST_LEN];
+
+ /** Name of pluggable transport protocol taken from its config line.
+ Free'd when we match the bridge with a transport at
+ match_bridges_with_transports(). */
+ char *transport_name_config;
+
+ /** Pluggable transport proxy this bridge uses. */
+ transport_info_t *transport;
+
/** When should we next try to fetch a descriptor for this bridge? */
download_status_t fetch_status;
} bridge_info_t;
smartlist_clear(bridge_list);
}
+/** A list of pluggable transports found in torrc. */
+static smartlist_t *transport_list = NULL;
+
+/** Initialize the pluggable transports list to empty, creating it if
+ needed. */
+void
+clear_transport_list(void)
+{
+ if (!transport_list)
+ transport_list = smartlist_create();
+ SMARTLIST_FOREACH(transport_list, transport_info_t *, t, transport_free(t));
+ smartlist_clear(transport_list);
+}
+
+/**
+ Free the transport_info_t <b>transport</b>.
+*/
+static void
+transport_free(transport_info_t *transport)
+{
+ tor_free(transport->name);
+ tor_free(transport);
+}
+
+/** 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.
+*/
+void
+transport_add_from_config(const tor_addr_t *addr, uint16_t port,
+ const char *name, int socks_ver)
+{
+ transport_info_t *t = tor_malloc_zero(sizeof(transport_info_t));
+
+ tor_addr_copy(&t->addr, addr);
+ t->port = port;
+ /** check strdup return */
+ t->name = strdup(name);
+ t->socks_version = socks_ver;
+ if (!transport_list)
+ transport_list = smartlist_create();
+
+ smartlist_add(transport_list, t);
+}
+
+/**
+ Attempts to map every transport found on torrc to it's
+ corresponding bridge.
+ Returns 1 on a succesfull bijective map, otherwise it returns -1.
+*/
+int
+match_bridges_with_transports(void)
+{
+ /* Used to check if a transport was finally found for a bridge */
+ int found_match=0;
+ /* Number of matches. */
+ int n_matches=0;
+ /* Number of transports. */
+ int n_transports=0;
+
+ tor_assert(transport_list);
+ tor_assert(bridge_list);
+
+ /* Iterate bridges */
+ SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b)
+ {
+ /* Skip bridges without transports. */
+ if (!b->transport_name_config)
+ continue;
+ found_match=0;
+ /* Iterate transports */
+ SMARTLIST_FOREACH_BEGIN(transport_list, transport_info_t *, t)
+ {
+ /* If the transport name of the transport is the same as the
+ transport name of the bridge, we have a match. */
+ if (!strcmp(b->transport_name_config, t->name)) {
+ found_match=1;
+ n_matches++;
+ b->transport = t;
+ tor_free(b->transport_name_config);
+ log_warn(LD_CONFIG, "Matched transport '%s'", t->name);
+ continue;
+ }
+ } SMARTLIST_FOREACH_END(t);
+ if (!found_match) {
+ log_warn(LD_CONFIG, "Couldn't find transport "
+ "match for %s!\n", b->transport_name_config);
+ return -1;
+ }
+ } SMARTLIST_FOREACH_END(b);
+
+ /* count number of transports to see if there were transports
+ that didn't get matched to a bridge. */
+ SMARTLIST_FOREACH(transport_list, transport_info_t *, t, n_transports++);
+ if (n_transports != n_matches) {
+ log_warn(LD_CONFIG, "You have %d transports and we only "
+ "managed to match %d of them!\n", n_transports, n_matches);
+ return -1;
+ }
+
+ return 1;
+}
+
/** 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).
* Else return NULL. */
* bridge in our list, unmark it, and don't actually add anything new. */
void
bridge_add_from_config(const tor_addr_t *addr, uint16_t port,
- const char *digest)
+ const char *digest, const char *transport_name)
{
bridge_info_t *b;
b->port = port;
if (digest)
memcpy(b->identity, digest, DIGEST_LEN);
+ if (transport_name)
+ b->transport_name_config = strdup(transport_name);
b->fetch_status.schedule = DL_SCHED_BRIDGE;
if (!bridge_list)
bridge_list = smartlist_create();
entry_guards = NULL;
}
clear_bridge_list();
+ clear_transport_list();
smartlist_free(bridge_list);
bridge_list = NULL;
}
#ifndef _TOR_CIRCUITBUILD_H
#define _TOR_CIRCUITBUILD_H
+/**
+ Represents a pluggable transport proxy used by a bridge. */
+typedef struct {
+ /* SOCKS version */
+ int socks_version;
+
+ /* Name of pluggable transport protocol */
+ char *name;
+
+ /* Address of proxy */
+ tor_addr_t addr;
+
+ /* Port of proxy */
+ uint16_t port;
+} transport_info_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,
void learned_router_identity(const tor_addr_t *addr, uint16_t port,
const char *digest);
void bridge_add_from_config(const tor_addr_t *addr, uint16_t port,
- const char *digest);
+ const char *digest,
+ const char *transport_name);
void retry_bridge_descriptor_fetch_directly(const char *digest);
void fetch_bridge_descriptors(or_options_t *options, time_t now);
void learned_bridge_descriptor(routerinfo_t *ri, int from_cache);
int circuit_build_times_get_bw_scale(networkstatus_t *ns);
+
+void clear_transport_list(void);
+int match_bridges_with_transports(void);
+void transport_add_from_config(const tor_addr_t *addr, uint16_t port,
+ const char *name, int socks_ver);
#endif
return -1;
if (options->ClientTransportPlugin) {
+ clear_transport_list();
for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
if (parse_transport_line(cl->value, 0)<0) {
log_warn(LD_BUG,
sweep_bridge_list();
}
+ /** Okay, we have Bridges and we have ClientTransportPlugins. Let's
+ match them together. */
+ if (options->Bridges && options->ClientTransportPlugin) {
+ if (match_bridges_with_transports() < 0)
+ return -1;
+ }
+
if (running_tor && rend_config_services(options, 0)<0) {
log_warn(LD_BUG,
"Previously validated hidden services line could not be added!");
fmt_addr(&addr), (int)port, transport_name,
fingerprint ? fingerprint : "no key listed");
bridge_add_from_config(&addr, port,
- fingerprint ? digest : NULL/*, transport_name*/);
+ fingerprint ? digest : NULL, transport_name);
}
r = 0;
if (!validate_only) {
log_warn(LD_DIR, "Transport %s at %s:%d", name,
fmt_addr(&addr), (int)port);
- /* transport_add_from_config(&addr, port,
- fingerprint ? digest : NULL, transport); */
+ transport_add_from_config(&addr, port, name,
+ socks_ver);
}
r = 0;