Selaa lähdekoodia

Make option OutboundBindAddress accept IPv6 addresses too.

Implements ticket 6786.
Linus Nordberg 11 vuotta sitten
vanhempi
commit
1cbf45bed1
4 muutettua tiedostoa jossa 103 lisäystä ja 21 poistoa
  1. 4 2
      doc/tor.1.txt
  2. 66 1
      src/or/config.c
  3. 28 17
      src/or/connection.c
  4. 5 1
      src/or/or.h

+ 4 - 2
doc/tor.1.txt

@@ -472,8 +472,10 @@ GENERAL OPTIONS
 **OutboundBindAddress** __IP__::
 **OutboundBindAddress** __IP__::
     Make all outbound connections originate from the IP address specified. This
     Make all outbound connections originate from the IP address specified. This
     is only useful when you have multiple network interfaces, and you want all
     is only useful when you have multiple network interfaces, and you want all
-    of Tor's outgoing connections to use a single one.  This setting will be
-    ignored for connections to the loopback addresses (127.0.0.0/8 and ::1).
+    of Tor's outgoing connections to use a single one. This option may
+    be used twice, once with an IPv4 address and once with an IPv6 address.
+    This setting will be ignored for connections to the loopback addresses
+    (127.0.0.0/8 and ::1).
 
 
 **PidFile** __FILE__::
 **PidFile** __FILE__::
     On startup, write our PID to FILE. On clean shutdown, remove
     On startup, write our PID to FILE. On clean shutdown, remove

+ 66 - 1
src/or/config.c

@@ -302,7 +302,7 @@ static config_var_t _option_vars[] = {
   V(NumEntryGuards,              UINT,     "3"),
   V(NumEntryGuards,              UINT,     "3"),
   V(ORListenAddress,             LINELIST, NULL),
   V(ORListenAddress,             LINELIST, NULL),
   VPORT(ORPort,                      LINELIST, NULL),
   VPORT(ORPort,                      LINELIST, NULL),
-  V(OutboundBindAddress,         STRING,   NULL),
+  V(OutboundBindAddress,         LINELIST,   NULL),
 
 
   V(PathBiasCircThreshold,       INT,      "-1"),
   V(PathBiasCircThreshold,       INT,      "-1"),
   V(PathBiasNoticeRate,          DOUBLE,   "-1"),
   V(PathBiasNoticeRate,          DOUBLE,   "-1"),
@@ -474,6 +474,8 @@ static int options_init_logs(or_options_t *options, int validate_only);
 
 
 static void init_libevent(const or_options_t *options);
 static void init_libevent(const or_options_t *options);
 static int opt_streq(const char *s1, const char *s2);
 static int opt_streq(const char *s1, const char *s2);
+static int parse_outbound_addresses(or_options_t *options, int validate_only,
+                                    char **msg);
 
 
 /** Magic value for or_options_t. */
 /** Magic value for or_options_t. */
 #define OR_OPTIONS_MAGIC 9090909
 #define OR_OPTIONS_MAGIC 9090909
@@ -1390,6 +1392,12 @@ options_act(const or_options_t *old_options)
     tor_free(http_authenticator);
     tor_free(http_authenticator);
   }
   }
 
 
+  if (parse_outbound_addresses(options, 0, &msg) < 0) {
+    log_warn(LD_BUG, "Failed parsing oubound bind addresses: %s", msg);
+    tor_free(msg);
+    return -1;
+  }
+
   /* Check for transitions that need action. */
   /* Check for transitions that need action. */
   if (old_options) {
   if (old_options) {
     int revise_trackexithosts = 0;
     int revise_trackexithosts = 0;
@@ -2164,6 +2172,9 @@ options_validate(or_options_t *old_options, or_options_t *options,
   if (parse_ports(options, 1, msg, &n_ports) < 0)
   if (parse_ports(options, 1, msg, &n_ports) < 0)
     return -1;
     return -1;
 
 
+  if (parse_outbound_addresses(options, 1, msg) < 0)
+    return -1;
+
   if (validate_data_directory(options)<0)
   if (validate_data_directory(options)<0)
     REJECT("Invalid DataDirectory");
     REJECT("Invalid DataDirectory");
 
 
@@ -5482,3 +5493,57 @@ getinfo_helper_config(control_connection_t *conn,
   return 0;
   return 0;
 }
 }
 
 
+/** Parse outbound bind address option lines. If <b>validate_only</b>
+ * is not 0 update _OutboundBindAddressIPv4 and
+ * _OutboundBindAddressIPv6 in <b>options</b>. On failure, set
+ * <b>msg</b> (if provided) to a newly allocated string containing a
+ * description of the problem and return -1. */
+static int
+parse_outbound_addresses(or_options_t *options, int validate_only, char **msg)
+{
+  const config_line_t *lines = options->OutboundBindAddress;
+  int found_v4 = 0, found_v6 = 0;
+
+  if (!validate_only) {
+    memset(&options->_OutboundBindAddressIPv4, 0,
+           sizeof(options->_OutboundBindAddressIPv4));
+    memset(&options->_OutboundBindAddressIPv6, 0,
+           sizeof(options->_OutboundBindAddressIPv6));
+  }
+  while (lines) {
+    tor_addr_t addr, *dst_addr = NULL;
+    int af = tor_addr_parse(&addr, lines->value);
+    switch (af) {
+    case AF_INET:
+      if (found_v4) {
+        if (msg)
+          tor_asprintf(msg, "Multiple IPv4 outbound bind addresses "
+                       "configured: %s", lines->value);
+        return -1;
+      }
+      found_v4 = 1;
+      dst_addr = &options->_OutboundBindAddressIPv4;
+      break;
+    case AF_INET6:
+      if (found_v6) {
+        if (msg)
+          tor_asprintf(msg, "Multiple IPv6 outbound bind addresses "
+                       "configured: %s", lines->value);
+        return -1;
+      }
+      found_v6 = 1;
+      dst_addr = &options->_OutboundBindAddressIPv6;
+      break;
+    default:
+      if (msg)
+        tor_asprintf(msg, "Outbound bind address '%s' didn't parse.",
+                     lines->value);
+      return -1;
+    }
+    if (!validate_only)
+      tor_addr_copy(dst_addr, &addr);
+    lines = lines->next;
+  }
+  return 0;
+}
+

+ 28 - 17
src/or/connection.c

@@ -1377,23 +1377,34 @@ connection_connect(connection_t *conn, const char *address,
 
 
   make_socket_reuseable(s);
   make_socket_reuseable(s);
 
 
-  if (options->OutboundBindAddress && !tor_addr_is_loopback(addr)) {
-    struct sockaddr_in ext_addr;
-
-    memset(&ext_addr, 0, sizeof(ext_addr));
-    ext_addr.sin_family = AF_INET;
-    ext_addr.sin_port = 0;
-    if (!tor_inet_aton(options->OutboundBindAddress, &ext_addr.sin_addr)) {
-      log_warn(LD_CONFIG,"Outbound bind address '%s' didn't parse. Ignoring.",
-               options->OutboundBindAddress);
-    } else {
-      if (bind(s, (struct sockaddr*)&ext_addr,
-               (socklen_t)sizeof(ext_addr)) < 0) {
-        *socket_error = tor_socket_errno(s);
-        log_warn(LD_NET,"Error binding network socket: %s",
-                 tor_socket_strerror(*socket_error));
-        tor_close_socket(s);
-        return -1;
+  if (!tor_addr_is_loopback(addr)) {
+    const tor_addr_t *ext_addr = NULL;
+    if (protocol_family == AF_INET &&
+        !tor_addr_is_null(&options->_OutboundBindAddressIPv4))
+      ext_addr = &options->_OutboundBindAddressIPv4;
+    else if (protocol_family == AF_INET6 &&
+             !tor_addr_is_null(&options->_OutboundBindAddressIPv6))
+      ext_addr = &options->_OutboundBindAddressIPv6;
+    if (ext_addr) {
+      struct sockaddr_storage ext_addr_sa;
+      socklen_t ext_addr_len = 0;
+      memset(&ext_addr_sa, 0, sizeof(ext_addr_sa));
+      ext_addr_len = tor_addr_to_sockaddr(ext_addr, 0,
+                                          (struct sockaddr *) &ext_addr_sa,
+                                          sizeof(ext_addr_sa));
+      if (ext_addr_len == 0) {
+        log_warn(LD_NET,
+                 "Error converting OutboundBindAddress %s into sockaddr. "
+                 "Ignoring.", fmt_addr(ext_addr));
+      } else {
+        if (bind(s, (struct sockaddr *) &ext_addr_sa, ext_addr_len) < 0) {
+          *socket_error = tor_socket_errno(s);
+          log_warn(LD_NET,"Error binding network socket to %s: %s",
+                   fmt_addr(ext_addr),
+                   tor_socket_strerror(*socket_error));
+          tor_close_socket(s);
+          return -1;
+        }
       }
       }
     }
     }
   }
   }

+ 5 - 1
src/or/or.h

@@ -3028,7 +3028,11 @@ typedef struct {
   /** Addresses to bind for listening for control connections. */
   /** Addresses to bind for listening for control connections. */
   config_line_t *ControlListenAddress;
   config_line_t *ControlListenAddress;
   /** Local address to bind outbound sockets */
   /** Local address to bind outbound sockets */
-  char *OutboundBindAddress;
+  config_line_t *OutboundBindAddress;
+  /** IPv4 address derived from OutboundBindAddress. */
+  tor_addr_t _OutboundBindAddressIPv4;
+  /** IPv6 address derived from OutboundBindAddress. */
+  tor_addr_t _OutboundBindAddressIPv6;
   /** Directory server only: which versions of
   /** Directory server only: which versions of
    * Tor should we tell users to run? */
    * Tor should we tell users to run? */
   config_line_t *RecommendedVersions;
   config_line_t *RecommendedVersions;