[tor-commits] [tor/master] Add a torrc option to specify the bind address of managed proxies.

nickm at torproject.org nickm at torproject.org
Wed Nov 28 03:31:48 UTC 2012


commit f88c3038697b00f50b2da12f46fc76ee0e20d646
Author: George Kadianakis <desnacked at riseup.net>
Date:   Tue Oct 30 04:17:13 2012 +0200

    Add a torrc option to specify the bind address of managed proxies.
---
 changes/bug7013    |    4 ++
 doc/tor.1.txt      |    5 +++
 src/or/config.c    |  101 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/or/config.h    |    2 +
 src/or/or.h        |    3 ++
 src/or/statefile.c |   11 +++++-
 6 files changed, 125 insertions(+), 1 deletions(-)

diff --git a/changes/bug7013 b/changes/bug7013
new file mode 100644
index 0000000..ba78520
--- /dev/null
+++ b/changes/bug7013
@@ -0,0 +1,4 @@
+  o Minor features:
+    - Add a new torrc option 'ServerTransportListenAddr' which allows
+      users to select the address where their pluggable transports
+      will listen for connections.
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 8245ff4..9eb3745 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -181,6 +181,11 @@ GENERAL OPTIONS
     using __options__ as its command-line options, and expects to receive
     proxied client traffic from it.
 
+**ServerTransportListenAddr** __transport__ __IP__:__PORT__::
+    When this option is set, Tor will suggest __IP__:__PORT__ as the
+    listening address of any pluggable transport proxy that tries to
+    launch __transport__.
+
 **ConnLimit** __NUM__::
     The minimum number of file descriptors that must be available to the Tor
     process before it will start. Tor will ask the OS for as many file
diff --git a/src/or/config.c b/src/or/config.c
index 6eace9f..822bc62 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -273,6 +273,7 @@ static config_var_t option_vars_[] = {
   V(HTTPSProxy,                  STRING,   NULL),
   V(HTTPSProxyAuthenticator,     STRING,   NULL),
   VAR("ServerTransportPlugin",   LINELIST, ServerTransportPlugin,  NULL),
+  V(ServerTransportListenAddr,   LINELIST, NULL),
   V(Socks4Proxy,                 STRING,   NULL),
   V(Socks5Proxy,                 STRING,   NULL),
   V(Socks5ProxyUsername,         STRING,   NULL),
@@ -462,6 +463,9 @@ static int parse_bridge_line(const char *line, int validate_only);
 static int parse_client_transport_line(const char *line, int validate_only);
 
 static int parse_server_transport_line(const char *line, int validate_only);
+static char *get_bindaddr_from_transport_listen_line(const char *line,
+                                                     const char *transport);
+
 static int parse_dir_server_line(const char *line,
                                  dirinfo_type_t required_type,
                                  int validate_only);
@@ -2879,6 +2883,22 @@ options_validate(or_options_t *old_options, or_options_t *options,
                escaped(options->ServerTransportPlugin->value));
   }
 
+  for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
+    /** If get_bindaddr_from_transport_listen_line() fails with
+        'transport' being NULL, it means that something went wrong
+        while parsing the ServerTransportListenAddr line. */
+    char *bindaddr = get_bindaddr_from_transport_listen_line(cl->value, NULL);
+    if (!bindaddr)
+      REJECT("ServerTransportListenAddr did not parse. See logs for details.");
+    tor_free(bindaddr);
+  }
+
+  if (options->ServerTransportListenAddr && !options->ServerTransportPlugin) {
+    log_notice(LD_GENERAL, "You need at least a single managed-proxy to "
+               "specify a transport listen address. The "
+               "ServerTransportListenAddr line will be ignored.");
+  }
+
   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. */
@@ -4117,6 +4137,87 @@ parse_client_transport_line(const char *line, int validate_only)
   return r;
 }
 
+/** Given a ServerTransportListenAddr <b>line</b>, return its
+ *  <address:port> string. 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 string is allocated on the heap and it's the
+ *  responsibility of the caller to free it. */
+static char *
+get_bindaddr_from_transport_listen_line(const char *line,const char *transport)
+{
+  smartlist_t *items = NULL;
+  const char *parsed_transport = NULL;
+  char *addrport = NULL;
+  char *addr = NULL;
+  uint16_t port = 0;
+
+  items = smartlist_new();
+  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 ServerTransportListenAddr line.");
+    goto err;
+  }
+
+  parsed_transport = smartlist_get(items, 0);
+  addrport = tor_strdup(smartlist_get(items, 1));
+
+  /* If 'transport' is given, check if it matches the one on the line */
+  if (transport && strcmp(transport, parsed_transport))
+    goto err;
+
+  /* Validate addrport */
+  if (tor_addr_port_split(LOG_WARN, addrport, &addr, &port)<0) {
+    log_warn(LD_CONFIG, "Error parsing ServerTransportListenAddr "
+             "address '%s'", addrport);
+    goto err;
+  }
+
+  if (!port) {
+    log_warn(LD_CONFIG,
+             "ServerTransportListenAddr address '%s' has no port.", addrport);
+    goto err;
+  }
+
+  goto done;
+
+ err:
+  tor_free(addrport);
+  addrport = NULL;
+
+ done:
+  SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+  smartlist_free(items);
+  tor_free(addr);
+
+  return addrport;
+}
+
+/** 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
+ *  so, otherwise NULL. */
+char *
+get_transport_bindaddr_from_config(const char *transport)
+{
+  config_line_t *cl;
+  const or_options_t *options = get_options();
+
+  for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
+    char *bindaddr =
+      get_bindaddr_from_transport_listen_line(cl->value, transport);
+    if (bindaddr)
+      return bindaddr;
+  }
+
+  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 f3b28ad..336685d 100644
--- a/src/or/config.h
+++ b/src/or/config.h
@@ -82,6 +82,8 @@ const char *tor_get_digests(void);
 uint32_t get_effective_bwrate(const or_options_t *options);
 uint32_t get_effective_bwburst(const or_options_t *options);
 
+char *get_transport_bindaddr_from_config(const char *transport);
+
 #ifdef CONFIG_PRIVATE
 /* Used only by config.c and test.c */
 or_options_t *options_new(void);
diff --git a/src/or/or.h b/src/or/or.h
index b59c079..82e847a 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3218,6 +3218,9 @@ typedef struct {
   config_line_t *ServerTransportPlugin; /**< List of client
                                            transport plugins. */
 
+  /** List of TCP/IP addresses that transports should listen at. */
+  config_line_t *ServerTransportListenAddr;
+
   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/statefile.c b/src/or/statefile.c
index beb9cf8..704c4e5 100644
--- a/src/or/statefile.c
+++ b/src/or/statefile.c
@@ -517,8 +517,17 @@ get_stored_bindaddr_for_server_transport(const char *transport)
 {
   char *default_addrport = NULL;
   const char *stored_bindaddr = NULL;
+  config_line_t *line = NULL;
+
+  {
+    /* See if the user explicitly asked for a specific listening
+       address for this transport. */
+    char *conf_bindaddr = get_transport_bindaddr_from_config(transport);
+    if (conf_bindaddr)
+      return conf_bindaddr;
+  }
 
-  config_line_t *line = get_transport_in_state_by_name(transport);
+  line = get_transport_in_state_by_name(transport);
   if (!line) /* Found no references in state for this transport. */
     goto no_bindaddr_found;
 





More information about the tor-commits mailing list