summaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
Diffstat (limited to 'src/or')
-rw-r--r--src/or/channel.c4
-rw-r--r--src/or/channeltls.c5
-rw-r--r--src/or/circuitlist.c4
-rw-r--r--src/or/circuitlist.h1
-rw-r--r--src/or/circuitmux.c3
-rw-r--r--src/or/config.c103
-rw-r--r--src/or/config.h15
-rw-r--r--src/or/confparse.c16
-rw-r--r--src/or/confparse.h2
-rw-r--r--src/or/dns.c8
-rw-r--r--src/or/or.h11
-rw-r--r--src/or/relay.c42
-rw-r--r--src/or/relay.h3
-rw-r--r--src/or/transports.c105
-rw-r--r--src/or/transports.h10
15 files changed, 274 insertions, 58 deletions
diff --git a/src/or/channel.c b/src/or/channel.c
index 98c23d91ea..05f269b8fa 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -3090,7 +3090,7 @@ channel_get_for_extend(const char *digest,
if (chan->state != CHANNEL_STATE_OPEN) {
/* If the address matches, don't launch a new connection for this
* circuit. */
- if (!channel_matches_target_addr_for_extend(chan, target_addr))
+ if (channel_matches_target_addr_for_extend(chan, target_addr))
++n_inprogress_goodaddr;
continue;
}
@@ -4106,7 +4106,7 @@ channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info)
}
/**
- * Check if a channel matches a given target address
+ * Check if a channel matches a given target address; return true iff we do.
*
* This function calls into the lower layer and asks if this channel thinks
* it matches a given target address for circuit extension purposes.
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index 60693daeb2..d758d22d82 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -546,7 +546,7 @@ channel_tls_matches_extend_info_method(channel_t *chan,
}
/**
- * Check if we match a target address
+ * Check if we match a target address; return true iff we do.
*
* This implements the matches_target method for channel_tls t_; the upper
* layer wants to know if this channel matches a target address when extending
@@ -563,8 +563,7 @@ channel_tls_matches_target_method(channel_t *chan,
tor_assert(target);
tor_assert(tlschan->conn);
- return tor_addr_compare(&(tlschan->conn->real_addr),
- target, CMP_EXACT);
+ return tor_addr_eq(&(tlschan->conn->real_addr), target);
}
/**
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 5e51301ceb..85bacce485 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -682,6 +682,7 @@ init_circuit_base(circuit_t *circ)
circ->package_window = circuit_initial_package_window();
circ->deliver_window = CIRCWINDOW_START;
+ cell_queue_init(&circ->n_chan_cells);
circuit_add(circ);
}
@@ -727,6 +728,7 @@ or_circuit_new(circid_t p_circ_id, channel_t *p_chan)
circuit_set_p_circid_chan(circ, p_circ_id, p_chan);
circ->remaining_relay_early_cells = MAX_RELAY_EARLY_CELLS_PER_CIRCUIT;
+ cell_queue_init(&circ->p_chan_cells);
init_circuit_base(TO_CIRCUIT(circ));
@@ -1638,7 +1640,7 @@ marked_circuit_free_cells(circuit_t *circ)
}
/** Return the number of cells used by the circuit <b>c</b>'s cell queues. */
-static size_t
+STATIC size_t
n_cells_in_circ_queues(const circuit_t *c)
{
size_t n = c->n_chan_cells.n;
diff --git a/src/or/circuitlist.h b/src/or/circuitlist.h
index a5a54859b2..4e56f5264f 100644
--- a/src/or/circuitlist.h
+++ b/src/or/circuitlist.h
@@ -72,6 +72,7 @@ void channel_note_destroy_not_pending(channel_t *chan, circid_t id);
#ifdef CIRCUITLIST_PRIVATE
STATIC void circuit_free(circuit_t *circ);
+STATIC size_t n_cells_in_circ_queues(const circuit_t *c);
#endif
#endif
diff --git a/src/or/circuitmux.c b/src/or/circuitmux.c
index 081416368e..47b423066a 100644
--- a/src/or/circuitmux.c
+++ b/src/or/circuitmux.c
@@ -383,6 +383,7 @@ circuitmux_alloc(void)
rv = tor_malloc_zero(sizeof(*rv));
rv->chanid_circid_map = tor_malloc_zero(sizeof(*( rv->chanid_circid_map)));
HT_INIT(chanid_circid_muxinfo_map, rv->chanid_circid_map);
+ cell_queue_init(&rv->destroy_cell_queue);
return rv;
}
@@ -510,7 +511,7 @@ circuitmux_mark_destroyed_circids_usable(circuitmux_t *cmux, channel_t *chan)
{
packed_cell_t *cell;
int n_bad = 0;
- for (cell = cmux->destroy_cell_queue.head; cell; cell = cell->next) {
+ TOR_SIMPLEQ_FOREACH(cell, &cmux->destroy_cell_queue.head, next) {
circid_t circid = 0;
if (packed_cell_is_destroy(chan, cell, &circid)) {
channel_mark_circid_usable(chan, circid);
diff --git a/src/or/config.c b/src/or/config.c
index 6d3b133389..ad6689ceef 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -9,6 +9,7 @@
* \brief Code to parse and interpret configuration files.
**/
+#define CONFIG_PRIVATE
#include "or.h"
#include "addressmap.h"
#include "channel.h"
@@ -280,6 +281,7 @@ static config_var_t option_vars_[] = {
V(IPv6Exit, BOOL, "0"),
VAR("ServerTransportPlugin", LINELIST, ServerTransportPlugin, NULL),
V(ServerTransportListenAddr, LINELIST, NULL),
+ V(ServerTransportOptions, LINELIST, NULL),
V(Socks4Proxy, STRING, NULL),
V(Socks5Proxy, STRING, NULL),
V(Socks5ProxyUsername, STRING, NULL),
@@ -508,10 +510,6 @@ static const config_var_t testing_tor_network_defaults[] = {
#ifdef _WIN32
static char *get_windows_conf_root(void);
#endif
-static int options_validate(or_options_t *old_options,
- or_options_t *options,
- or_options_t *default_options,
- int from_setconf, char **msg);
static int options_act_reversible(const or_options_t *old_options, char **msg);
static int options_act(const or_options_t *old_options);
static int options_transition_allowed(const or_options_t *old,
@@ -555,7 +553,7 @@ static void config_maybe_load_geoip_files_(const or_options_t *options,
#define OR_OPTIONS_MAGIC 9090909
/** Configuration format for or_options_t. */
-static config_format_t options_format = {
+STATIC config_format_t options_format = {
sizeof(or_options_t),
OR_OPTIONS_MAGIC,
STRUCT_OFFSET(or_options_t, magic_),
@@ -711,7 +709,7 @@ get_short_version(void)
/** Release additional memory allocated in options
*/
-static void
+STATIC void
or_options_free(or_options_t *options)
{
if (!options)
@@ -2348,7 +2346,7 @@ compute_publishserverdescriptor(or_options_t *options)
* Log line should stay empty. If it's 0, then give us a default log
* if there are no logs defined.
*/
-static int
+STATIC int
options_validate(or_options_t *old_options, or_options_t *options,
or_options_t *default_options, int from_setconf, char **msg)
{
@@ -3147,6 +3145,19 @@ options_validate(or_options_t *old_options, or_options_t *options,
"ServerTransportListenAddr line will be ignored.");
}
+ for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
+ /** If get_options_from_transport_options_line() fails with
+ 'transport' being NULL, it means that something went wrong
+ while parsing the ServerTransportOptions line. */
+ smartlist_t *options_sl =
+ get_options_from_transport_options_line(cl->value, NULL);
+ if (!options_sl)
+ REJECT("ServerTransportOptions did not parse. See logs for details.");
+
+ SMARTLIST_FOREACH(options_sl, char *, cp, tor_free(cp));
+ smartlist_free(options_sl);
+ }
+
if (options->ConstrainedSockets) {
/* If the user wants to constrain socket buffer use, make sure the desired
* limit is between MIN|MAX_TCPSOCK_BUFFER in k increments. */
@@ -3817,6 +3828,7 @@ options_init_from_torrc(int argc, char **argv)
}
if (command == CMD_HASH_PASSWORD) {
+ cf_defaults = tor_strdup("");
cf = tor_strdup("");
} else {
cf_defaults = load_torrc_from_disk(argc, argv, 1);
@@ -4580,6 +4592,63 @@ get_bindaddr_from_transport_listen_line(const char *line,const char *transport)
return addrport;
}
+/** Given a ServerTransportOptions <b>line</b>, return a smartlist
+ * with the options. Return NULL if the line was not well-formed.
+ *
+ * If <b>transport</b> is set, return NULL if the line is not
+ * referring to <b>transport</b>.
+ *
+ * The returned smartlist and its strings are allocated on the heap
+ * and it's the responsibility of the caller to free it. */
+smartlist_t *
+get_options_from_transport_options_line(const char *line,const char *transport)
+{
+ smartlist_t *items = smartlist_new();
+ smartlist_t *options = smartlist_new();
+ const char *parsed_transport = NULL;
+
+ smartlist_split_string(items, line, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+
+ if (smartlist_len(items) < 2) {
+ log_warn(LD_CONFIG,"Too few arguments on ServerTransportOptions line.");
+ goto err;
+ }
+
+ parsed_transport = smartlist_get(items, 0);
+ /* If 'transport' is given, check if it matches the one on the line */
+ if (transport && strcmp(transport, parsed_transport))
+ goto err;
+
+ SMARTLIST_FOREACH_BEGIN(items, const char *, option) {
+ if (option_sl_idx == 0) /* skip the transport field (first field)*/
+ continue;
+
+ /* validate that it's a k=v value */
+ if (!string_is_key_value(LOG_WARN, option)) {
+ log_warn(LD_CONFIG, "%s is not a k=v value.", escaped(option));
+ goto err;
+ }
+
+ /* add it to the options smartlist */
+ smartlist_add(options, tor_strdup(option));
+ log_debug(LD_CONFIG, "Added %s to the list of options", escaped(option));
+ } SMARTLIST_FOREACH_END(option);
+
+ goto done;
+
+ err:
+ SMARTLIST_FOREACH(options, char*, s, tor_free(s));
+ smartlist_free(options);
+ options = NULL;
+
+ done:
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+
+ return options;
+}
+
/** Given the name of a pluggable transport in <b>transport</b>, check
* the configuration file to see if the user has explicitly asked for
* it to listen on a specific port. Return a <address:port> string if
@@ -4600,6 +4669,26 @@ get_transport_bindaddr_from_config(const char *transport)
return NULL;
}
+/** Given the name of a pluggable transport in <b>transport</b>, check
+ * the configuration file to see if the user has asked us to pass any
+ * parameters to the pluggable transport. Return a smartlist
+ * containing the parameters, otherwise NULL. */
+smartlist_t *
+get_options_for_server_transport(const char *transport)
+{
+ config_line_t *cl;
+ const or_options_t *options = get_options();
+
+ for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
+ smartlist_t *options_sl =
+ get_options_from_transport_options_line(cl->value, transport);
+ if (options_sl)
+ return options_sl;
+ }
+
+ return NULL;
+}
+
/** Read the contents of a ServerTransportPlugin line from
* <b>line</b>. Return 0 if the line is well-formed, and -1 if it
* isn't.
diff --git a/src/or/config.h b/src/or/config.h
index c35214cd02..16a8a350d5 100644
--- a/src/or/config.h
+++ b/src/or/config.h
@@ -112,6 +112,21 @@ typedef struct bridge_line_t {
void bridge_line_free(bridge_line_t *bridge_line);
bridge_line_t *parse_bridge_line(const char *line);
+smartlist_t *get_options_from_transport_options_line(const char *line,
+ const char *transport);
+smartlist_t *get_options_for_server_transport(const char *transport);
+
+#ifdef CONFIG_PRIVATE
+#ifdef TOR_UNIT_TESTS
+extern struct config_format_t options_format;
+#endif
+
+STATIC void or_options_free(or_options_t *options);
+STATIC int options_validate(or_options_t *old_options,
+ or_options_t *options,
+ or_options_t *default_options,
+ int from_setconf, char **msg);
+#endif
#endif
diff --git a/src/or/confparse.c b/src/or/confparse.c
index eb0362f494..41055791ef 100644
--- a/src/or/confparse.c
+++ b/src/or/confparse.c
@@ -1126,20 +1126,36 @@ static struct unit_table_t memory_units[] = {
{ "kbytes", 1<<10 },
{ "kilobyte", 1<<10 },
{ "kilobytes", 1<<10 },
+ { "kilobits", 1<<7 },
+ { "kilobit", 1<<7 },
+ { "kbits", 1<<7 },
+ { "kbit", 1<<7 },
{ "m", 1<<20 },
{ "mb", 1<<20 },
{ "mbyte", 1<<20 },
{ "mbytes", 1<<20 },
{ "megabyte", 1<<20 },
{ "megabytes", 1<<20 },
+ { "megabits", 1<<17 },
+ { "megabit", 1<<17 },
+ { "mbits", 1<<17 },
+ { "mbit", 1<<17 },
{ "gb", 1<<30 },
{ "gbyte", 1<<30 },
{ "gbytes", 1<<30 },
{ "gigabyte", 1<<30 },
{ "gigabytes", 1<<30 },
+ { "gigabits", 1<<27 },
+ { "gigabit", 1<<27 },
+ { "gbits", 1<<27 },
+ { "gbit", 1<<27 },
{ "tb", U64_LITERAL(1)<<40 },
{ "terabyte", U64_LITERAL(1)<<40 },
{ "terabytes", U64_LITERAL(1)<<40 },
+ { "terabits", U64_LITERAL(1)<<37 },
+ { "terabit", U64_LITERAL(1)<<37 },
+ { "tbits", U64_LITERAL(1)<<37 },
+ { "tbit", U64_LITERAL(1)<<37 },
{ NULL, 0 },
};
diff --git a/src/or/confparse.h b/src/or/confparse.h
index d82e1096ca..924ee0d945 100644
--- a/src/or/confparse.h
+++ b/src/or/confparse.h
@@ -76,7 +76,7 @@ typedef int (*validate_fn_t)(void*,void*,int,char**);
/** Information on the keys, value types, key-to-struct-member mappings,
* variable descriptions, validation functions, and abbreviations for a
* configuration or storage format. */
-typedef struct {
+typedef struct config_format_t {
size_t size; /**< Size of the struct that everything gets parsed into. */
uint32_t magic; /**< Required 'magic value' to make sure we have a struct
* of the right type. */
diff --git a/src/or/dns.c b/src/or/dns.c
index edcf92e5b3..f2b7eecc3f 100644
--- a/src/or/dns.c
+++ b/src/or/dns.c
@@ -437,8 +437,8 @@ cached_resolve_add_answer(cached_resolve_t *resolve,
if (resolve->res_status_ipv4 != RES_STATUS_INFLIGHT)
return;
- if (dns_result == DNS_ERR_NONE && answer_addr) {
- tor_assert(tor_addr_family(answer_addr) == AF_INET);
+ if (dns_result == DNS_ERR_NONE && answer_addr &&
+ tor_addr_family(answer_addr) == AF_INET) {
resolve->result_ipv4.addr_ipv4 = tor_addr_to_ipv4h(answer_addr);
resolve->res_status_ipv4 = RES_STATUS_DONE_OK;
} else {
@@ -450,8 +450,8 @@ cached_resolve_add_answer(cached_resolve_t *resolve,
if (resolve->res_status_ipv6 != RES_STATUS_INFLIGHT)
return;
- if (dns_result == DNS_ERR_NONE && answer_addr) {
- tor_assert(tor_addr_family(answer_addr) == AF_INET6);
+ if (dns_result == DNS_ERR_NONE && answer_addr &&
+ tor_addr_family(answer_addr) == AF_INET6) {
memcpy(&resolve->result_ipv6.addr_ipv6,
tor_addr_to_in6(answer_addr),
sizeof(struct in6_addr));
diff --git a/src/or/or.h b/src/or/or.h
index 568958d61f..06363fa360 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -99,6 +99,7 @@
#include "ht.h"
#include "replaycache.h"
#include "crypto_curve25519.h"
+#include "tor_queue.h"
/* These signals are defined to help handle_control_signal work.
*/
@@ -1083,7 +1084,8 @@ typedef struct var_cell_t {
/** A cell as packed for writing to the network. */
typedef struct packed_cell_t {
- struct packed_cell_t *next; /**< Next cell queued on this circuit. */
+ /** Next cell queued on this circuit. */
+ TOR_SIMPLEQ_ENTRY(packed_cell_t) next;
char body[CELL_MAX_NETWORK_SIZE]; /**< Cell as packed for network. */
} packed_cell_t;
@@ -1105,8 +1107,8 @@ typedef struct insertion_time_queue_t {
/** A queue of cells on a circuit, waiting to be added to the
* or_connection_t's outbuf. */
typedef struct cell_queue_t {
- packed_cell_t *head; /**< The first cell, or NULL if the queue is empty. */
- packed_cell_t *tail; /**< The last cell, or NULL if the queue is empty. */
+ /** Linked list of packed_cell_t*/
+ TOR_SIMPLEQ_HEAD(cell_simpleq, packed_cell_t) head;
int n; /**< The number of cells in the queue. */
insertion_time_queue_t *insertion_times; /**< Insertion times of cells. */
} cell_queue_t;
@@ -3500,6 +3502,9 @@ typedef struct {
/** List of TCP/IP addresses that transports should listen at. */
config_line_t *ServerTransportListenAddr;
+ /** List of options that must be passed to pluggable transports. */
+ config_line_t *ServerTransportOptions;
+
int BridgeRelay; /**< Boolean: are we acting as a bridge relay? We make
* this explicit so we can change how we behave in the
* future. */
diff --git a/src/or/relay.c b/src/or/relay.c
index 7ec7e03024..297f0f69e0 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -2089,7 +2089,7 @@ packed_cell_free_unchecked(packed_cell_t *cell)
}
/** Allocate and return a new packed_cell_t. */
-static INLINE packed_cell_t *
+STATIC packed_cell_t *
packed_cell_new(void)
{
++total_cells_allocated;
@@ -2100,6 +2100,8 @@ packed_cell_new(void)
void
packed_cell_free(packed_cell_t *cell)
{
+ if (!cell)
+ return;
packed_cell_free_unchecked(cell);
}
@@ -2129,7 +2131,6 @@ packed_cell_copy(const cell_t *cell, int wide_circ_ids)
{
packed_cell_t *c = packed_cell_new();
cell_pack(c, cell, wide_circ_ids);
- c->next = NULL;
return c;
}
@@ -2137,14 +2138,7 @@ packed_cell_copy(const cell_t *cell, int wide_circ_ids)
void
cell_queue_append(cell_queue_t *queue, packed_cell_t *cell)
{
- if (queue->tail) {
- tor_assert(!queue->tail->next);
- queue->tail->next = cell;
- } else {
- queue->head = cell;
- }
- queue->tail = cell;
- cell->next = NULL;
+ TOR_SIMPLEQ_INSERT_TAIL(&queue->head, cell, next);
++queue->n;
}
@@ -2187,18 +2181,24 @@ cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell,
cell_queue_append(queue, copy);
}
+/** Initialize <b>queue</b> as an empty cell queue. */
+void
+cell_queue_init(cell_queue_t *queue)
+{
+ memset(queue, 0, sizeof(cell_queue_t));
+ TOR_SIMPLEQ_INIT(&queue->head);
+}
+
/** Remove and free every cell in <b>queue</b>. */
void
cell_queue_clear(cell_queue_t *queue)
{
- packed_cell_t *cell, *next;
- cell = queue->head;
- while (cell) {
- next = cell->next;
+ packed_cell_t *cell;
+ while ((cell = TOR_SIMPLEQ_FIRST(&queue->head))) {
+ TOR_SIMPLEQ_REMOVE_HEAD(&queue->head, next);
packed_cell_free_unchecked(cell);
- cell = next;
}
- queue->head = queue->tail = NULL;
+ TOR_SIMPLEQ_INIT(&queue->head);
queue->n = 0;
if (queue->insertion_times) {
while (queue->insertion_times->first) {
@@ -2212,17 +2212,13 @@ cell_queue_clear(cell_queue_t *queue)
/** Extract and return the cell at the head of <b>queue</b>; return NULL if
* <b>queue</b> is empty. */
-static INLINE packed_cell_t *
+STATIC packed_cell_t *
cell_queue_pop(cell_queue_t *queue)
{
- packed_cell_t *cell = queue->head;
+ packed_cell_t *cell = TOR_SIMPLEQ_FIRST(&queue->head);
if (!cell)
return NULL;
- queue->head = cell->next;
- if (cell == queue->tail) {
- tor_assert(!queue->head);
- queue->tail = NULL;
- }
+ TOR_SIMPLEQ_REMOVE_HEAD(&queue->head, next);
--queue->n;
return cell;
}
diff --git a/src/or/relay.h b/src/or/relay.h
index 4be3194e5b..e1b5e381ed 100644
--- a/src/or/relay.h
+++ b/src/or/relay.h
@@ -51,6 +51,7 @@ size_t packed_cell_mem_cost(void);
/* For channeltls.c */
void packed_cell_free(packed_cell_t *cell);
+void cell_queue_init(cell_queue_t *queue);
void cell_queue_clear(cell_queue_t *queue);
void cell_queue_append(cell_queue_t *queue, packed_cell_t *cell);
void cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell,
@@ -81,6 +82,8 @@ int relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction,
#ifdef RELAY_PRIVATE
STATIC int connected_cell_parse(const relay_header_t *rh, const cell_t *cell,
tor_addr_t *addr_out, int *ttl_out);
+STATIC packed_cell_t *packed_cell_new(void);
+STATIC packed_cell_t *cell_queue_pop(cell_queue_t *queue);
#endif
#endif
diff --git a/src/or/transports.c b/src/or/transports.c
index 0bd024fab7..62cc1a864f 100644
--- a/src/or/transports.c
+++ b/src/or/transports.c
@@ -102,9 +102,6 @@ create_managed_proxy_environment(const managed_proxy_t *mp);
static INLINE int proxy_configuration_finished(const managed_proxy_t *mp);
-static void managed_proxy_destroy(managed_proxy_t *mp,
- int also_terminate_process);
-
static void handle_finished_proxy(managed_proxy_t *mp);
static void parse_method_error(const char *line, int is_server_method);
#define parse_server_method_error(l) parse_method_error(l, 1)
@@ -135,7 +132,8 @@ static smartlist_t *transport_list = NULL;
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)
+ const char *name, int socks_ver,
+ const char *extra_info_args)
{
transport_t *t = tor_malloc_zero(sizeof(transport_t));
@@ -143,6 +141,8 @@ transport_new(const tor_addr_t *addr, uint16_t port,
t->port = port;
t->name = tor_strdup(name);
t->socks_version = socks_ver;
+ if (extra_info_args)
+ t->extra_info_args = tor_strdup(extra_info_args);
return t;
}
@@ -155,6 +155,7 @@ transport_free(transport_t *transport)
return;
tor_free(transport->name);
+ tor_free(transport->extra_info_args);
tor_free(transport);
}
@@ -322,7 +323,7 @@ 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);
+ transport_t *t = transport_new(addr, port, name, socks_ver, NULL);
int r = transport_add(t);
@@ -698,7 +699,7 @@ register_proxy(const managed_proxy_t *mp)
}
/** Free memory allocated by managed proxy <b>mp</b>. */
-static void
+STATIC void
managed_proxy_destroy(managed_proxy_t *mp,
int also_terminate_process)
{
@@ -945,7 +946,7 @@ parse_smethod_line(const char *line, managed_proxy_t *mp)
smartlist_t *items = NULL;
char *method_name=NULL;
-
+ char *args_string=NULL;
char *addrport=NULL;
tor_addr_t tor_addr;
char *address=NULL;
@@ -962,6 +963,9 @@ parse_smethod_line(const char *line, managed_proxy_t *mp)
goto err;
}
+ /* Example of legit SMETHOD line:
+ SMETHOD obfs2 0.0.0.0:25612 ARGS:secret=supersekrit,key=superkey */
+
tor_assert(!strcmp(smartlist_get(items,0),PROTO_SMETHOD));
method_name = smartlist_get(items,1);
@@ -989,7 +993,19 @@ parse_smethod_line(const char *line, managed_proxy_t *mp)
goto err;
}
- transport = transport_new(&tor_addr, port, method_name, PROXY_NONE);
+ if (smartlist_len(items) > 3) {
+ /* Seems like there are also some [options] in the SMETHOD line.
+ Let's see if we can parse them. */
+ char *options_string = smartlist_get(items, 3);
+ log_debug(LD_CONFIG, "Got options_string: %s", options_string);
+ if (!strcmpstart(options_string, "ARGS:")) {
+ args_string = options_string+strlen("ARGS:");
+ log_debug(LD_CONFIG, "Got ARGS: %s", args_string);
+ }
+ }
+
+ transport = transport_new(&tor_addr, port, method_name,
+ PROXY_NONE, args_string);
if (!transport)
goto err;
@@ -1081,7 +1097,7 @@ parse_cmethod_line(const char *line, managed_proxy_t *mp)
goto err;
}
- transport = transport_new(&tor_addr, port, method_name, socks_ver);
+ transport = transport_new(&tor_addr, port, method_name, socks_ver, NULL);
if (!transport)
goto err;
@@ -1104,6 +1120,50 @@ parse_cmethod_line(const char *line, managed_proxy_t *mp)
return r;
}
+/** Return a newly allocated string that tor should place in
+ * TOR_PT_SERVER_TRANSPORT_OPTIONS while configuring the server
+ * manged proxy in <b>mp</b>. Return NULL if no such options are found. */
+STATIC char *
+get_transport_options_for_server_proxy(const managed_proxy_t *mp)
+{
+ char *options_string = NULL;
+ smartlist_t *string_sl = smartlist_new();
+
+ tor_assert(mp->is_server);
+
+ /** Loop over the transports of the proxy. If we have options for
+ any of them, format them appropriately and place them in our
+ smartlist. Finally, join our smartlist to get the final
+ string. */
+ SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, const char *, transport) {
+ smartlist_t *options_tmp_sl = NULL;
+ options_tmp_sl = get_options_for_server_transport(transport);
+ if (!options_tmp_sl)
+ continue;
+
+ /** Loop over the options of this transport, escape them, and
+ place them in the smartlist. */
+ SMARTLIST_FOREACH_BEGIN(options_tmp_sl, const char *, options) {
+ char *escaped_opts = tor_escape_str_for_pt_args(options, ":;\\");
+ smartlist_add_asprintf(string_sl, "%s:%s",
+ transport, escaped_opts);
+ tor_free(escaped_opts);
+ } SMARTLIST_FOREACH_END(options);
+
+ SMARTLIST_FOREACH(options_tmp_sl, char *, c, tor_free(c));
+ smartlist_free(options_tmp_sl);
+ } SMARTLIST_FOREACH_END(transport);
+
+ if (smartlist_len(string_sl)) {
+ options_string = smartlist_join_strings(string_sl, ";", 0, NULL);
+ }
+
+ SMARTLIST_FOREACH(string_sl, char *, t, tor_free(t));
+ smartlist_free(string_sl);
+
+ return options_string;
+}
+
/** Return the string that tor should place in TOR_PT_SERVER_BINDADDR
* while configuring the server managed proxy in <b>mp</b>. The
* string is stored in the heap, and it's the the responsibility of
@@ -1185,6 +1245,16 @@ create_managed_proxy_environment(const managed_proxy_t *mp)
tor_free(bindaddr_tmp);
}
+ {
+ char *server_transport_options =
+ get_transport_options_for_server_proxy(mp);
+ if (server_transport_options) {
+ smartlist_add_asprintf(envs, "TOR_PT_SERVER_TRANSPORT_OPTIONS=%s",
+ server_transport_options);
+ tor_free(server_transport_options);
+ }
+ }
+
/* XXX024 Remove the '=' here once versions of obfsproxy which
* assert that this env var exists are sufficiently dead.
*
@@ -1215,7 +1285,7 @@ create_managed_proxy_environment(const managed_proxy_t *mp)
* <b>proxy_argv</b>.
*
* Requires that proxy_argv have at least one element. */
-static managed_proxy_t *
+STATIC managed_proxy_t *
managed_proxy_create(const smartlist_t *transport_list,
char **proxy_argv, int is_server)
{
@@ -1389,6 +1459,8 @@ pt_get_extra_info_descriptor_string(void)
tor_assert(mp->transports);
SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
+ char *transport_args = NULL;
+
/* 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. */
@@ -1404,9 +1476,16 @@ pt_get_extra_info_descriptor_string(void)
addrport = fmt_addrport(&t->addr, t->port);
}
+ /* If this transport has any arguments with it, prepend a space
+ to them so that we can add them to the transport line. */
+ if (t->extra_info_args)
+ tor_asprintf(&transport_args, " %s", t->extra_info_args);
+
smartlist_add_asprintf(string_chunks,
- "transport %s %s",
- t->name, addrport);
+ "transport %s %s%s",
+ t->name, addrport,
+ transport_args ? transport_args : "");
+ tor_free(transport_args);
} SMARTLIST_FOREACH_END(t);
} SMARTLIST_FOREACH_END(mp);
@@ -1444,7 +1523,7 @@ pt_stringify_socks_args(const smartlist_t *socks_args)
SMARTLIST_FOREACH_BEGIN(socks_args, const char *, s) {
/* Escape ';' and '\'. */
- escaped_string = tor_escape_str_for_socks_arg(s);
+ escaped_string = tor_escape_str_for_pt_args(s, ";\\");
if (!escaped_string)
goto done;
diff --git a/src/or/transports.h b/src/or/transports.h
index 7f180a67b9..7b524f2073 100644
--- a/src/or/transports.h
+++ b/src/or/transports.h
@@ -25,6 +25,9 @@ typedef struct transport_t {
/** 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;
+ /** Arguments for this transport that must be written to the
+ extra-info descriptor. */
+ char *extra_info_args;
} transport_t;
void mark_transport_list(void);
@@ -110,6 +113,13 @@ STATIC int parse_smethod_line(const char *line, managed_proxy_t *mp);
STATIC int parse_version(const char *line, managed_proxy_t *mp);
STATIC void parse_env_error(const char *line);
STATIC void handle_proxy_line(const char *line, managed_proxy_t *mp);
+STATIC char *get_transport_options_for_server_proxy(const managed_proxy_t *mp);
+
+STATIC void managed_proxy_destroy(managed_proxy_t *mp,
+ int also_terminate_process);
+
+STATIC managed_proxy_t *managed_proxy_create(const smartlist_t *transport_list,
+ char **proxy_argv, int is_server);
STATIC int configure_proxy(managed_proxy_t *mp);